C 用户仅输入整数,来自 scanf 的 return 值

C user input only integers, return value from scanf

我正在尝试获取一些用户输入,我想确保他们输入的是整数,如果他们不输入,我会要求他们再次输入(循环直到他们输入正确)。

我发现了很多不同的方法来做到这一点;有些比其他的更复杂。但我发现这种方法似乎有效。

但我真的不明白为什么要在代码中测试它:

scanf("%d%c", &num, &term) != 2

我能理解scanf输出匹配分配成功的项目数,但我不明白为什么它输出2如果它是一个整数。

C 中的代码是:

int main(void)
{
    int num;
    char term;

    if (scanf("%d%c", &num, &term) != 2 || term != '\n')
        printf("failure\n");
    else
        printf("valid integer followed by enter key\n");
}

试图将其放入循环中:

int main(void){

int m, n, dis;
char m_check, n_check, dis_check;

do{
    m = 0; n = 0; dis = 0;
    m_check = ' '; n_check = ' '; dis_check = ' ';

printf("Please enter number of rows m in the matrix (integer): ");
if(scanf("%d%c", &m, &m_check) !=2 || m_check != '\n')
        m_check = 'F';

printf("Please enter number of columns n in the matrix (integer): ");
if(scanf("%d%c", &n, &n_check) !=2 || n_check != '\n')
            n_check = 'F';

printf("Should the random numbers come from a uniform or normal distribution?... 
Please press 1 for uniform or 2 for normal: ");
if(scanf("%d%c", &dis, &dis_check) !=2 || dis_check != '\n' || dis != 1 || dis !=2)
            dis_check = 'F';

}while(m_check == 'F'  || n_check == 'F' || dis_check == 'F');

我试过只输入 m = 3、n = 3、dis = 2,然后循环重新开始并要求我输入行数。如果我被要求按 f 或其他东西,它就会开始疯狂地循环打印 printf 语句 :)

scanf returns 它转换的字段数。您有格式字符串 %d%c;它有:

  1. %d - 第一个字段
  2. %c - 第二个字段

所以scanfreturns 2.

如果用户输入数字,例如123 并按 Enter,您的 num 将等于 123,而 term 将等于 \n

如果用户输入的数字末尾有乱码,例如123garbage 并按 Enter,您的 num 将等于 123term 将等于 g,并且arbage\n 将保留在输入缓冲区中。

在这两种情况下,scanf 读取一个 int 和一个 char,所以它 returns 2.

另一个例子:用户输入 garbage123。在这种情况下,scanf 将无法读取整数,而 return 0.

因此您的代码会检查两种不同形式的错误输出。

scanf("%d%c", &num, &term) != 2 

这会检查 scanfreturn 值。它将正确匹配 return 个参数。因此,如果输入 integer 和字符,它们将存储在变量 numtermscanf returns 2 中。

如果两个参数都没有正确匹配,

scanf 将不会 return 2,在这种情况下,failure 将显示为输出。

输入一个整数将匹配格式化程序 %d,并将值赋给变量 num%c 格式化程序将采用换行符 ('\n') 并将其存储在变量 term 中。 scanf returns 2 导致正确分配的 2 个元素(numterm

如果您不输入整数,格式化程序 %d 将无法正确匹配,scanf 也不会 return 2,产生失败

编辑:您的 do-while 循环变得疯狂,因为您在上次 scanf 中的条件是错误的 (dis != 1 || dis !=2)。应该是

if(scanf("%d%c", &dis, &dis_check) !=2 || dis_check != '\n' || (dis != 1 && dis !=2))

糟糕 - 现在看到 OP 想知道为什么接近失败并且不一定在寻找操作方法。将其作为参考,因为它确实断言了基本问题:scanf()。不要将其用于 user 输入。


如果代码确实需要 "get some user input, and wants to make sure that they enter integers",则使用 fgets() 获取行并 然后 处理输入。

将用户输入与 scanning/parse 混合使用总是会导致某些用户输入无法通过检查、stdin 中的额外用户输入或不正确地等待更多输入。

// true implies success
bool Read_int(int *value) {
  char buffer[100];
  if (fgets(buffer, sizeof buffer, stdin) == NULL) return false; // EOF or error

  // Now parse the input
  char *endptr;
  errno = 0;
  long number = strtol(buffer, &endptr, 10);
  if (errno)                                return false; // long overflow
  if (number < INT_MIN || number > INT_MAX) return false; // int overflow
  if (endptr == buffer)                     return false; // No conversion
  while (isspace((unsigned char) *endptr)) endptr++;
  if (*endptr)                              return false; // non-white-space after number
  *value = (int) number;
  return true;
}