改变 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*/ 中,您正在重写输入流中的一行并询问它是否不是 nullfgets() 成功完成后,fgets() 应 return s。如果流位于 end-of-file,则应设置流的文件结束指示符,并且 fgets() 应 return 和 null pointer。如果出现 read error,则应设置流的错误指示符,fgets() 应 return 和 null pointer,并应设置 errno 以指示错误。在某些时候,您将到达 eof 并且 fgets() 将 return null 然后您将退出循环。如需进一步阅读,请参阅 link

中的手册页

以下建议代码:

  1. 干净地编译
  2. 执行所需的功能
  3. 正确检查(并处理)来自 fopen()fgets()
  4. 的错误
  5. 不再使用 'magic' 个数字
  6. 包括所需的头文件
  7. 包含 main()
  8. 的有效签名
  9. 将正确的参数传递给 fgets()
  10. 包括对 puts() 的最终调用以确保将输出流缓冲区刷新到终端
  11. 合并我对 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 );
}