'how does fscanf works with different variable types?

I was looking at the MSDN documentation for fscanf. I tried changing the sample code in the documentation, but it didn't work as I expected.

If, for example, I have a file "x" with the contents:

"string" 7 3.13 'x'

After scanf("%s", string_input) is executed so the data "string" is read into string_input, does it go to the next in line, or to the 7 for the next read?

Next, suppose the following executes:

char test;
fscanf("%c" , &test)

Will the program jump to the 'x' or read the 7 as its ASCII value?

Here's my rewrite of the sample code from the documentation:

#include <stdio.h>

FILE *stream;

int main( void )
{
    long l;
    float fp,fp1;
    char s[81];
    char c,t;

    stream = fopen( "fscanf.out", "w+" );
    if( stream == NULL )
        printf( "The file fscanf.out was not opened\n" );
    else
    {
        fprintf( stream, "%s %d %c%f%ld%f%c", "a-string",48,'y', 5.15,
                 65000, 3.14159, 'x' );
        // Security caution!
        // Beware loading data from a file without confirming its size,
        // as it may lead to a buffer overrun situation.
        /* Set pointer to beginning of file: */
        fseek( stream, 0L, SEEK_SET );

        /* Read data back from file: */
        fscanf( stream, "%s", s );
        fscanf( stream, "%c", &t );
        fscanf( stream, "%c", &c );

        fscanf( stream, "%f", &fp );
        fscanf( stream, "%f", &fp1 );
        fscanf( stream, "%ld", &l );

     

        printf( "%s\n", s );
        printf("%c\n" , t);
        printf( "%ld\n", l );
        printf( "%f\n", fp );
        printf( "%c\n", c );
     
        printf("f\n",fp1);
        getchar();


        fclose( stream );
    }
}

This is the output:

a-string -858553460 8.000000 4 f

Why is this the output? I was expecting:

a-string
0
65000
5.15
y
3.14159


Solution 1:[1]

Missing format specifier:

printf("f\n",fp1);

should be:

printf("%f\n",fp1);

More importantly: check the return value of fscanf(). It returns the number of successful assignments made: it should be 1 for each call here as there should be exactly one assignment per fscanf() call. If fscanf() fails, the variable is unmodified. As the variables in the code are uninitialised, if fscanf() fails to assign to them they will contain random values, which is the case here:

                            /* a-string 48 y 5.15 65000 3.14159 x */
fscanf(stream, "%s", s);    /* ^             (s is assigned "a-string") */
fscanf(stream, "%c", &t);   /*         ^     (t is assigned space)      */
fscanf(stream, "%c", &c);   /*          ^    (c is assigned 4)          */
fscanf(stream, "%f", &fp);  /*           ^   (fp is assigned 8)         */
fscanf(stream, "%f", &fp1); /*             ^ (fail: 'y' is not a float) */
fscanf(stream, "%ld", &l);  /*             ^ (fail: 'y' is not a long)  */

Solution 2:[2]

Your write statement was

"%s %d %c%f%ld%f%c", "a-string",48,'y', 5.15, 65000, 3.14159, 'x'

If you print the fifth argument as %ld then you should also pass it as (long)65000. But on most systems this won't make a difference. The content of the file should now look and get parsed as follows:

a-string 48 y5.15650003.14159x
^       ^^^
s       |c|
        t fp

s:  "a-string"
t:  ' '
l:  undefined
fp: 8
c:  '4'
fp1: undefined

So s matches the first word, up to the first space. t matches the space character, as %c won't skip leading whitespace. c matches the first digit of 48, and fp the second digit. The %f for fp1 will skip the next space, and then fail to read anything, as the character y cannot be read as a floatingpoint number. The %ld for %l will fail for the same reason. You should check the result of fscanf to detect and report such errors.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1
Solution 2 MvG