fgets în C

Citește un rând întreg (cu tot cu spații) într-un tablou de caractere, fără să depășească dimensiunea dată.

Sintaxă
#include <stdio.h>
char *fgets(char *s, int n, FILE *stream);

Ce face fgets

fgets citește caractere din stream până la primul '\n' inclusiv, până la sfârșitul fișierului sau până a citit n - 1 caractere, oricare vine primul. Adaugă la final '\0', deci nu scrie niciodată mai mult de n octeți în tablou. Pentru tastatură, stream este stdin.

Spre deosebire de scanf("%s"), fgets păstrează spațiile, deci citește nume compuse sau adrese. Păstrează și caracterul '\n' de la final, dacă a încăput; de obicei îl ștergi cu s[strcspn(s, "\n")] = '\0';.

Funcția gets, care citea un rând fără limită de lungime, a fost eliminată din limbaj în C11 tocmai pentru că permitea depășirea tabloului. Folosește fgets.

Parametri

Parametru Descriere
s Tabloul în care se scrie rândul.
n Dimensiunea tabloului; se citesc cel mult n - 1 caractere.
stream De unde se citește: stdin sau un fișier deschis cu fopen.

Ce returnează

s dacă a citit ceva, sau NULL la sfârșitul fișierului (fără niciun caracter citit) sau la eroare.

Exemple

Exemplul 1: Un rând cu spații și ștergerea lui \n

strlen arată că rândul citit conține și '\n'. strcspn găsește poziția lui, iar acolo punem '\0'.

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

int main(void) {
    char nume[50];
    printf("Numele complet: ");
    if (fgets(nume, sizeof nume, stdin) == NULL) {
        return 0;
    }
    printf("\nLungime cu \\n: %zu\n", strlen(nume));
    nume[strcspn(nume, "\n")] = '\0';
    printf("Lungime fără \\n: %zu\n", strlen(nume));
    printf("Bun venit, %s!\n", nume);
    return 0;
}

Ce scrie utilizatorul (intrare)

Ana Maria Popescu

Rezultat

Numele complet: 
Lungime cu \n: 18
Lungime fără \n: 17
Bun venit, Ana Maria Popescu!

Exemplul 2: Toate rândurile până la sfârșitul intrării

fgets returnează NULL când nu mai are ce citi, așa că bucla se oprește singură. La fel se citesc rândurile unui fișier, cu FILE * în loc de stdin.

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

int main(void) {
    char rand[100];
    int numar = 0;
    while (fgets(rand, sizeof rand, stdin) != NULL) {
        rand[strcspn(rand, "\n")] = '\0';
        numar++;
        printf("%d. %s\n", numar, rand);
    }
    printf("Total orașe: %d\n", numar);
    return 0;
}

Ce scrie utilizatorul (intrare)

Iași
Cluj-Napoca
Timișoara

Rezultat

1. Iași
2. Cluj-Napoca
3. Timișoara
Total orașe: 3

Exemplul 3: Ce se întâmplă când rândul nu încape

Tabloul are 8 octeți, deci fiecare apel citește cel mult 7 caractere. Rândul lung este citit în bucăți; doar ultima bucată se termină cu '\n'. Așa poți ști dacă ai primit rândul întreg. Bucata Lăpuș are doar 5 litere pentru că „ă” și „ș” ocupă câte doi octeți în UTF-8.

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

int main(void) {
    char bucata[8];
    while (fgets(bucata, sizeof bucata, stdin) != NULL) {
        int complet = strchr(bucata, '\n') != NULL;
        bucata[strcspn(bucata, "\n")] = '\0';
        printf("[%s]%s\n", bucata, complet ? " <- sfârșit de rând" : "");
    }
    return 0;
}

Ce scrie utilizatorul (intrare)

Strada Lăpușneanu 12

Rezultat

[Strada ]
[Lăpuș]
[neanu 1]
[2] <- sfârșit de rând

Greșeli frecvente

  • Uiți că '\n' rămâne în tablou. Comparația strcmp(raspuns, "da") nu va fi niciodată 0, pentru că șirul este "da\n".
  • Amesteci scanf("%d") cu fgets: după scanf, Enter-ul rămâne în stdin, iar următorul fgets citește un rând gol. Citește totul cu fgets și convertește cu strtol sau sscanf.
  • Transmiți o dimensiune mai mare decât tabloul (de exemplu fgets(s, 100, stdin) pentru char s[50]). Folosește sizeof s când s este tablou (nu pointer).

Comenzi înrudite

  • scanf: Citește valori de la tastatură după un șablon (%d, %lf, %s) și le scrie la adresele primite; returnează câte valori a citit.
  • getchar: Citește un singur caracter de la intrarea standard; returnează EOF când intrarea s-a terminat.
  • puts și putchar: puts afișează un șir și trece la rând nou, putchar afișează un singur caracter; mai simple decât printf când nu formatezi nimic.
  • Șiruri de caractere (char[]): În C, un șir de caractere este un tablou de char terminat cu caracterul nul ‘\0’, care marchează sfârșitul textului.
  • fopen și fclose: Deschide un fișier pentru citire, scriere sau adăugare și returnează un FILE *; fclose îl închide și salvează datele rămase.
  • strtol și strtod: Transformă text în număr și îți spune unde s-a oprit citirea și dacă valoarea a depășit limitele.