Kopiowanie znaków z pliku do pamięci

0

Hejo mam funkcje ktora otwiera plik binarnie i zapisuje znak do pamieci. wpadlem na takie cos:

	
void readFile(char *name, char **text, int *size)
{
	FILE *file_ptr = NULL;
	file_ptr = fopen(name, "rb");
	if (file_ptr != NULL)
	{
		unsigned int counter = 0;
		char character;
		while ((character = fgetc(file_ptr)) != EOF)//dopoki nie dojedzie do konca
		{
			counter++;
			*text = (char*)realloc(*text, (counter + 1)*sizeof(char*));//realokacja o counter+1 bo znak NULL
			*text[counter - 1] = character;//przypisuje do tablicy wczytany znak
		}
		*(text + counter) = '\0';//na ostatnie miejsce wpisuje nulla
		fclose(file_ptr);
		file_ptr = NULL;
	}
}

podejrzewam ze mam blad z nawiasami albo gdzies z gwiazka. jakies pomysly?

0

Może warto nauczyć się używać debuggera ? Nie mówię tego złośliwie, ale przy takich problemach jest idealnym rozwiązaniem

0

no dobra sprobuje z debbugerem. ale czy zapis

*(text + counter) = 'a'; 

znaczy to samo co

*text[counter] = 'a'; 
1

Trochę zagmatwany kod stworzyłeś, bracie. Jeśli dobrze zrozumiałem, chcesz sobie po prostu wczytać cały plik do pamięci bajt po bajcie. W takim razie bardziej bym się skłaniał ku temu podejściu.

void* readFile(const char *fileName)
{
  FILE *file = fopen(fileName, "rb") ;
  size_t fileSize ;

  if (file == NULL) return NULL ;

  fseek(file, 0, SEEK_END) ;
  fileSize = ftell(file) ;
  fseek(file, 0, SEEK_SET) ;

  unsigned char *array = (unsigned char*)malloc(fileSize) ;
  size_t i ;

  for (i = 0 ; i < fileSize ; ++i) array[i] = fgetc(file) ;

  fclose(file) ;

  return array ;
}
  1. Poprzez ustawianie wskaźnika na strumień pliku przy pomocy funkcji fseek() oraz obliczeniu, jak daleko jest on od początku pliku, poprzez funkcję ftell(), uzyskujesz rozmiar całego pliku, który chcesz sobie wczytać. Nie musisz się bawić w sprawdzanie, czy natrafiłeś już na EOF.
  2. Znając już rozmiar pliku, wystarczy tylko raz zaalokować tyle pamięci, ile faktycznie potrzebujesz, aby móc go bez problemu wczytać. W ten sposób nie musisz się męczyć z funkcją realloc().
  3. Zamiast przekazywać tablicę, którą chcesz zmodyfikować, jako parametr, możesz sobie przypisać do niej tablicę, która została utworzona w tej funkcji i będzie zawierała wczytaną już zawartość pliku.

Pamiętaj, że zamiast wczytywać bajt po bajcie, możesz od razu hurtem władować do tablicy dane poprzez funkcję fread().

0

spodobal mi sie twoj pomysl. pozwolilem sobie go uzyc na swoj sposob. ale cos jest zle bo nie moge pracowac na *text. ja chce zeby funkcja pracowala na wskazniku text ktory jest w mainie a nie zeby funkcja zwracala char

void readFile(char *name, char **text, int *size)
{
FILE *file_ptr = NULL;
	file_ptr = fopen(name, "rb");
	if (file_ptr != NULL)
	{
		unsigned int counter = 0;
		fseek(file_ptr, 0, SEEK_END);//lecimy na koniec
		counter = ftell(file_ptr);//zwraca pozycje wskaznika
		fseek(file_ptr, 0, SEEK_SET);//wracamy ze wskaznikiem na poczatek
		if (*text != NULL)
			free(*text);
		*text = (char*)malloc(counter);
		for (int i = 0; i < counter; i++)
			*(text + i) = fgetc(file_ptr);
		fseek(file_ptr, 0, SEEK_SET);
		fclose(file_ptr);
		file_ptr = NULL; 
}
0

Bardzo zły pomysł z tym *text w main(). W ten sposób tworzysz trudne do analizowania powiązania w kodzie. Traktuj funkcję jak "samodzielne czarne pudełko" do którego coś wrzucasz w postaci argumentów i które coś zwraca w postaci wyników. Jeśli będziesz miał takie pomysły jak z *text, to osiwiejesz w przyszłości analizując lub rozwijając taki kod.
Jeśli nie chcesz skorzystać z rady kolegi, to zerknij jeszcze do funkcji mmap(). Ona mapuje plik na pamięć co bardzo przyśpiesza pracę na pliku.

0

do tego co napisał @Lord Darkstorm dodałbym jeszcze, że - jak już mamy tak zaalokowaną pamięc, to lepiej wczytać po prostu całość - będzie szybciej, niż wczytywanie po znaku.

0

Dziekuje za pomoc wszystkim. wiem ze mozna otworzyc plik jedna funkcja jako calosc, ale ja mam otwierac po jednym charze. jak widzicie taki problem to od razu przypominacie sobie wiele funkcji ktore to ulatwiaja. ja probuje napisac program korzystajac z "podstawowych" funkcji.
po prostu chce trzymac w mainie wskaznik na tablice charow i wczytujac do niego w funkcji. mam nadzieje ze wyrazilem sie jasno.

void readFile(char *name, char **text, int *size)
{
	FILE *file_ptr = NULL;
	file_ptr = fopen(name, "rb");
	if (file_ptr != NULL)
	{
		unsigned int counter = 0;
		printf("Otwarcie pliku \"%s\".", name);
		fseek(file_ptr, 0, SEEK_END);//lecimy na koniec
		counter = ftell(file_ptr);//zwraca pozycje wskaznika
		fseek(file_ptr, 0, SEEK_SET);//wracamy ze wskaznikiem na poczatek
		if (*text != NULL)
			free(*text);
		*text = (char*)malloc(counter*sizeof(char));
		for (unsigned int i = 0; i < counter; i++)
			*(text + i) = fgetc(file_ptr);
		fseek(file_ptr, 0, SEEK_SET);
		printf("\n\n\tOtworzylem.\n\n\n");
		fclose(file_ptr);
		file_ptr = NULL;
	}
	else
		printf("\n\n\tPlik o nazwie %s nie istnieje.\n\n\n", name);
} 

dostaje error:

text	{sz=0x00000061 <Error reading characters of string.> wz=0x00000061 <Error reading characters of string.> }	_output_l::__l2::<unnamed-type-text>

i nie wiem co mam zrobic

zamiana znacznika <quote> na <code class="none"> - @furious programming

1

Ponieważ wykonujesz operacje na text, to prawidłowo przekazujesz go jako char **text, tylko, że nieprawidłowo obsługujesz później w pętli:

*(text + i)

jakby zamiast używać tego nieszczesnego zapisu używać [] moze szybciej byś zauważył, że najpierw musisz wyłuskać samo text, a dopiero pożniej przesunąć wskaźnik i wyłuskać adres.
czyli albo

*((*text) + i)

albo

(*text)[i] 

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