fscanf 是否向后移动文件指针?

Does fscanf move the file pointer backwards?

这些是我的文件的内容,'unsorted.txt' :

3 robert justin trump

这是我的代码:

#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;
}

执行时输出如下:

0
3 -1

为什么在第二种情况下 return -1?它应该从 0 移动到 1 对吗?

注意:该文件可以打开,因为它如何在第一次调用时打印 0 和文件中的第一个字符而无法打开?

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

是非常错误的,因为你声明了 char n; (只有一个字节)。你得到了undefined behavior. Be very scared(下一次,感到羞耻)。

我推荐:

测试 fopen 不会失败:

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

声明一个合理大小的缓冲区(80 是 70 年代穿孔卡片的大小)。

char buf[80];

清除它(你想要defensive programming):

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

然后仔细阅读fscanf。多次阅读该文档。以固定大小使用它并测试它的结果:

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

(72是PL/1打孔卡程序中可用的大小,小于80)

不要忘记阅读其他函数的文档,包括 ftell

重要提示:

编译时包含所有警告和调试信息(gcc -Wall -Wextra -gGCC),改进代码以消除警告,使用调试器 gdb到运行它一步一步来。

PS。作为练习,找到 unsorted.txt 的可能内容,这些内容使您的初始程序 运行 正确。在那种情况下,你能预测它的输出吗?如果不是,为什么??

您的代码中存在多个问题:

  • 您没有测试 fopen() 的 return 值。使用 NULL 指针调用 ftell() 具有未定义的行为。您无法从观察到的行为中得出结论。

  • printf("%d\n", ftell(f)); 不正确,因为 ftell() 的 return 值是 long。您应该使用格式 %ld.

  • fscanf(f, "%s", &n); 是不正确的,因为您为 fscanf() 传递了单个 char 的地址来存储以 null 结尾的字符串。 fscanf() 将访问超出 char 大小的内存,这具有未定义的行为。定义一个char的数组,比如char buf[80];,传最大字符数存储为:fscanf(f, "%79s", buf);,检查return值,或者用%c读取一个字节。

  • int l = n - '0'; 并不是严格意义上的错误,但它很容易出错:避免将变量命名为 l,因为它看起来与 1.[=36 容易混淆=]

  • printf("%d %d\n", l, ftell(f)); 与之前对 printf 的调用不正确:对 [=13= 的 return 值使用转换说明符 %ld ].

另请注意,文本流中 ftell() 的 return 值不一定是文件中的字节偏移量。

这是更正后的版本:

#include <stdio.h>

int main(void) {
    FILE *f = fopen("unsorted.txt", "r");
    char c;

    if (f != NULL) {
        printf("%ld\n", ftell(f));
        if (fscanf(f, "%c", &c) == 1) {
            int diff = c - '0';
            printf("%d %ld\n", diff, ftell(f));
        }
    }
    return 0;
}

输出:

0
3 1