【问题标题】:Different output on changing the position of fgets() function改变 fgets() 函数位置的不同输出
【发布时间】:2020-09-18 07:54:27
【问题描述】:

当 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);
}

【问题讨论】:

  • 请看下面我的回答。 fgets 从流中读取一行 tell \n 或已达到限制字符。当 fget 到达 eof 时,它将返回 null。查看我的内联 cmets
  • 贴出的代码无法编译!首先是因为它缺少所需的头文件所需的 #include 语句。其次是因为函数main()(对于所有C语言有效签名)返回一个int
  • 数组 s[] 永远不会等于 NULL,因此发布的代码包含逻辑错误

标签: c loops file-handling


【解决方案1】:

s!=NULL 将数组 s 的地址与 NULL 进行比较,NULL 永远不会匹配。

while(fgets(s,100,fp))!=NULL)fgets() 的返回值与 NULL 进行比较,NULL 在 EOF 或错误时为 NULL。

搜索:

手册页 fgets

【讨论】:

    【解决方案2】:

    代码 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)。所以你输入while loops!=null 然后在/*3*/ 中你在stdoutput 中打印这个并返回到/*2*/ 点询问s != null 并再次得到s 不是@ 的相同答案987654333@。因此,您将永远陷入这个无限循环。

    代码 2 中,在点 /*1*/ 中,您正在从输入流中重写一行并询问它是否不是 nullfgets() 成功完成后,fgets() 将返回 s。如果流位于end-of-file,则应设置流的文件结束指示符并且fgets() 应返回null pointer。如果出现read error,则应设置流的错误指示符,fgets() 应返回null pointer,并应设置errno 以指示错误。在某些时候,您将到达eof,而fgets() 将返回null,然后您将退出循环。如需进一步阅读,请参阅link 中的手册页

    【讨论】:

    • 你至少应该检查fopen是否失败
    • @Jabberwocky - 感谢您的评论。我没有纠正或修复所有代码问题,我只是专注于他的问题。无论如何感谢您的评论。我将在代码中添加它。
    【解决方案3】:

    以下建议的代码:

    1. 干净编译
    2. 执行所需的功能
    3. 正确检查(并处理)来自fopen()fgets() 的错误
    4. 不再使用“幻数”
    5. 包含所需的头文件
    6. 包含main() 的有效签名
    7. 将正确的参数传递给fgets()
    8. 包括对puts() 的最终调用,以确保将输出流缓冲区刷新到终端
    9. 将我的 cmets 合并到 OPs 问题中

    现在,建议的代码:

    #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 );
    }
    

    【讨论】:

      猜你喜欢
      • 2018-10-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-01-17
      • 2019-08-03
      • 2019-06-02
      相关资源
      最近更新 更多