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) 
  1. 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