Search code examples
cfilevariablesscanf

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

  • 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)  */