验证do-while循环C中的输入类型

时间:2015-07-26 02:17:34

标签: c loops infinite-loop

基本上,我需要确保输入是整数,如下所示:

do {
    printf("Enter > ");
    scanf("%d", &integer);
} while (/* user entered a char instead of an int */);

我尝试了各种方法,但在尝试输入char时,它总是以运行时错误或无限循环结束。我知道fflush(stdin)是一个未定义的行为,最好不要将它包含在我的代码中以防止任何错误加上它在VS2015中不再有用由于某些原因。< / p>

以下代码是我尝试过的方法:

typedef enum {false, true} bool;
int ipt;
char c;
bool wrong_ipt;

do {
    c = '\0';
    printf("Enter > ");
    scanf("%d%c", &ipt, &c); //infinite loop occurs while a char has been entered
} while (c != '\n');

do {
    c = '\0';
    printf("Enter > ");
} while (scanf("%d", &ipt) != EOF);

do {
    wrong_ipt = false;
    do {
        ipt = NULL;
        printf("Enter > ");
        scanf("%d", &ipt);
        if (ipt == NULL) {
            wrong_ipt = true;
            break;
        }
    } while (ipt == NULL);
} while (wrong_ipt);

当用户在 C 中输入fflush(stdin)时,除char之外还有其他可以用来阻止无限循环吗?

谢谢

4 个答案:

答案 0 :(得分:6)

问题是“scanf()”可能会在输入缓冲区中留下未读数据。因此,“无限循环”。

另一个问题是您应该验证scanf()的返回值。如果你期望一个整数值...并且scanf返回“0”项读取...那么你就知道出了什么问题。

以下是一个例子:

#include <stdio.h>

void discard_junk () 
{
  char c;
  while((c = getchar()) != '\n' && c != EOF)
    ;
}

int main (int argc, char *argv[])
{
  int integer, i;
  do {
      printf("Enter > ");
      i = scanf("%d", &integer);
      if (i == 1) {
        printf ("Good value: %d\n", integer);
      }
      else {
        printf ("BAD VALUE, i=%i!\n", i);
        discard_junk ();
      }
   } while (i != 1);

  return 0;
}

示例输出:

Enter > A
BAD VALUE, i=0!
Enter > B
BAD VALUE, i=0!
Enter > 1
Good value: 1

'希望有所帮助!

答案 1 :(得分:1)

格式说明符%d告诉scanf命令行中需要一个整数值。当用户输入一行数据时,它将作为字符串读取,然后scanf会尝试理解输入的字符串是否可以解释为整数的十进制数字。

如果此解释成功,则找到的值存储在作为参数传递的整数变量中。

scanf执行的权限替换次数由该函数以int值的形式检索。由于您只需要一个输入,因此值1表示一切正常。

因此,如果出现错误,例如,用户输入了无效的整数,则scanf返回的数字小于格式说明符的数量。在这种情况下,小于1的值会通知发生错误:

 int ipt, succeded;
 do {
    printf("ipt? ");
    succeded = scanf("%d", &ipt);
    if (succeded < 1) {    // Clean the input
      while (getchar() != '\n') 
        ;
    }
 } while(succeded < 1);

答案 2 :(得分:1)

你的根本错误是你永远不会告诉你的程序消耗无效输入。换句话说,你告诉程序:

  • 如果有,则读取整数。 (否则什么都不读)
  • 如果没有得到整数,请返回步骤1.

我假设你正在做的想法

  • 读取输入,如果是整数,则存储它。
  • 如果不是整数,请返回步骤1.

所以你需要做的是重写你的代码,以便它做你想做的事情(或者提出一些其他方法,如在另一个答案中)。也就是说,将您的程序写入:

  • 阅读一些输入内容。 (例如一条线)
  • 扫描输入以查看它是否为整数,然后存储它。
  • 如果不是整数,请返回步骤1.

您可能会觉得有用的一些相关功能有fgetssscanfatoi。 (另外,试着抵制编写错误代码的诱惑;例如,如果您打算阅读一行输入,请确保实际执行正确。很多人是懒惰的,如果行很长,它会做错事;例如只读取部分行,或导致缓冲区溢出)

答案 3 :(得分:0)

我知道我回答这个问题有点晚了,但是您可以减少使用循环,而使用跳转语句,然后仅使用一个if语句检查错误的输入并仍然获得相同的结果

      enter: printf("Enter > ");
      i = scanf("%d", &integer);
      if (i != 1) {
        printf ("BAD VALUE, i=%i!\n", i);
        discard_junk ();
        goto enter:
      }
      printf ("Good value: %d\n", integer);