[C] Problemy z funkcją fgets()

Awatar użytkownika
Pneumokok
Użytkownik
Użytkownik
Posty: 48
Rejestracja: 2 sty 2011, o 14:29
Płeć: Mężczyzna
Lokalizacja: Małopolska
Podziękował: 11 razy
Pomógł: 1 raz

[C] Problemy z funkcją fgets()

Post autor: Pneumokok »

Mam otóż taki kod:
Ukryta treść:    
Fgets() z jakiegoś powodu ciągle zwraca NULL - plik istnieje, jego pierwsza linijka to ,,Rekordy=3" - czyli atoi powinien dać 3 (funkcja jest niekompletna - ma służyć do dopisania wyniku do bazy rekordów, zmienna ilosc ma określac wielkość tablicy do przechowywania wyników). Coś pogmatwałem w kodzie?
W razie potrzeby, wrzucę cały plik by osoba która będzie gotowa pomóc mogła samodzielnie go sobie skompilować.
O dziwo - do pliku mogę dopisywać, więc to nie jest chyba problem z samym plikiem
Używam kompilatora Dev C++ w środowisku Windows XP.

Z góry dziękuję za każdą pomoc,
Pneumokok.
void_t
Użytkownik
Użytkownik
Posty: 103
Rejestracja: 14 maja 2011, o 18:25
Płeć: Mężczyzna
Pomógł: 26 razy

[C] Problemy z funkcją fgets()

Post autor: void_t »

W którym miejscu fgets zwraca NULL?
Zamiast:

Kod: Zaznacz cały

char bufor[ROZMIAR+1];
(...)
memset(bufor, '\0', ROZMIAR+1); 
Możesz zapisać:

Kod: Zaznacz cały

char bufor[ROZMIAR+1] = {0};
jego pierwsza linijka to ,,Rekordy=3" - czyli atoi powinien dać 3
Nie. atoi nie wyszuka w zadanym ciągu znaków liczby. Ta funkcja zaczyna interpretować argument jak liczbę (uprzednio pomijając wszystkie białe znaki). Napotykając jednak na coś innego zwraca zero.
Awatar użytkownika
Pneumokok
Użytkownik
Użytkownik
Posty: 48
Rejestracja: 2 sty 2011, o 14:29
Płeć: Mężczyzna
Lokalizacja: Małopolska
Podziękował: 11 razy
Pomógł: 1 raz

[C] Problemy z funkcją fgets()

Post autor: Pneumokok »

Faktycznie, coś musiałem przedtem pogmatwać... Fgets() nie zwraca NULLa, działa tak jak powinno.
Używając funkcji atoi, byłem przekonany że wyłuskuje ona z łańcucha znaków liczbę, teraz gdy sprawdziłem co ona właściwie robi okazało sie że tak nie jest.
Znasz może jakis sposób na wyłuskanie z tablicy znaków liczby?


P.S
Czy ma sens zamiana wszystkich liter na spacje oprócz cyfr
np

Kod: Zaznacz cały

if ( (znak[i]<48) OR (znak[i]>57) ) 
{
    znak[i]=;
}
I wtedy uzycie atoi?
void_t
Użytkownik
Użytkownik
Posty: 103
Rejestracja: 14 maja 2011, o 18:25
Płeć: Mężczyzna
Pomógł: 26 razy

[C] Problemy z funkcją fgets()

Post autor: void_t »

Jest wiele sposobów. Pokażę może jeden na prostym przykładzie:

Kod: Zaznacz cały

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

#define is_numeric(p) (p >= '0' && p <= '9')

int main(void)
{
	char *buf = "als32amakota=32434kotmaale?kolejnyciag123";
	char *num = NULL;
	char *p;
	size_t len;

	for (p = buf, len = 0; *p; p++) {
		/*
		 * *(p + 1) na wypadek gdyby liczby byly
		 * jednak na końcu ciągu
		 */
		if (is_numeric(*p) && *(p + 1) != '\0') {
			len++;
		} else if ((!is_numeric(*p) && len > 0)) {
	copy:
			num = strndup(p - len, len);

			puts(num);
			len = 0;
			free(num);
		} else if (len > 0) {
			/*
			 * aktualizacja statusu zmiennych
			 * i skok celem skopiowania liczby
			 * stojącej na końcu ciągu
			 */
			len++;
			p++;
			goto copy;
		}
	}
}
Jeśli uważasz, że te dane z bufora nie są Ci potrzebne, to czemu nie? Możesz zmienić na białe znaki a potem użyć atoi.
Swoją drogą, zamiast wypisywać numery ASCII umieść znaki w podobny sposób w jaki ja zrobiłem to w makrze is_numeric (tj. w apostrofach).

