提问人:Somjit 提问时间:12/14/2014 最后编辑:Somjit 更新时间:11/22/2018 访问量:1646
使用 feof() 从文件读取并退出循环
Reading from file and exiting loop using feof()
问:
这个链接讲述了为什么用作循环的退出指示符是一件坏事。feof()
不安全 ==> 在一段时间内检查,同时在里面检查。feof()
fgets()
安全 ==> 在同时本身进行检查。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
答:
我尝试了你的两个例子,得到了与你不同的结果。函数打印了我文件的最后一行两次。这有两个原因。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
评论
newline
strlen(buf)
if (buf[strlen(buf) - 1]
"\0some text\n"
fgets()
newline
newline
newline
如果文本文件在最后一行文本后没有换行符,则该函数将在读取最后一行时到达文件末尾,并生成您显示的三行输出。testUnsafe()
如果文本文件在最后一行文本后确实有换行符,则该函数将读取最后一行(包括换行符),而不会到达文件末尾。当它再次进入循环时,它会读取零个字符,设置文件结束标志,并输出最后一行,该行仍在上一轮的缓冲区中。while()
该建筑本身并非不安全。它忽略了检查它的返回值是不安全的。while (!feof(f))
fgets()
评论
基本上,要阅读所有行,您必须像这样使用算法。 使用文件末尾没有换行符的 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);
评论