C 使用feof()从文件读取并退出循环
说明为什么将C 使用feof()从文件读取并退出循环,c,file-io,fgets,feof,C,File Io,Fgets,Feof,说明为什么将feof()用作循环的退出指示器是件坏事 不安全==>在while中有一个feof()签入,在while中有一个fgets() 安全==>拥有fgets()=空检入while本身 我应该看到不安全的代码执行额外的while循环迭代,但两者执行相同(并且正确)的循环数。有人能帮我理解这里发生了什么吗 编辑:这个链接确实说明了为什么会发生这种情况,但我需要在下面找到正确的答案才能准确地理解我所读的内容。我的文件在最后一行没有“\n”,因此得到了相同的结果 以下是文件内容: abcd ef
feof()
用作循环的退出指示器是件坏事
不安全==>在while中有一个feof()
签入,在while中有一个fgets()
安全==>拥有fgets()=空
检入while本身
我应该看到不安全的代码执行额外的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()
#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;
}
testUnsafe()
的输出:
testSafe()
的输出:
我尝试了你的两个例子,得到了与你不同的结果。函数
testUnsafe()
将文件的最后一行打印了两次。这有两个原因
feof()
函数将返回一个非零值testUnsafe()
#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;
}
testUnsafe()
的输出:
testSafe()
的输出:
如果文本文件在最后一行文本后没有换行符,则testUnsafe()
函数在读取最后一行文本时将到达文件末尾,并生成所显示的三行输出
如果文本文件在最后一行文本后有换行符,则函数将读取最后一行,包括换行符,而不会到达文件末尾。当它再次进入while()
循环时,它读取零个字符,设置文件结束标志,并输出上一轮仍在缓冲区中的最后一行
while(!feof(f))
构造本身并不不安全。它忽略了检查不安全的fgets()
的返回值。如果文本文件在最后一行文本后没有换行结束,那么testUnsafe()
函数在读取最后一行时将到达文件末尾,并生成您显示的三行输出
如果文本文件在最后一行文本后有换行符,则函数将读取最后一行,包括换行符,而不会到达文件末尾。当它再次进入while()
循环时,它读取零个字符,设置文件结束标志,并输出上一轮仍在缓冲区中的最后一行
while(!feof(f))
构造本身并不不安全。它忽略了检查不安全的fgets()
的返回值。基本上,要读取所有行,必须像那样使用algo。
如果文件末尾没有换行符,则确保加载所有行
这里的例外是最后一行不确定末尾是否有LF
除了检查缓冲区溢出等优化内存使用的方法外,您还可以在将缓冲区添加到数组中之前调用realloc()来修剪缓冲区
buffer = (char*)malloc(bufferSize);
while(fgets(buffer, bufferSize, file) != NULL) {
//here store your pointer in array...
buffer = (char*)malloc(bufferSize);
};
free(buffer);
基本上,要阅读所有的行,你必须像那样使用algo。 如果文件末尾没有换行符,则确保加载所有行 这里的例外是最后一行不确定末尾是否有LF 除了检查缓冲区溢出等优化内存使用的方法外,您还可以在将缓冲区添加到数组中之前调用realloc()来修剪缓冲区
buffer = (char*)malloc(bufferSize);
while(fgets(buffer, bufferSize, file) != NULL) {
//here store your pointer in array...
buffer = (char*)malloc(bufferSize);
};
free(buffer);
尝试将文件放在netwrok驱动器上,在循环中进行某种暂停,并在读取文件时断开网线。抱歉,正如您所看到的,我不太擅长C语言来理解这里的问题,如果,也就是说,这不是一开始的讽刺。尝试将文件放在netwrok驱动器上,在循环中进行某种暂停,并在读取文件时断开网络电缆。抱歉,正如您所看到的,我不太擅长C来理解这里的问题,如果,也就是说,这不是一开始的讽刺。在@NisseEngström注释之后,这就是它不安全的原因。在最后一行之后没有
换行符
,打印了正确的3行。在选定的情况下(嵌入空字符),strlen(buf)
为0,因此if(buf[strlen(buf)-1]
为UB。@chux:你能给我一个链接,让我可以(轻松地)了解嵌入的空字符吗?我的谷歌搜索结果对我来说有点太难了。@chux的意思是一行,比如“\0一些文本\n”
其中fgets()
将读取并包括换行符
,但读取后,字符串函数将看到一个空字符串。我注意到了潜在的缺陷,但认为在本例中不会发生这种情况,因为即使是空行也会有一个换行符
,如果最后一个文本行缺少换行符
,则必须至少有一个其他字符。但正如@chux所说,它可以。在@NisseEngström注释之后,这就是它不安全的原因。在最后一行之后没有换行符
,正确的3行被打印出来。在选择的情况下(嵌入空字符),strlen(buf)
为0,因此if(bu
buffer = (char*)malloc(bufferSize);
while(fgets(buffer, bufferSize, file) != NULL) {
//here store your pointer in array...
buffer = (char*)malloc(bufferSize);
};
free(buffer);