【问题标题】:File reading program hangs at end of while loop (linux c)文件读取程序在while循环结束时挂起(linux c)
【发布时间】:2016-03-20 22:14:06
【问题描述】:

抱歉这个琐碎的问题。我正在逐个字符地读取文件。它似乎一直工作到最终运行(EOF),由于某种原因程序挂起。

while 循环的最后一行“Done outer loop, in is 0”被打印出来,但是 由于某种原因,即使条件是“(in!='0')”,循环也不会退出。 “完成解析事件”行不打印,程序停止并且没有响应。

char in = '1';
FILE *fid = fopen(filename, "r");
while (in != '0') {
    printf("Start of loop, in is %c\r\n", in);
    if ((in = fgetc(fid)) == EOF) 
        in = '0';

    /* Large block that does stuff depending on the value of in*/

    printf("Done outer loop, in is %c\r\n", in);

}

fclose(fid);
printf("Finished parsing events");
//fflush(stdout);

【问题讨论】:

  • 阅读文档。 fgetc 返回 int,而不是 char,这是有充分理由的。
  • @user3074 在答案下看到您的评论,请张贴Minimal, Complete, and Verifiable example,它显示了您尝试过的内容。我注意到您在最终打印后没有newline,并注释掉了fflush
  • 那么,正是你在这里所拥有的,“根据 in 的值执行操作的大块”完全注释掉,仍然产生相同的挂起外观?

标签: c linux io


【解决方案1】:

尝试改变:

char in = '1';

收件人:

int in = '1';

首先fgetc函数的返回类型是int。当您到达文件末尾时返回EOF(可能是-1,我假设它等于-1)。然后-1存储在in变量中,其类型为char。标准中没有定义char是否签名,在你的情况下它似乎是未签名的,所以in变成255。然后将in 提升为int 类型与EOF 进行比较,但是255 != -1 当然是这样,所以你处于无限循环中。

【讨论】:

  • 我明白了。类似to this question.
  • 确实很常见,我经常看到(一周一次左右,取决于学年临近学期结束的时间)。
  • 您好,谢谢您的回答。这似乎对输出没有任何影响。如果它无限循环,那么行(“循环开始...”)和(“循环结束...”)是否也会无限重复?这不是这里的情况。
  • @user3074 一般来说,行应该无限重复。但这可能取决于描述为“大块...”的代码
  • @user3074 在任何情况下,您都可以在上述修复前后使用调试器检查您的程序。
【解决方案2】:

即使有您发布的代码,以及您收到的关于使用fgetc(3) 的答案,您发布的代码也不应该挂起。让我们看看会发生什么:

fgetc(3) 返回int -1 值(作为int,通常定义为常量EOF)以区分8 位char 的256 种可能性,再加上一种, EOF 条件(不是来自流的数据值)并将其转换为 char(使 EOF 只是一些有效输入的别名)。在您的情况下,您错误地将该条件同化为 char 类型的值之一。

但这通常不会使程序挂起(它甚至没有定义未定义的行为,除了我们实际上不知道哪个char 值将用作@987654333 的别名@ 健康)状况)。然后程序将有 breaking 循环的两个条件(因为您已经屏蔽了一个)。第一个是真正的EOF 条件,第二个是从输入流接收char,当您输入它时EOF 正在被转换为。

正如有人在 cmets 中指出的那样。 问题一定出在大的注释块中,你已经隐藏了。即使 printf(3) 你在它之后执行,而块的外部没有,你可以在隐藏块中出现错误,只有在离开它时才会出现,并使错误明显在循环测试你make 在代码块的开头。

char in = '1'; 更改为int in = '1'; 是消除虚假breaks 问题的好选择,但您的挂起问题不存在...您必须发布隐藏块以获得更多反馈。

重要提示

尝试习惯于编写完整的失败示例......不要编辑代码只是为了发布它,而不测试它是否继续失败(因为你的没有,我在下面演示),你不会得到这种答案(这似乎更像是一种火焰而不是试图帮助你)。您发布的代码,至少必须进行编辑以使其可运行,因为您仅粘贴了一段无法编译的代码。一些这样的例子,应该像我在下面发布的那样,但是,因为它不会失败,所以不能用来解决你的问题。对吧?

#include <stdio.h>             /* line added to make runnable */
#define filename "test.txt"    /* line added to make runnable */
int main()                     /* line added to make runnable */
{                              /* line added to make runnable */
    char in = '1';
    FILE *fid = fopen(filename, "r");
    while (in != '0') {
        printf("Start of loop, in is %c\r\n", in);
        if ((in = fgetc(fid)) == EOF) 
            in = '0';

        /* Large block that does stuff depending on the value of in*/

        printf("Done outer loop, in is %c\r\n", in);

    }

    fclose(fid);
    printf("Finished parsing events");
    //fflush(stdout);
}                              /* line added to make runnable */

如下图运行(没有任何挂起)(请注意sed(1)命令用于在此处添加嵌入输出所需的四个空格为 输出文本,请勿在家里使用它进行测试):

$ pru8 | sed -e 's/^/    /'
Start of loop, in is 1
Done outer loop, in is p
Start of loop, in is p
Done outer loop, in is s
Start of loop, in is s
Done outer loop, in is d

[...] <--- a lot more of repeating lines like the ones posted above.

Start of loop, in is  
Done outer loop, in is 

Start of loop, in is 

Done outer loop, in is 0
Finished parsing events
$ _

没有挂起。

【讨论】:

    猜你喜欢
    • 2013-09-16
    • 2012-10-07
    • 1970-01-01
    • 1970-01-01
    • 2012-12-23
    • 2018-04-17
    • 1970-01-01
    相关资源
    最近更新 更多