fscanf/fscanf_s的行为差异

Ofe*_*lon 7 c++ visual-studio-2005 crt visual-c++

我对以下行为差异感到困惑:

// 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);
Run Code Online (Sandbox Code Playgroud)

结果不依赖于调用顺序(即,首先调用fscanf_s,首先获取空字符串).编译VC++ - VS2005.有人可以复制吗?谁能解释一下?

谢谢!

Mic*_*urr 8

来自文档fscanf_s(),http://msdn.microsoft.com/en-us/library/6ybhk9kc.aspx:

安全函数(带_s后缀)和旧函数之间的主要区别在于安全函数需要每个c,C,s,S和[type字段的大小作为紧跟在变量之后的参数传递.有关更多信息,请参阅scanf_s,_scanf_s_l,wscanf_s,_wscanf_s_l和scanf Width Specification.

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

与scanf和wscanf不同,scanf_s和wscanf_s要求为c,C,s,S或[.]类型的所有输入参数指定缓冲区大小.缓冲区大小在指向缓冲区或变量的指针后立即作为附加参数传递.例如,如果读取字符串,则传递该字符串的缓冲区大小,如下所示:

char s [10];

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

所以你应该这样称呼它:

fscanf_s(fp,"%80s",cmd, sizeof(cmd));
Run Code Online (Sandbox Code Playgroud)


Mic*_*zek 6

fscanf_s(和整个scanf_s家庭)要求您传递的任何大小%c,%C,%s,%S,或%[缓冲区本身之后; 你忽略了这个论点:

fscanf_s(fp, "%80s", cmd, 81);
Run Code Online (Sandbox Code Playgroud)

  • 这似乎是错误的用法.`81`应该是`cmd`缓冲区的大小.但是吗?即使使用"安全"功能,这也是编写崩溃代码的好方法.在读取静态的字符数组时,应该有`sizeof(cmd)`,存储缓冲区分配长度的变量,或者调用给定缓冲区的大小/容量函数.虽然您的示例在技术上是正确的,但对许多人来说可能会产生误导. (3认同)