fgets() i gets() w programowaniu C

fgets() i gets() w programowaniu C

Wprowadzenie

Funkcje fgets() i gets() są podstawowymi funkcjami biblioteki standardowej C służącymi do odczytywania znaków z wejścia standardowego. Są one często używane do pobierania danych wprowadzonych przez użytkownika lub z plików. Podczas gdy obie funkcje służą do tego samego celu, istnieją między nimi pewne istotne różnice, które należy wziąć pod uwagę.

fgets()

Funkcja fgets() odczytuje linię tekstu z wejścia standardowego do bufora znakowego. Zwraca wskaźnik do bufora, jeśli odczyt się powiódł, lub NULL, jeśli wystąpił błąd lub osiągnięto koniec pliku (EOF).

Składnia

c
char fgets(char *str, int n, FILE stream);

gdzie:

* str – wskaźnik do bufora znakowego, do którego należy odczytać linię
* n – maksymalna liczba znaków do odczytania, w tym znak końca linii (\n)
* stream – strumień wejściowy, z którego należy odczytać linię

Działanie

1. Odczytywanie znaków:
– Funkcja fgets() odczytuje znaki z wejścia standardowego do bufora znakowego, dopóki nie napotka znaku końca linii (\n) lub nie osiągnie maksymalnej liczby znaków (n).
– Znak końca linii jest dodawany na końcu odczytanej linii.

2. Znak końca pliku (EOF):
– Jeśli osiągnięto koniec pliku (EOF), funkcja fgets() zwraca NULL.
– W takim przypadku bufor znakowy pozostaje pusty.

3. Błędy:
– Jeśli wystąpi błąd odczytu, na przykład błąd wejścia-wyjścia, funkcja fgets() zwraca NULL.

Przykład użycia

c
#include <stdio.h>

int main() {
char buffer[100];
printf("Wprowadź linię tekstu: ");
fgets(buffer, sizeof(buffer), stdin);
printf("Odczytana linia: %s", buffer);
return 0;
}

gets()

Funkcja gets() odczytuje linię tekstu z wejścia standardowego do bufora znakowego. Podobnie jak fgets(), zwraca wskaźnik do bufora, jeśli odczyt się powiódł, lub NULL, jeśli wystąpił błąd lub osiągnięto EOF.

Składnia

c
char gets(char str);

gdzie:

* str – wskaźnik do bufora znakowego, do którego należy odczytać linię

Działanie

1. Odczytywanie znaków:
– Funkcja gets() odczytuje znaki z wejścia standardowego do bufora znakowego, dopóki nie napotka znaku końca linii (\n).
– Znak końca linii NIE jest dodawany na końcu odczytanej linii.

2. Znak końca pliku (EOF):
– Jeśli osiągnięto EOF, funkcja gets() zwraca NULL.
– W takim przypadku bufor znakowy pozostaje pusty.

3. Błędy:
– Jeśli wystąpi błąd odczytu, na przykład błąd wejścia-wyjścia, funkcja gets() zwraca NULL.

Przykład użycia

c
#include <stdio.h>

int main() {
char buffer[100];
printf("Wprowadź linię tekstu (bez znaku końca linii): ");
gets(buffer);
printf("Odczytana linia: %s", buffer);
return 0;
}

Różnice między fgets() a gets()

Główną różnicą między fgets() a gets() jest sposób obsługi znaku końca linii. fgets() dodaje znak końca linii do odczytanej linii, natomiast gets() nie. Dodatkowo gets() jest uważany za funkcję niebezpieczną, ponieważ nie sprawdza, czy bufor znakowy jest wystarczająco duży, aby pomieścić odczytaną linię. Może to prowadzić do przepełnienia bufora i błędów ochrony pamięci.

Kiedy używać fgets() lub gets()

