【问题标题】:fgets() isn't prompting user a second timefgets() 没有第二次提示用户
【发布时间】:2013-06-21 05:02:41
【问题描述】:

这是代码的编写方式。

int main()
{   
    char enteredName[30];
    char stringNum[4];
    char continueLetter = 0;
    int continueProgram = 0;
    int enteredAge;
    int i;

    do
    {
    memset(enteredName,'\0', 30);
    printf("Please enter a name: ");
    fgets(enteredName, 29, stdin);

    printf("\n\nNow please enter your age: ");
    fgets(stringNum, 3, stdin );

    for(i = 0; i < 30; i++)
    {
        if (enteredName[i] == '\n')
        {
            enteredName[i] = '\0';
            break;
        }
    }

    for(i = 0; i < 4; i++)
    {
        if (stringNum[i] == '\n')
        {
            stringNum[i] = '\0';
            break;
        }
    }

    enteredAge = atol(stringNum);
} while();

当我第二次运行循环时,我无法在 char 数组中输入新名称,它只会进入下一个提示符(年龄)。除非这个问题涉及链表,否则问题似乎出在其他问题上。你能帮我找出错误吗?谢谢!

【问题讨论】:

  • 感谢您的帮助,我必须道歉,但这不是整个代码;我认为这是主要问题的一部分。其余代码涉及一个用于“使用 Y/N 继续程序”的 char 变量。它没有像我的'for loops'那样检查'\n',所以我只是用一个简单的fflush修复它。再次感谢您的帮助,祝您有美好的一天!
  • 请注意,每次使用后都要检查fgets()的返回值。

标签: c


【解决方案1】:

如果您输入两位数的年龄,您的第二个 fgets 呼叫会留下等待从 stdin 读取的字符(特别是换行符)。

增加长度参数以匹配数组大小:

fgets(stringNum, 4, stdin);

或者更好:

fgets(stringNum, sizeof stringNum, stdin);

您可能希望对 enteredName 执行相同的操作。

来自fgets(3) man page

fgets() 函数读取最多比字符数少一个 size 从给定的流中指定并将它们存储在字符串中 str

您不需要像现在这样为空终止符保留额外的数组条目 - fgets 会自行正确处理。

【讨论】:

    【解决方案2】:

    问题是,您没有刷新输入缓冲区,这就是为什么fgets() 会直接将您带到第二个询问年龄的提示。这是遇到的常见问题,只需在fgets(); 之后添加fflush(stdin);//my compiler supports it。这里是对我有用的代码希望它也对你有用:

    编辑:有一个非常 useful post 提供有关 fflush() 的信息。正如所描述的那样,fflush 基本上是为了被调用到输出流。尽管一些编译器提供了对刷新 stdin 的支持,但这被认为是一个未定义的行为。在再次查看程序时,我发现使用sizeof 可以创造奇迹并且是有效的,因此,我已经将程序修改得更好。 sizeof 的使用也在此处的其中一个答案中有所描述。

    #include<stdio.h>
    #include<stdlib.h>
    int main()
    {   
        char enteredName[30];
        char stringNum[4];
        int continueProgram=0;
        int i;
    
       while(continueProgram<3)
          {
            setbuf(stdout,NULL);
        printf("Please enter a name: ");
        fgets(enteredName, sizeof enteredName, stdin);
        printf("\n\nNow please enter your age: ");
        fgets(stringNum,sizeof stringNum, stdin );
    
       for(i = 0; i < 30; i++)
        {
            if (enteredName[i] == '\n')
            {
                enteredName[i] = '\0';
                break;
            }
        }
    
        for(i = 0; i < 4; i++)
        {
            if (stringNum[i] == '\n')
            {
                stringNum[i] = '\0';
                break;
            }
        }
    
        //enteredAge = atol(stringNum);
        continueProgram++;
        }
        return 0;
    }
    

    【讨论】:

    • 谢谢老兄,fflush 可以创造奇迹。我发现的另一种方法是在底部放一个额外的 getchar,但这只会处理剩下的一个。我会多读一点,这很有用。
    【解决方案3】:

    问题是你不知道读取的字符串是否包含newline。如果它不包含newline,那么这将在下一次调用fgets 时被读取,并在其中留下一个空字符串。为防止出现这种情况,请检查该行末尾是否包含 newline 字符。如果不只是使用getchar() 和瞧!!(请注意,此解决方案仅对您的问题有效,而不是一般情况下)。这段代码是在读取stringNum字符串后添加的。

    if(stringNum[strlen(stringNum)-1]!='\n')
    {
        getchar();
    }
    

    发生这种情况是因为,如果年龄是两位数,那么 fgets 将读取到最后一个数字,而不是 newline 字符。因此,如果最后一个字符不是\n,您需要阅读它。如果年龄是个位数,则原程序运行良好。

    【讨论】:

      【解决方案4】:

      你试试下面这段代码:

      if(stringNum[strlen(arr)-1]=='\n')
           stringNum[strlen(arr)-1]='\0';
      else
           while(getchar()!='\n');
      

      每当您输入两位数的年龄时,您在按 Enter 时插入的换行符都会存储在缓冲区中。 上面这段代码的作用是,它将检查存储的最后一个字符是否用换行符填充,如果是,那么它将用空终止符替换它。 否则,它将继续从缓冲区读取,直到且除非换行符从缓冲区中删除。

      PS:如果您使用的是 borland,那么您将使用 fflush(stdin) 从缓冲区中清除任何额外的字符,如 PHlFounder 所示,但如果您碰巧使用 gcc,那么这种方法非常好。

      您还可以为这段代码创建一个函数或宏,并在每次需要时调用它,例如。

      void function(char * arr)
      {
              if(arr[strlen(arr)-1]=='\n')
                      arr[strlen(arr)-1]='\0';
              else
                      while(getchar()!='\n')
      }
      

      【讨论】:

        猜你喜欢
        • 2021-03-02
        • 2012-05-11
        • 2015-09-15
        • 2014-05-24
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多