-3

I was given a problem to solve using fscanf which states the following:

Write a function to initialize array x of size SIZE with integers read from a text file. The function receives the name of the file as an argument.

The solution states the following below. Why would fscanf return a value < 1 if you're scanning each integer in the file? Shouldn't it be > 0 since fscanf returns the number of elements scanned?

void init (char *name)
{
    FILE    *fp;
    int i;

    fp = fopen (name, "r");
    if (fp == NULL)
    {
        printf ("no file\n");
        return;
    }

    for (i = 0; i < SIZE; i++)
    {
        if (fscanf (fp, "%d", &x[i]) < 1)
        {
            printf ("got %d numbers\n", i);
            return;
        }
    }

    fclose (fp);
    return;
}
eel314
  • 3
  • 5
  • So if it returns < 1 then it didn't scan anything. Perhaps you've run out of data? perhaps there is an error? – John3136 Nov 02 '17 at 05:06
  • Read the man page. It says `the function returns the number of items of the argument list successfully filled. This count can match the expected number of items or be less (even zero) due to a matching failure, a reading error, or the reach of the end-of-file.`. – Gaurav Pathak Nov 02 '17 at 05:06
  • If you are on Linux you can simply type `man fscanf` in terminal to open the API reference manual of `fscanf` and you can read the section under _**return value**_. This goes for any function call. – Gaurav Pathak Nov 02 '17 at 05:10
  • @Gaurav yeah I did read the manual and I'm still confused which is why I'm asking on here.... am I correct in thinking that this if statement is written to break the for loop when the fscanf returns a value < 1 which is essentially the EOF? – eel314 Nov 02 '17 at 05:18
  • @Connor, it's not just EOF, it will also fail if it finds something like `hello`, or the `.14159` bit of `3.14159`. Basically, anything that's not a valid integer. – paxdiablo Nov 02 '17 at 05:31

2 Answers2

2

You seem to be misunderstanding the intent of the code:

for (i = 0; i < SIZE; i++)
{
    if (fscanf (fp, "%d", &x[i]) < 1)
    {
        printf ("got %d numbers\n", i);
        return;
    }
}

What this will do is return if the fscanf failed to read in an integer (it returns the number of items scanned). So, at that point, the function will return(a).

If you get a positive integer, it means you successfully read in the value and your loop will continue.


(a) You probably should break here rather than return since the file doesn't get closed the way it is at the moment.

paxdiablo
  • 854,327
  • 234
  • 1,573
  • 1,953
  • Probably, OP should replace `printf` with `perror`, in this way it should also print what error actually made `fscanf` to return 0. – Gaurav Pathak Nov 02 '17 at 05:15
  • 1
    @Gaurav -- `errno` is not set just because a user fails to enter an integer when expected by `fscanf()`.... In other words, `perror()` is probably going to be useless here. – ad absurdum Nov 02 '17 at 05:19
  • @paxdiablo so basically this is just a long winded way of breaking when fscanf is no longer able to read integers in the file? – eel314 Nov 02 '17 at 05:20
  • @DavidBowling Ohh, I thought that `perror` should print the errno in this case as well if `fscanf` fails. – Gaurav Pathak Nov 02 '17 at 05:21
  • @Stargateur Thanks, I just read it in the duplicate link. Got it. (y) – Gaurav Pathak Nov 02 '17 at 05:25
  • @Connor: yes, basically. It will loop up to `SIZE` times but break out early if you run out of valid input values. – paxdiablo Nov 02 '17 at 05:29
  • 1
    @Stargateur -- it is a POSIX requirement that `errno` be set if an error occurs before the first conversion has completed, but I don't anywhere in the C11 Standard that `fscanf()` must set `errno` or any error indicators. – ad absurdum Nov 02 '17 at 05:35
0

Why would fscanf return a value < 1 if you're scanning each integer in the file?

fscanf (fp, "%d", &x[i]) returns:

1 when one int scanned successfully. Code loops to read additional int

0 when only non-numeric non-white-space input detected

EOF (EOF is some negative value) on end-of-file.

EOF on input error (rare).


With if (fscanf (fp, "%d", &x[i]) < 1), the branch is taken as one of the last 3 conditions occurred - likely end-of-file.

chux - Reinstate Monica
  • 143,097
  • 13
  • 135
  • 256