改变 fgets() 函数位置的不同输出
Different output on changing the position of fgets() function
当 fgets() 包含在 while 循环中时,输出是正确的,但将其放在外面会使它成为无限循环。谁能解释一下为什么?
main()
{
FILE *fp=fopen("myfile.txt","r");
char s[100];
fgets(s,50,fp);
while(s!=NULL) //infinte loop
puts(s);
/* while((fgets(s,100,fp))!=NULL)
puts(s);
This runs fine */
fclose(fp);
}
s!=NULL
将数组 s 的地址与 NULL 进行比较,永远不会匹配。
while(fgets(s,100,fp))!=NULL)
比较fgets()
的return和NULL,在EOF或错误时为NULL。
搜索:
man page fgets
代码 1
main()
{
FILE *fp = NULL;
FILE *fp=fopen("myfile.txt","r");
if(!fp)
{
/*error occured during fopen()! abort*/
printf("Error while openning the file!\n");
return 1;
}
char s[100];
fgets(s,50,fp); /*1*/
while(s != NULL) /*2*/
{
puts(s); /*3*/
}
fclose(fp);
}
代码 2
main()
{
FILE *fp=fopen("myfile.txt","r");
char s[100];
while((fgets(s,100,fp)) != NULL) /*1*/
{
puts(s); /*2*/
}
fclose(fp);
}
在 代码 1 中,当您到达点 /*1*/
时,您的缓冲区 s
不为空并且包含一些字符串(它不是 null
).所以你用 s!=null
输入 while loop
然后在 /*3*/
你在标准输出中打印这个并且 return 指向 /*2*/
询问是否 s != null
并再次得到 s
不是 null
的相同答案。因此你永远陷入了这个无限循环。
在 代码 2 中,在点 /*1*/
中,您正在重写输入流中的一行并询问它是否不是 null
。 fgets()
成功完成后,fgets()
应 return s
。如果流位于 end-of-file
,则应设置流的文件结束指示符,并且 fgets()
应 return 和 null pointer
。如果出现 read error
,则应设置流的错误指示符,fgets()
应 return 和 null pointer
,并应设置 errno
以指示错误。在某些时候,您将到达 eof
并且 fgets()
将 return null 然后您将退出循环。如需进一步阅读,请参阅 link
中的手册页
以下建议代码:
- 干净地编译
- 执行所需的功能
- 正确检查(并处理)来自
fopen()
和 fgets()
的错误
- 不再使用 'magic' 个数字
- 包括所需的头文件
- 包含
main()
的有效签名
- 将正确的参数传递给
fgets()
- 包括对
puts()
的最终调用以确保将输出流缓冲区刷新到终端
- 合并我对 OP 问题的评论
现在,建议的代码:
#include <stdio.h>
#include <stdlib.h>
#define BUF_LEN 100
int main( void )
{
FILE *fp = fopen( "myfile.txt", "r" );
if( ! fp )
{
perror( "fopen to read file: myfile.txt failed" );
exit( EXIT_FAILURE );
}
char s[ BUF_LEN ];
while( fgets( s, sizeof(s), fp ) )
{
puts( s );
}
puts( "" );
fclose( fp );
}
当 fgets() 包含在 while 循环中时,输出是正确的,但将其放在外面会使它成为无限循环。谁能解释一下为什么?
main()
{
FILE *fp=fopen("myfile.txt","r");
char s[100];
fgets(s,50,fp);
while(s!=NULL) //infinte loop
puts(s);
/* while((fgets(s,100,fp))!=NULL)
puts(s);
This runs fine */
fclose(fp);
}
s!=NULL
将数组 s 的地址与 NULL 进行比较,永远不会匹配。
while(fgets(s,100,fp))!=NULL)
比较fgets()
的return和NULL,在EOF或错误时为NULL。
搜索:
man page fgets
代码 1
main()
{
FILE *fp = NULL;
FILE *fp=fopen("myfile.txt","r");
if(!fp)
{
/*error occured during fopen()! abort*/
printf("Error while openning the file!\n");
return 1;
}
char s[100];
fgets(s,50,fp); /*1*/
while(s != NULL) /*2*/
{
puts(s); /*3*/
}
fclose(fp);
}
代码 2
main()
{
FILE *fp=fopen("myfile.txt","r");
char s[100];
while((fgets(s,100,fp)) != NULL) /*1*/
{
puts(s); /*2*/
}
fclose(fp);
}
在 代码 1 中,当您到达点 /*1*/
时,您的缓冲区 s
不为空并且包含一些字符串(它不是 null
).所以你用 s!=null
输入 while loop
然后在 /*3*/
你在标准输出中打印这个并且 return 指向 /*2*/
询问是否 s != null
并再次得到 s
不是 null
的相同答案。因此你永远陷入了这个无限循环。
在 代码 2 中,在点 /*1*/
中,您正在重写输入流中的一行并询问它是否不是 null
。 fgets()
成功完成后,fgets()
应 return s
。如果流位于 end-of-file
,则应设置流的文件结束指示符,并且 fgets()
应 return 和 null pointer
。如果出现 read error
,则应设置流的错误指示符,fgets()
应 return 和 null pointer
,并应设置 errno
以指示错误。在某些时候,您将到达 eof
并且 fgets()
将 return null 然后您将退出循环。如需进一步阅读,请参阅 link
以下建议代码:
- 干净地编译
- 执行所需的功能
- 正确检查(并处理)来自
fopen()
和fgets()
的错误
- 不再使用 'magic' 个数字
- 包括所需的头文件
- 包含
main()
的有效签名
- 将正确的参数传递给
fgets()
- 包括对
puts()
的最终调用以确保将输出流缓冲区刷新到终端 - 合并我对 OP 问题的评论
现在,建议的代码:
#include <stdio.h>
#include <stdlib.h>
#define BUF_LEN 100
int main( void )
{
FILE *fp = fopen( "myfile.txt", "r" );
if( ! fp )
{
perror( "fopen to read file: myfile.txt failed" );
exit( EXIT_FAILURE );
}
char s[ BUF_LEN ];
while( fgets( s, sizeof(s), fp ) )
{
puts( s );
}
puts( "" );
fclose( fp );
}