使用fgetc(stdin)时的未定义行为

时间:2018-03-13 05:22:00

标签: c stdin fgetc fflush

在提出这个问题之前,我读过:fgetc(stdin) in a loop is producing strange behaviour。我正在编写一个程序来询问用户是否要退出。这是我的代码:

#include<stdio.h>
#include<stdlib.h>

int ask_to_exit()
{
    int choice;
    while(choice!='y'||choice!='n')
    {   printf("Do you want to continue?(y/n):");
        while((fgetc(stdin)) != '\n');
        choice = fgetc(stdin);
        if(choice=='y') return 0;
        else if(choice=='n') return 1;
        else printf("Invalid choice!\n");
    }
}

int main()
{
    int exit = 0;
    while(!exit)
    {
        exit = ask_to_exit();
    }
    return 0;
}

由于fflush(stdin)是未定义的行为,我没有使用它。在另一个问题中遵循解决方案后,我仍然得到错误。以下是上述计划的试运行:

$./a.out
Do you want to continue?(y/n):y<pressed enter key>
<pressed enter key>
Invalid choice!
Do you want to continue?(y/n):y<pressed enter key>
<pressed enter key>
Invalid choice!
Do you want to continue?(y/n):n<pressed enter key>
<pressed enter key>
Invalid choice!
Do you want to continue?(y/n):n<pressed enter key>
n<pressed enter key>
<program exits>

2 个答案:

答案 0 :(得分:1)

在检查choice的值之前,您需要获取一些输入,否则它将被取消初始化。而且,在抓取第一个字符之前,你正在消耗剩余的输入,你应该在以下之后完成:

int ask_to_exit()
{
    int choice;

    do
    {
        printf("Do you want to continue?(y/n):");
        choice = fgetc(stdin);

        while (fgetc(stdin) != '\n');

        if (choice == 'y') {
            return 0;
        } else if (choice == 'n') {
            return 1;
        } else {
            printf("Invalid choice!\n");
        }
    } while (1);
}

输出中:

Do you want to continue?(y/n):g
Invalid choice!
Do you want to continue?(y/n):h
Invalid choice!
Do you want to continue?(y/n):j
Invalid choice!
Do you want to continue?(y/n):k
Invalid choice!
Do you want to continue?(y/n):m
Invalid choice!
Do you want to continue?(y/n):y
Do you want to continue?(y/n):y
Do you want to continue?(y/n):y
Do you want to continue?(y/n):n
Press any key to continue . . .

答案 1 :(得分:0)

我在您的代码中看到以下问题。

  1. 您在初始化之前使用choice
  2. 在阅读choice
  3. 之前,您正在跳过一行输入

    @WhozCraig发现错误:

    choice!='y'||choice!='n'永远是真的。

    我建议:

    int ask_to_exit()
    {
       int choice;
       while ( 1 )
       {
          printf("Do you want to continue?(y/n):");
          choice = fgetc(stdin);
          if ( choice == 'y' )
          {
             return 0;
          }
          if ( choice == 'n' )
          {
             return 1;
          }
    
          printf("Invalid choice!\n");
    
          // Skip rest of the line.
          int c;`
          while( (c = fgetc(stdin)) != EOF && c != '\n');
    
          // If EOF is reached, return 0 also.
          if ( c == EOF )
          {
             return 0;
          }
       }
    }