Search code examples
cfgetsscanf

fgets adding string to another variable


I'm trying to do a relatively simple library project in C, but I'm stuck. I'm using fscanf to set a variable (cote which is char[5]) and then fgets to set another variable (titre which is a char[50]). Both of these variables belong to a structure called Ouvrage.

The problem is that fgets seems to add the string it is reading to cote, before the fgets : strlen(o.cote) returns 5 yet afterwards it returns 31.

Here is the code for test.c :

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

typedef struct {
    char cote[5];
    char titre[50];
} Ouvrage;

void main(void)
{
    FILE *flot;
    Ouvrage o;

    // Opening the file

    flot = fopen("ouvrages.don", "r");

    if(flot == NULL)
    {
        printf("Error opening file.\n");
        exit(1);
    }

    // Reading the cote

    fscanf(flot, "%s%*c", o.cote);

    // Printing the length of cote

    printf("STRLEN: %d\t", strlen(o.cote));

    // Reading the titre

    fgets(o.titre, 50, flot);
    o.titre[strlen(o.titre) - 1] = '\0';

    // Printing the length of cote again.... Different.

    printf("STRLEN: %d\n", strlen(o.cote));
}

And here is the ouvrage.don file :

NJDUI
Charlie et la chocolaterie
ROM
Rhoal Doal

So how is fgets affecting a previous variable and how to stop it ? Any help is greatly appreciated.


Solution

  • Welcome to the world of c-strings. Assuming cote is supposed to be 5 characters long, you actually need to reserve 6 characters in order to have space for the end of string character ('\0'); what happened was that fscanf wrote that string character as the first character of titre,but then fgets overwrote that, which is why you saw what you saw. Also note that as far as I'm concerned, scanf and related is the tool of the devil; why not just use fgets (which allows you to specify the maximum number of bytes to read [read closely the manpage to avoid an off by one]) for both reads?