0

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

3 罗伯特·贾斯汀·特朗普

这是我的代码:

#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

为什么它-1在第二种情况下返回?0它应该从1右移?

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

4

2 回答 2

3
 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

重要提示:

使用所有警告和调试信息进行编译(gcc -Wall -Wextra -g使用GCC),改进代码以消除警告,使用调试器 gdb逐步运行它。

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

于 2017-09-17T16:11:52.067 回答
3

您的代码中有多个问题:

  • 您不测试fopen(). ftell()使用指针调用NULL具有未定义的行为。你不能从观察到的行为中得出结论。

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

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

  • int l = n - '0';并非严格不正确,但很容易出错:避免命名变量l,因为它看起来与1.

  • printf("%d %d\n", l, ftell(f));与之前的调用不正确printf:使用转换说明符%ld作为 的返回值ftell()

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

这是一个更正的版本:

#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
于 2017-09-17T16:42:07.373 回答