alokacja i przepisanie pliku do tablicy

0

Witam. Mam takie zadanko do zrobienia:

Napisz program, który otwiera do odczytu plik lec.txt, który zawiera 26 przykładowych wierszy tekstu różnej długości.
Program powinien wywoływać funkcję alokuj_tab_str(), która pobiera wskaźnik plikowy. Funkcja
alokuj_tab_str() powinna alokować pamięć dla tablicy 26 wierszy znaków (char) o długości o jeden większej
od liczby znaków w kolejnych wierszach pliku. W tym celu funkcja alokuj_tab_str() powinna zliczać liczbę
znaków w wierszu (bez znaku nowej linii) i alokować odpowiedni blok pamięci. Następnie funkcja powinna
odczytywać kolejne wiersze pliku znak po znaku i zapisywać je w odpowiednich wierszach tablicy, dodając po
ostatnim znaku odczytanego wiersza znak NULL (\0). Funkcja alokuj_tab_str() powinna zwracać wskaźnik do
tak stworzonej tablicy łańcuchów. W dalszej kolejności program powinien wypisywać kolejne wiersze tablicy
używając funkcji puts() i dealokować przydzieloną pamięć.

Napisałem cos takiego ale nie moge znaleŹĆ bledów a troche juz na dtm siedze . Prosze o wskazówki jeśli ma ktos chwilke.

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define BUFF 100
char **alokuj_tab_str(char *s)
{
    int dl;
    char p[BUFF];
    char **tab;
    tab=(char**)malloc(26*sizeof(char*));
    FILE *in;
    int i=0;
    if((in=fopen(s,"r")==NULL))
    {
        printf("%s","Blad otwarcia pliku");
        return 0;
    }

    while(fgets(p, BUFF, in)){
        dl=strlen(p);
        tab[i]=(char *)malloc((dl+1)*sizeof(char));
        sprintf(tab[i],"%s\0",p);
        i++;

    }
    fclose(in);
    return tab; 

}
int main(int argc, char *argv[]) {
    int i;
    char **tab;
    tab=alokuj_tab_str("c:\\users\\jo\\desktop\\sesja\\9\\plik.txt");
    if(tab==NULL)return 0;

    for(i=0;i<26;i++)
    {
        puts(tab[i]);
    }
    return 0;
} 
0

To mi wygląda na standardowe ćwiczenie z wykorzystaniem realloc, nawiasem mówiąc dosyć przydatnej funkcji:

#include <stdio.h>
#include <stdlib.h>

void odczytaj(char *tab[26]){
    FILE *plik = fopen("tekst.txt","rt");
    if(plik){
        char znak;
        int licznikZnakow = 0;
        int linia = 0;
        while((znak = fgetc(plik)) != EOF && linia < 26){
            if(znak != '\n'){
                char *temp = (char*)realloc(tab[linia],licznikZnakow * sizeof(char) + 1);
                tab[linia] = temp;
                tab[linia][licznikZnakow] = znak;
                printf("%c", tab[linia][licznikZnakow]);
                licznikZnakow++;
            }
            else{
                printf("\n");
                licznikZnakow = 0;
                linia++;
            }
        }
        fclose(plik);
    }
    else printf("Blad odczytu!\n");
}

void inicjalizuj(char *tab[26]){
    int i;
    for(i = 0; i < 26; i++)tab[i] = NULL;
}

void zniszcz(char *tab[26]){
    int i;
    for(i = 0; i < 26; i++){
        free(tab[i]);
        tab[i] = NULL;
    }
}

int main()
{
    char *tab[26];
    inicjalizuj(tab);
    odczytaj(tab);
    zniszcz(tab);
    return 0;
}

Program odczytuje plik bajt po bajcie i ciągle realokuje sobie pamięć w wybranych wierszach tablicy.
Naturalnie jest on w stanie według zadania odczytać jedynie 26 linii tekstu.

1

@Wybitny Kaczor
1) fgets wstawia \0 na końcu
2) fgets jeśli linia jest krótsza od bufora wczyta znak końca linii
3) sprintf(tab[i],"%s\0",p); - brzydkie, wykonać strcpy, albo nawet memcpy
4) żeby było ładnie

char **alokuj_tab_str(const char *s) 

5) nie zwalniasz pamięci

@grzesiek51114
1) Jeśli robić juz realloc to co najwyżej bufora wczytującego dane i nie po 1 bajcie!
2) do czytania po znaku jest funkcja fgetc

0

