Search code examples
cfile-pointerftell

Does fscanf move the file pointer backwards?


These are the contents of my file, 'unsorted.txt' :

3 robert justin trump

This is my code:

#include <stdio.h>

int main(void) {
    FILE *f = fopen("unsorted.txt", "r");
    char n;
    printf("%d\n", ftell(f));
    fscanf(f, "%s", &n);
    int l = n - '0';
    printf("%d %d\n", l, ftell(f));
    return 0;
}

on execution it gives the following output:

0
3 -1

why did it return -1 in second case? It should move from 0 to 1 right?

NOTE: the file can be opened, because then how would it print 0 in the first call and the first character from the file without being able to be opened?


Solution

  •  fscanf(f,"%s",&n);
    

    is very wrong, since you declared char n; (of only one byte). You got undefined behavior. Be very scared (and next time, be ashamed).

    I recommend:

    Test that fopen don't fail:

    FILE *f = fopen("unsorted.txt","r");
    if (!f)  { perror("fopen unsorted.txt"); exit(EXIT_FAILURE); };
    

    Declare a buffer of reasonable size (80 was the size of punched cards in the 1970s).

    char buf[80];
    

    clear it (you want defensive programming):

    memset(buf, 0, sizeof(buf));
    

    Then read carefully about fscanf. Read that documentation several times. Use it with a fixed size and test its result:

    if (fscanf(f, "%72s", buf) > 0) {
    

    (72 was the usable size in PL/1 programs of punched cards; it is less than 80)

    Don't forget to read documentation of other functions, including ftell.

    Important hint:

    compile with all warnings and debug info (gcc -Wall -Wextra -g with GCC), improve the code to get no warnings, use the debugger gdb to run it step by step.

    PS. As an exercise, find the possible content of unsorted.txt which made your initial program run correctly. Could you in that case predict its output? If not, why??