fgets何时停止读取?调试时fgets读空致死循环求助排查
首先先明确fgets什么时候会停止读取:
- 碰到**换行符(
\n)**就停,而且这个换行符会被一起存入你指定的缓冲区里 - 读到**文件末尾(EOF)**时停止,如果这时候已经读了部分字符,就把这些字符存进缓冲区;要是啥都没读到,就返回
NULL - 当读取的字符数达到缓冲区大小减1时也会停——毕竟要留一个位置放字符串结束符
\0
接下来解决你遇到的头疼问题:fgets读不到内容,还在while(!feof(fp2))里无限循环,核心问题和几个排查方向我给你列出来:
第一个坑:别用while(!feof(fp))当循环条件!
这是C语言里新手常踩的坑——feof的触发逻辑是只有当你尝试读取过了文件末尾之后,它才会被置位。也就是说,当fgets已经读不到内容返回NULL时,feof可能还没触发,循环就会继续跑,直接导致无限循环。
正确的写法应该直接把fgets的返回值作为判断条件:
while(fgets(line, sizeof(line), fp2) != NULL) { // 这里处理你读到的每一行内容 }
这样一来,只要fgets读不到内容(不管是到了EOF还是出错),循环直接就停了,根本不会有无限循环的问题。
然后排查为什么fgets读不到内容
先检查文件有没有正确打开
你有没有验证fp2的有效性?比如fopen的时候如果路径错了、文件不存在或者没权限,会返回NULL。加个判断排查一下:fp2 = fopen("你的输入文件名", "r"); if(fp2 == NULL) { perror("打开文件失败"); exit(1); // 或者做其他错误处理 }文件指针位置是不是跑偏了
如果之前你对fp2做过fseek、fread之类的操作,可能把指针移到了文件末尾,这时候fgets当然读不到东西。可以用rewind(fp2)把指针重置回文件开头试试。流是不是处于错误状态
如果之前对这个文件流的操作出过错(比如读写出错),流会被标记为错误状态,后续的fgets也会失败。你可以用ferror(fp2)检查是否有错误,要是有的话用clearerr(fp2)清除错误状态再试试。缓冲区大小够不够?
你提供的输入文件是一整行长文本,如果sizeof(line)比这个文本的长度小,fgets会先读满缓冲区,下次循环继续读剩下的内容,但不会直接返回NULL。不过这不会导致完全读不到内容,只是需要多循环几次。
按照这个思路先改循环条件,再逐一排查上面的点,应该就能解决你的问题了。
内容的提问来源于stack exchange,提问作者topcat

