Search code examples
cmemorystructurefgets

fgets is influencing output


I'm having an hard time trying to figure out why my last fgets() seems to delete the value into "studente[0].nome", meanwhile when i use the scanf() that doesn't happen, so I would love if someone could explain me the problem and give me a new opportunity to learn. Thanks in advance.

struct studenti
{
    char nome[40];
    char cognome[40];
    short voto;
    char matricola[3];
};

#define N_STUDENTI 1

int main(void)
{
struct studenti studente[N_STUDENTI];
//float media = 0.0f;
char matricola[3];

printf("Inserisci i dati degli studenti nel Db:\n");

for(short i = 0;i<N_STUDENTI;i++)
{
    printf("Studente %d\n", i+1);
    fputs("NOME:", stdout);
    fgets(studente[i].nome, 40, stdin);
    fputs("COGNOME:", stdout);
    fgets(studente[i].cognome, 40, stdin);
    fputs("NUMERO MATRICOLA:", stdout);
    fgets(studente[i].matricola, 4, stdin);
    fputs("VOTO:", stdout);
    scanf("%hu", &studente[i].voto);
    getchar();
}

/* */
puts("INSERISCI MATRICOLA DELLO STUDENTE: ");
fgets(matricola, 4, stdin);//**HERE IS THE PROBLEM**
//whith a getcahr() works
printf("\n*NOME*: %s*", studente[0].nome);

return 0;
}

Solution

  • You do

    fgets(studente[i].matricola, 4, stdin);
    

    But the matricola definition is

    char matricola[3];
    

    That means you can go out of bounds of the array and have undefined behavior.

    When using fgets with arrays (not pointers) then always use sizeof to get the size:

    fgets(studente[i].matricola, sizeof studente[i].matricola, stdin);
    

    That way you will always pass the correct size.

    And of course you have the same problem after the loop when you read into the stand-alone array matricola.

    If you really need a three-character string then you need to increase the size to 4 (to fit the null-terminator). If you need a four character string, then the size should be 5.