这些是我的文件"未排序.txt的内容:
3罗伯特·贾斯汀·特朗普
这是我的代码:
#include <stdio.h>
int main(void) {
FILE *f = fopen("unsorted.txt", "r");
char n;
printf("%dn", ftell(f));
fscanf(f, "%s", &n);
int l = n - '0';
printf("%d %dn", l, ftell(f));
return 0;
}
在执行时,它给出以下输出:
0
3 -1
为什么在第二种情况下它返回-1
?它应该从0
转移到1
,对吧?
注意:文件可以打开,因为这样它如何在第一次调用中打印 0 和文件中的第一个字符而无法打开?
fscanf(f,"%s",&n);
是非常错误的,因为你声明了char n;
(只有一个字节)。你有未定义的行为。非常害怕(下次,感到羞耻)。
我建议:
测试fopen
不会失败:
FILE *f = fopen("unsorted.txt","r");
if (!f) { perror("fopen unsorted.txt"); exit(EXIT_FAILURE); };
声明一个合理大小的缓冲区(80 是 1970 年代穿孔卡的大小)。
char buf[80];
清除它(你想要防御性编程):
memset(buf, 0, sizeof(buf));
然后仔细阅读有关 fscanf 的信息。多次阅读该文档。以固定大小使用它并测试其结果:
if (fscanf(f, "%72s", buf) > 0) {
(72是穿孔卡PL/1程序中的可用大小;小于80)
不要忘记阅读其他函数的文档,包括 ftell。
重要提示:
使用所有警告和调试信息进行编译(使用 GCCgcc -Wall -Wextra -g
),改进代码以获得无警告,使用调试器gdb
逐步运行它。
附言。作为练习,找到使初始程序正常运行的unsorted.txt
的可能内容。在这种情况下,你能预测它的输出吗?如果没有,为什么??
代码中存在多个问题:
-
您不测试
fopen()
的返回值。使用NULL
指针调用ftell()
具有未定义的行为。 您无法从观察到的行为中得出结论。 -
printf("%dn", ftell(f));
不正确,因为ftell()
的返回值是一个long
。 您应该使用格式%ld
。 -
fscanf(f, "%s", &n);
不正确,因为您传递了单个char
的地址,以便fscanf()
存储以 null 结尾的字符串。fscanf()
将访问超出char
大小的内存,而具有未定义的行为。定义一个char
数组(如char buf[80];
),并将要存储的最大字符数传递为:fscanf(f, "%79s", buf);
并检查返回值,或使用%c
读取单个字节。 -
int l = n - '0';
并非严格不正确,但它容易出错:避免将变量命名l
因为它看起来与1
相似。 -
printf("%d %dn", l, ftell(f));
不正确,因为前面对printf
的调用:对返回值ftell()
使用转换说明符%ld
。
另请注意,文本流上ftell()
的返回值不一定是文件中的字节偏移量。
这是更正后的版本:
#include <stdio.h>
int main(void) {
FILE *f = fopen("unsorted.txt", "r");
char c;
if (f != NULL) {
printf("%ldn", ftell(f));
if (fscanf(f, "%c", &c) == 1) {
int diff = c - '0';
printf("%d %ldn", diff, ftell(f));
}
}
return 0;
}
输出:
0
3 1