2013-05-01 36 views
6

Od The GNU C Programming Tutorial:Dlaczego funkcja fgets jest przestarzała?

fgets funkcji ("file get string") jest podobny do dostaje funkcję. Ta funkcja jest przestarzała - co oznacza, że ​​jest przestarzała i zdecydowanie zaleca się, abyś jej nie używał - ponieważ jest niebezpieczny pod względem niebezpieczeństwa . Jest to niebezpieczne, ponieważ jeśli dane wejściowe zawierają znak zerowy , nie można powiedzieć. Nie używaj fgets, chyba że wiesz, że dane nie mogą zawierać wartości null. Nie używaj go do odczytywania plików edytowanych przez użytkownika , ponieważ jeśli użytkownik wstawi pusty znak, powinieneś go odpowiednio obsłużyć lub wydrukować czysty komunikat o błędzie. Zawsze używaj getline lub getdelim zamiast fgets, jeśli możesz.

Myślałem funkcja fgets zatrzymuje się, gdy napotka \0 lub \n; dlaczego ta strona podręcznika sugeruje, że bajt zerowy jest "niebezpieczny", gdy fgets powinien poprawnie obsłużyć dane wejściowe? Ponadto jaka jest różnica między getline i fgets, a funkcja fgets jest naprawdę uważana za przestarzałą w przyszłych standardach C?

Odpowiedz

12

Nie, fgets nie jest aktualnie uznawane za przestarzałe w C99 lub w obecnym standardzie, C11. Ale autor tego samouczka ma rację, że fgets nie zatrzyma się, gdy napotka NUL, i nie ma mechanizmu do zgłaszania odczytania takiej postaci.

Funkcja fgets czyta co najwyżej o jeden mniejsza niż liczba znaków określonych przez n ze strumienia wskazywanego przez stream do tablicy wskazywanej przez s. Żadne dodatkowe znaki nie są odczytywane po znaku nowej linii (który jest zachowywany) lub po końcu pliku.

(§7.21.7.2)

GNU na getdelim i getline zostały znormalizowane w POSIX 2008, więc jeśli są kierowane na platformę POSIX, to nie może być zły pomysł, aby korzystać z tych zamiast.

EDIT myślałem, nie było żadnego bezpieczny sposób korzystać fgets w obliczu znaków NUL, ale R .. (patrz komentarze) wskazał, znajduje się:

char buf[256]; 

memset(buf, '\n', sizeof(buf)); // fgets will never write a newline 
fgets(buf, sizeof(buf), fp); 

Teraz spójrz na ostatni Non-\n znak w buf. Właściwie to nie polecałbym tego kundla.

+0

Tak więc 'fgets' zachowuje czytanie przeszłych bajtów zerowych, szukając tylko znaku nowej linii? –

+1

@VilhelmGray: Zgadza się i nie będzie ci tego mówić. Nie ma sposobu, aby upewnić się, że pierwsze znalezione \ 0 zostało dodane przez 'fgets' lub nie. –

+4

bajty null nie należą do plików ** tekstowych.'fgets()' zostało zaprojektowane do pracy z plikami tekstowymi: używanie 'fgets()' z plikami danych binarnych nie jest zalecane. – pmg

5

To jest tylko propaganda GNU. W żadnym oficjalnym znaczeniu nie jest już uznawane za przestarzałe fgets. gets jest jednak niebezpieczny i przestarzały.

+3

'gets' został faktycznie * usunięty * ze standardu ISO C z 2011 roku. (To nie było oficjalnie przestarzałe lub przestarzałe w C99.) –

+3

@KeithThompson: Sekcja 7.26.9 normy ISO/IEC 9899: 1999 TC3 mówi "Funkcja' gets' jest przestarzała i jest przestarzała. " więc uważam, że 'dostaje' zostało oficjalnie wycofane w C99. –

+0

Czy ten język został dodany do jednego z TC, czy był w oryginalnej publikacji C99? –