【问题标题】:How to use fgets in a loop?如何在循环中使用 fgets?
【发布时间】:2017-05-04 21:57:17
【问题描述】:

我想在这里使用循环。但是我的第二个 fget 不能正常工作!
在第一个循环中没关系!但之后它会跳过第二个 fget!
如何解决?
谢谢

#include<stdio.h>
#include<string.h>
int main (void)
{
char first_line[1000];
char second_line[2];
int i,n,j,k;
int count=0,flag=0;
scanf("%d ",&k);
for(int m=0; m<k; m++)
{
    fgets(first_line, 1000, stdin);
    fgets(second_line, 2, stdin);
    for(i=0; i<strlen(first_line); i++)
    {
        if(second_line[0]==first_line[i])
        {
            flag=1;
            count++;
        }
    }
    first_line[strlen(first_line)-1] = '\0';
    if(flag==1)
        printf("Occurrence of '%c' in %s = %d",second_line[0],first_line,count);

    else
        printf("%c isn't present",second_line[0]);
    count=0;
    flag=0;
}

return 0;
}

【问题讨论】:

  • char second_line[2]; 只能容纳一个真实角色。因此,如果一行中有一个字母和一个换行符,则在下一个循环的fgets 中会输入一个换行符。
  • 我已经做过一次了! stackoverflow.com/q/43789708/7761980
  • 请注意,您应该检查每个fgets()调用的返回值。

标签: c string loops for-loop fgets


【解决方案1】:

问题是数组second_line 被声明为只有两个元素。

char second_line[2];

因此在这次通话之后

fgets(second_line, 2, stdin);

它无法容纳仍在输入缓冲区中的换行符。由于输入缓冲区中存在换行符,fgets 的第一次调用读取了一个空字符串。

至少你应该写

char second_line[3];

//...

fgets(second_line, sizeof( second_line ), stdin);

考虑到这种从字符串中删除换行符的方法通常是错误的

first_line[strlen(first_line)-1] = '\0';

因为字符串不一定包含换行符。

改为写

first_line[ strcspn( first_line, "\n" ) ] = '\0';

【讨论】:

    【解决方案2】:

    在这种情况下,第二行实际上是一个字符。 C中有 fgetc() ,它接受一个字符。在这种情况下,可以使用它来代替 fgets()。除了第二行的 fgets() 问题之外,scanf("%d ", ) 语句也存在问题。格式说明符后的空格会导致您没有预料到的行为。此外,在输入数值后输入的换行符也会导致跳过提示行为。 这可能不是最佳解决方案,但以下代码解决了这种跳过提示行为。在 scanf() 和 fgetc() 之后有 fgets(caGarbage, sizeof caGarbage, stdin) 语句。该语句使用换行符,从而解决了这种跳过提示行为。

     #include<stdio.h>
     #include<string.h>
    
     int 
     main(void)
     {
         char first_line[1000];
         char cC;
         char caGarbage[50];
         int i,n,j,k;
         int count=0,flag=0;
    
         printf("Enter count:");
         scanf("%d",&k);
         fgets( caGarbage, sizeof caGarbage, stdin);//Consumes newline character.
    
         for(int m=0; m<k; m++)
         {
             printf("Insert first line:");
             fgets(first_line, 1000, stdin);
    
             printf("Insert a character:");
             cC = fgetc( stdin );
    
             fgets( caGarbage, sizeof caGarbage, stdin); //Consumes newline character
    
             for(i=0; i<strlen(first_line); i++)
             {
                if(cC == first_line[i])
                {
                    flag=1;
                    count++;
                }
             }
    
             first_line[strcspn( first_line, "\n" )] = '\0';
    
             if(flag==1)
                printf("Occurrence of '%c' in %s = %d",cC,first_line,count);
             else
                printf("%c isn't present",cC);
    
             printf("\n");
    
             count=0;
             flag=0;
         }
    
         return 0;
     }
    

    【讨论】:

    • 你能说详细点吗? scanf("%d",&k) 和 cC = fgetc(stdin) 占用了多少空间/新行?
    • 因为k是整数,所以取数值,在最大最小整数的范围内。 fgetc() 只需要一个字符。在这两种情况下,换行符都被发送到输入缓冲区。输入黄油中的换行符被转移到下一个输入语句。
    • 为什么这里没有采用 fgets(caGarbage, sizeof caGarbage, stdin);在 fgets(first_line, 1000, stdin) 之后;消耗换行符? @Nguai
    • @TonmoyMohajan - 一个好问题!!!在 Linux 上做man fgets。它说: fgets() 从流中最多读入一个小于 size 的字符,并将它们存储到 s 指向的缓冲区中。在 EOF 或换行符后停止读取 ` 如果读取换行符,则将其存储到缓冲区中。` 终止空字节 ('\0') 存储在缓冲区中的最后一个字符之后。因此,在这种情况下,换行符将存储到 first_line 中。这就是 fgets() 的优点。它处理换行符,不像 scanf() 和 fetc()。
    【解决方案3】:

    你不了解scanf()和fgets()的细节 当您从键盘输入一系列字符时,这些字符会保存在 inputbuf 中,而不是保存到您的进程中。当您输入 [Enter] 时,inputbuf 中的字符被发送到您的进程(第一个是 scanf(),第二个是 fgets()),scanf() 可以选择数字,inputbuf 中的空格键。但它跳过了 Enter 并停止了,所以 '\n' 仍在 inputbuf 中,但 fgets() 没有。 fgets() 获取 inputbuf 中的任何字符,包括 ' ' 和 '\n'(它在获取 '\n' 时停止)。
    当您同时使用它们时,scanf() 和 fgets() 之间的区别令人烦恼。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-12-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多