This link讲述为什么feof()
作为循环的退出指示符是一件坏事。
不安全==>在那里进行feof()
检查,并在其中进行fgets()
。
安全==>在{while}本身进行fgets()!=NULL
检查。
我应该看到不安全的代码执行额外的while循环迭代,但两者都执行相同(和正确)的循环次数。有人可以帮我理解这里发生了什么吗?
编辑:链接实际上确实说明了为什么会发生这种情况,但下面的正确答案让我理解我正在阅读的内容。我的档案中没有' \ n'在最后一行,所以得到了相同的结果。这是文件内容:
abcd
efgh
ijkl
以下代码:
void testUnsafe(void) {
FILE *f;
char buf[20];
f = fopen("fil.txt", "r");
while (!feof(f)) {
fgets(buf, 20, f);
if (buf[strlen(buf) - 1] == '\n') //cleaner
buf[strlen(buf) - 1] = '\0';
printf("%s , %d\n", buf, strlen(buf));
}
fclose(f);
}
void testSafe(void) {
FILE *f;
char buf[20];
f = fopen("fil.txt", "r");
while (fgets(buf, 20, f) != NULL) {
if (buf[strlen(buf) - 1] == '\n') //cleaner
buf[strlen(buf) - 1] = '\0';
printf("%s , %d\n", buf, strlen(buf));
}
fclose(f);
}
输出是:
******unsafe test********
abcd , 4
efgh , 4
ijkl , 4
********safe test********
abcd , 4
efgh , 4
ijkl , 4
答案 0 :(得分:3)
如果您的文本文件在最后一行文本后结束而没有换行符,则testUnsafe()
函数在读取最后一行时将到达文件结尾,并生成三个你已经展示的输出线。
如果您的文本文件 在最后一行文本后面有换行符,则该函数将读取最后一行,包括换行符,不带到达结束行文件。当它再次进入while()
循环时,它会读取零个字符,设置文件结束标志,并输出最后一行仍在缓冲区中的最后一行。
while (!feof(f))
构造本身并不安全 。它忽略了检查不安全的fgets()
的返回值。
答案 1 :(得分:2)
我尝试了你的两个例子,并得到了不同的结果。函数testUnsafe()
两次打印了我文件的最后一行。这有两个原因。
如果读取操作已尝试读取文件末尾,则feof()
函数返回非零值。
函数testUnsafe()
不检查fgets()
的返回值,因此在达到feof()
条件之前重复先前读取的字符串。
我将你的功能复制到我的测试程序中
#include <stdio.h>
#include <string.h>
void testUnsafe(void) {
FILE *f;
char buf[20];
f = fopen("fil.txt", "r");
while (!feof(f)) {
fgets(buf, 20, f);
if (buf[strlen(buf) - 1] == '\n') //cleaner
buf[strlen(buf) - 1] = '\0';
printf("%s , %d\n", buf, strlen(buf));
}
fclose(f);
}
void testSafe(void) {
FILE *f;
char buf[20];
f = fopen("fil.txt", "r");
while (fgets(buf, 20, f) != NULL) {
if (buf[strlen(buf) - 1] == '\n') //cleaner
buf[strlen(buf) - 1] = '\0';
printf("%s , %d\n", buf, strlen(buf));
}
fclose(f);
}
int main()
{
testUnsafe();
printf ("\n\n");
testSafe();
return 0;
}
测试文件:
Line 1
Line 2
Line 3
testUnsafe()
的输出:
Line 1 , 6
Line 2 , 6
Line 3 , 6
Line 3 , 6
testSafe()
的输出:
Line 1 , 6
Line 2 , 6
Line 3 , 6
答案 2 :(得分:0)
基本上,要阅读所有行,您必须使用类似的算法。 如果ou在文件末尾没有换行符,则一定要加载所有行。
这里的例外是最后一行不确定结尾处是否有LF。
除了检查缓冲区溢出以优化内存使用以外,还可以调用realloc()修剪缓冲区,然后再将其添加到数组中。
buffer = (char*)malloc(bufferSize);
while(fgets(buffer, bufferSize, file) != NULL) {
//here store your pointer in array...
buffer = (char*)malloc(bufferSize);
};
free(buffer);