Ogólnie rzecz biorąc, zaleca się używanie fgets() zamiast gets(). fgets() jest bezpieczniejszą i bardziej elastyczną opcją, ponieważ umożliwia określenie maksymalnej liczby znaków do odczytania i dodaje znak końca linii na końcu odczytanej linii.

gets() można nadal używać w niektórych przypadkach, na przykład gdy wiadomo, że odczytywana linia nie zawiera żadnego znaku końca linii lub gdy nie ma obaw o przepełnienie bufora.

Przykłady użycia fgets() i gets()

Przykład 1: Odczytywanie linii tekstu z wejścia standardowego

c
#include <stdio.h>

int main() {
char buffer[100];
printf("Wprowadź linię tekstu (zostanie dodany znak końca linii): ");
fgets(buffer, sizeof(buffer), stdin);
printf("Odczytana linia z fgets(): %s", buffer);
return 0;
}

Ten przykład używa fgets() do odczytania linii tekstu z wejścia standardowego. Ponieważ maksymalną liczbę znaków ustawiono na 100, odczytywana linia może zawierać maksymalnie 99 znaków plus znak końca linii.

Przykład 2: Odczytywanie linii tekstu bez znaku końca linii

c
#include <stdio.h>

int main() {
char buffer[100];
printf("Wprowadź linię tekstu (bez znaku końca linii): ");
gets(buffer);
printf("Odczytana linia z gets(): %s", buffer);
return 0;
}

Ten przykład używa gets() do odczytania linii tekstu z wejścia standardowego. Ponieważ nie określono maksymalnej liczby znaków, funkcja gets() będzie odczytywać znaki, dopóki nie napotka znaku końca linii. Należy pamiętać, że odczytana linia nie będzie zawierać znaku końca linii.

Konkluzja

Funkcje fgets() i gets() są użytecznymi narzędziami do odczytywania danych z wejścia standardowego w programowaniu C. fgets() jest ogólnie bezpieczniejszą i bardziej elastyczną opcją, podczas gdy gets() może być przydatny w niektórych przypadkach, gdy nie ma obaw o przepełnienie bufora. Zrozumienie różnic między tymi funkcjami i ich prawidłowe użycie ma kluczowe znaczenie dla pisania bezpiecznego i wydajnego kodu.

Często zadawane pytania (FAQ)

1. Co się stanie, jeśli bufor znakowy przekazany do fgets() jest zbyt mały, aby pomieścić odczytywaną linię?
Funkcja fgets() odczyta tylko tyle znaków, ile mieści się w buforze znakowym, i doda znak końca linii.

2. Czy fgets() czyta znaki białe?
Tak, fgets() czyta wszystkie znaki, w tym znaki białe (spacje, tabulatory itp.).

3. Co to jest znak końca linii (EOF)?
Znak końca linii (EOF) to specjalny znak oznaczający koniec pliku lub ciągu znaków.

4. Dlaczego fgets() jest uważany za bezpieczniejszy od gets()?
fgets() jest uważany za bezpieczniejszy, ponieważ umożliwia określenie maksymalnej liczby znaków do odczytania, co zapobiega przepełnieniu bufora. gets() nie ma takiej możliwości.

5. Kiedy powinienem używać fgets() zamiast gets()?
Zaleca się używanie fgets() zamiast gets() w większości przypadków, ponieważ jest to bezpieczniejsza i bardziej elastyczna opcja.

6. Czy fgets() może być użyty do odczytywania linii tekstu z pliku?
Tak, fgets() można użyć do odczytywania linii tekstu z pliku, jeśli jest on otwarty w trybie odczytu.

7. Czy gets() można użyć do odczytywania wielowierszowego tekstu?
Nie, gets() odczytuje tylko jedną linię tekstu. Aby odczytać wielowierszowy tekst, należy użyć pętli lub funkcji takiej jak getline().

8. Czy fgets() dodaje znak końca linii na końcu odczytanej linii?
Tak, fgets() dodaje znak końca linii (\n) na końcu odczytanej linii, chyba że osiągnięto EOF