Aha no i drobne uwagi do mojego kawałka kodu:
1. Jeśli nie potrzebujesz liczby jako stringu, rozważ pewne zmiany.
2. Jeśli nie potrzebujesz parsować tego typu ciągu - także rozważ pewne zmiany.
3. Alokacja jest wolna. Jeśli przykładowo stwierdzisz, że interesują Cie tylko liczby typu całkowitego mieszczące się w 32 bitowym typie int, rozważ zamianę jej, na kopiowanie do statycznego bufora o długości 10 znaków (2^32 ma 10 znaków w zapisie, prawda?)
Awatar użytkownika
Pneumokok
Użytkownik
Użytkownik
Posty: 48
Rejestracja: 2 sty 2011, o 14:29
Płeć: Mężczyzna
Lokalizacja: Małopolska
Podziękował: 11 razy
Pomógł: 1 raz

[C] Problemy z funkcją fgets()

Post autor: Pneumokok »

Faktycznie, po przeróbce działa - dziekuję za pomoc


Korzystając z okazji, o jeszcze jedną rzecz chciałbym zapytać:
Otóż, funkcja ma na celu aktualizację bazy wyników.
Początkowo planowałem zrobić to następująco:

-alokuję tablicę o rozmiarze IlośćRekordów + 1
-wczytuję do tablicy wyniki z pliku
-dopisuję do niej wynik, który ma zostać dodany
-tworzę tablicę wskaźników którą sortuję malejąco
-nadpisuję poprzedni plik

Ale teraz myślę, że dużo roboty z tym... I tu mnie nieco oświeciło - czy jest mozliwość dopisania rekordu wynikowego w dowolnym miejscu w pliku tekstowym, tj odpowiednio wyznaczonym?
Wtedy odpada sortowanie, alokacja... Jedyne co trzeba zrobić to wczytać wiersz, wyłuskać wynik i sprawdzić, czy nowy rekord ma się znajdować za czy przed nim - czy jednak wstawiając nowy wiersz nie nadpiszę znajdującego się pod nim? Ponadto funkcja Fprintf() wymaga wskaźnika do pilku - czy oszukanie jej przez podanie przesuniętej pozycji kursora jest możliwe?
Ponadto czy mozna w języku C nadpisać wiersz w pliku?
Chodzi mi o to, czy np: w pliku jest wiersz Rekordy=0 - czy da się ją nadpisać informacją Rekordy=1?
Ostatnio zmieniony 1 lis 2011, o 22:07 przez Pneumokok, łącznie zmieniany 1 raz.
void_t
Użytkownik
Użytkownik
Posty: 103
Rejestracja: 14 maja 2011, o 18:25
Płeć: Mężczyzna
Pomógł: 26 razy

[C] Problemy z funkcją fgets()

Post autor: void_t »

Po kolei.
czy jest mozliwość dopisania rekordu wynikowego w dowolnym miejscu w pliku tekstowym, tj odpowiednio wyznaczonym?
Jak najbardziej. Zainteresuj się funkcją fseek().
czy nowy rekord ma się znajdować za czy przed nim - czy jednak wstawiając nowy wiersz nie nadpiszę znajdującego się pod nim?
Hm, plik jest ciągiem bajtów. Jeśli chcesz wpisać coś w jego środek bez nadpisywania, to automatycznie zmuszony jesteś niejako "rozsunąć" bajty.
Ponadto funkcja Fprintf() wymaga wskaźnika do pilku - czy oszukanie jej przez podanie przesuniętej pozycji kursora jest możliwe?
Troszeczkę mylisz pojęcia. Wskaźnik typu FILE to taka struktura, o budowie której możesz poczytać w dokumentacji - nie jest ona bynajmniej wskaźnikiem na żaden obszar HDD.
Nie samym też fprintf człowiek żyje. Zainteresuj się bardziej funkcjami fwrite, fseek a odpowiedzi i pomysły przyjdą same.
Ponadto czy mozna w języku C nadpisać wiersz w pliku?
Oczywiście. Kwestia ustawienia się na odpowiedniej pozycji i rozpoczęcia zapisywania do pliku. Oraz tak, "Rekordy=0" z powodzeniem będziesz mógł nadpisać ciągiem "Rekordy=1".
Xitami

[C] Problemy z funkcją fgets()

Post autor: Xitami »

Ponadto czy mozna w języku C nadpisać wiersz w pliku?
Oczywiście. Kwestia ustawienia się na odpowiedniej pozycji i rozpoczęcia zapisywania do pliku. Oraz tak, "Rekordy=0" z powodzeniem będziesz mógł nadpisać ciągiem "Rekordy=1".
oczywiście, że to prawda tylko że nie prawda
void_t
Użytkownik
Użytkownik
Posty: 103
Rejestracja: 14 maja 2011, o 18:25
Płeć: Mężczyzna
Pomógł: 26 razy

[C] Problemy z funkcją fgets()

Post autor: void_t »

Chcesz więc powiedzieć, że nie można otworzyć pliku w r+, ustawić wskaźnika na nty bajt i od tego miejsca zapisywać. Doskonale. Czekam na więcej. A może jednak skusisz się na wygłoszenie konkretów.
ODPOWIEDZ