Kaczus,
dzieki za odpowiedz. Poprawiłem to co mowiłeś ale program nie działa poprawinie. Tzn funkcja fgets nie działa i nie przepisuje znakow z pliku do p. Nie wiem dlaczego. Funkcja zwalniajaca pamiec wywala mi program.

0

grzesiek51114,
Dziękuje za program:) ale chciałbym napisać go z uzyciam funkcji malloc, bo takiej będę musiał uzyc na egzaminie najprawdopodobniej.

0

Program wyglada tak:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define BUFF 1000
/* run this program using the console pauser or add your own getch, system("pause") or input loop */
char **alokuj_tab_str(const char *s)
{
    int dl;
    char p[BUFF];
    char **tab;
    tab=(char**)malloc(26*sizeof(char*));
    FILE *in;
    int i=0;
    if((in=fopen(s,"r")==NULL))
    {
        printf("%s","Blad otwarcia pliku");
        return 0;
    }

    while(fgets(p, BUFF, in) && i<26){
        dl=strlen(p);
        tab[i]=(char *)malloc((dl+1)*sizeof(char));
        strcpy(tab[i],p);
        i++;

    }
    fclose(in);
    return tab; 

}
int main(int argc, char *argv[]) {
    int i;
    char **tab;
    tab=alokuj_tab_str("c:\\users\\jo\\desktop\\sesja\\9\\plik.txt");
    if(tab==NULL)return 0;

    for(i=0;i<26;i++)
    {
        puts(tab[i]);

    }

    for(i=0;i<26;i++)
    {
        free(tab[i]);

    }
    free(tab);
    return 0;
} 

Co do fgets to wiem ze bufor musi byc odpowiednio duzy i jest to ograniczeniem.

0

Twoja funkcja alokuj_tab_str jest napisana bez sensu.

  • W if'ie warunek jest źle napisany: brakuje tam nawiasu i kompilator wyrzuca warninga.
  • Po co alokujesz dynamicznie główną tablicę skoro znasz z góry jej rozmiar i wiesz, że się nie zmieni?
  • co zrobisz jeżeli ilość znaków w jednej linijce będzie większy niż 1000?
  • W mainie puts i free można wykonać w jednej pętli.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define BUFF 1000
/* run this program using the console pauser or add your own getch, system("pause") or input loop */
char **alokuj_tab_str(const char *s)
{
    int dl;
    char p[BUFF];
    char **tab;
    tab=(char**)malloc(26*sizeof(char*));
    FILE *in;
    int i=0;
    if(((in=fopen(s,"r"))==NULL))
    {
        printf("%s","Blad otwarcia pliku");
        tab = NULL;
    }
    else{
        while(fgets(p, BUFF, in) && i<26){
            dl=strlen(p);
            tab[i]=(char *)malloc((dl+1)*sizeof(char));
            strcpy(tab[i],p);
            i++;
        }
        fclose(in);
    }
    return tab;

}

int main() {
    int i;
    char **tab;
    tab=alokuj_tab_str("tekst.txt");
    if(tab!=NULL){
        for(i=0;i<26;i++)
        {
            puts(tab[i]);
            free(tab[i]);
        }
        free(tab);
    }
    return 0;
}
0

-Własnie braku tego nawiasu nie zauważyłem,
-alokuje pamieć dla głownej tablicy bo pozniej musze ja zwolnic a chyba nie mozna tego zrobic jesli utworze ja statycznie,
-nieważne jest co sie stanie jak linijka bedzie dłuższa niż 1000 bo mogę dac 10000, akurat to jest nieistotne,
-wiem ze drukować i zwalniać moge razem ale gdybym napisał funkcje osobne do tego to tez by robiły to osobno,
Dzięki. Pozdrawiam:)

0

Jeżeli obiekt utworzysz na stosie to nie będziesz musiał martwić się ze zwolnieniem jego pamięci. Po co tworzyć na stercie obiekt, którego rozmiar znasz już podczas kompilacji?

Lepiej zamiast:

char **tab=(char**)malloc(26*sizeof(char*));

Zrób:

char *tab[26];

i przekazuj tego taba np. jako argument funkcji, nie tworząc obiektu chwilowego wewnątrz ciała funkcji, bo taki obiekt zakończy swój żywot po wyjściu z funkcji.
Wtedy funkcje będzie też typu void.

0

Rozumiem, jednak w zadaniu stoi żebym dynamicznie zablokował całą tablice dlatego alokuje całą tabilce.

1 użytkowników online, w tym zalogowanych: 0, gości: 1, botów: 0