Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

fscanf / fscanf_s difference in behaviour

I'm puzzled by the following difference in behaviour:

// suppose myfile.txt contains a single line with the single character 's'
    errno_t res;
    FILE* fp;
    char cmd[81];

    res = fopen_s(&fp, "D:\\myfile.txt", "rb" );
    fscanf(fp,"%80s",cmd); // cmd now contains 's/0'
    fclose(fp);

    res = fopen_s(&fp, "D:\\myfile.txt", "rb" );
    fscanf_s(fp,"%80s",cmd); // cmd now contains '/0' !
    fclose(fp);

The results do not depend in the order of call (i.e., call fscanf_s first, you'd get the empty string first). Compiled on VC++ - VS2005. Can anyone reproduce? Can anyone explain?

Thanks!

like image 465
Ofek Shilon Avatar asked Jun 24 '10 18:06

Ofek Shilon


People also ask

Does fscanf read one line at a time?

Each call to fscanf() reads one line from the file.

How does fscanf function work?

The fscanf() function reads data from the current position of the specified stream into the locations that are given by the entries in argument-list, if any. Each entry in argument-list must be a pointer to a variable with a type that corresponds to a type specifier in format-string.

What is the difference between Scanf and Scanf_s in C?

scanf originally just reads whatever console input you type and assign it to a type of variable. scanf_s has an parameter, When you read a string, the parameter must be provided to indicate how many characters are read at most to prevent overflow.


2 Answers

From the docs on fscanf_s(), http://msdn.microsoft.com/en-us/library/6ybhk9kc.aspx:

The main difference between the secure functions (with the _s suffix) and the older functions is that the secure functions require the size of each c, C, s, S and [ type field to be passed as an argument immediately following the variable. For more information, see scanf_s, _scanf_s_l, wscanf_s, _wscanf_s_l and scanf Width Specification.

And http://msdn.microsoft.com/en-us/library/w40768et.aspx:

Unlike scanf and wscanf, scanf_s and wscanf_s require the buffer size to be specified for all input parameters of type c, C, s, S, or [. The buffer size is passed as an additional parameter immediately following the pointer to the buffer or variable. For example, if reading a string, the buffer size for that string is passed as follows:

char s[10];

scanf("%9s", s, 10);

So you should call it like so:

fscanf_s(fp,"%80s",cmd, sizeof(cmd));
like image 68
Michael Burr Avatar answered Sep 25 '22 11:09

Michael Burr


fscanf_s (and the whole scanf_s family) requires that you pass the size of any %c, %C, %s, %S, or %[ after the buffer itself; you're omitting that argument:

fscanf_s(fp, "%80s", cmd, 81);
like image 45
Michael Mrozek Avatar answered Sep 22 '22 11:09

Michael Mrozek