cfor-loopscanffgets

behaviour of scanf vs fgets


Please see the following piece of code in C

printf ("\nEnter the lines (terminate each line with ENTER...\n\n");
for (i = 0; i < lines; i++)
    scanf (" %[^\n]", s[i]);

I have been told this is a dangerous way of using scanf(). So I tried to use fgets() instead...

printf ("\nEnter the lines (terminate each line with ENTER...\n\n");
for (i = 0; i < lines; i++)
    fgets(s[i], 999,stdin);

However, the fgets() reads one line less than the scanf, everything else remaining the same. For example, if lines = 5, scanf reads strings from 0 to 4 i.e. 5 in all, however, fgets reads only 4 strings.

Why is that so and how can I remedy that?


Solution

  • This call of scanf

    scanf (" %[^\n]", s[i]);
    

    is unsafe because there is not specified field width. If for example sizeof( s[i] ) is equal to 1000 then you should write

    scanf (" %999[^\n]", s[i]);
    

    As for fgets then it seems before the for loop you entered something as for example the value of the variable lines. In this case the input buffer contains the new line character stored there after the call of scanf and the first call of fgets reads an empty string.

    There is no such a problem with the call of scanf because the leading space in the format string

    scanf (" %[^\n]", s[i]);
           ^^
    

    allows to skip leading white space characters in the input buffer.

    In such a situation if you use fgets then you need to remove the new line character if it is in the input buffer before a call of fgets.