使用 %d 跳过字符输入的 scanf

Skipping scanf for character input with %d

  int valid = 0;
  while (!valid) {

    printf("\nEnter number of characters (1-30)> ");
    scanf("%d", & n);
    printf("\nInclude numbers (Y/N)> ");
    scanf(" %c", & nf);
    printf("\nInclude symbols (Y/N)> ");
    scanf(" %c", & sf);
    //cond1 and cond2 initialized here
    if (cond1 && cond2)
      valid = 1;
    else
      printf("Invalid input");
  }

我需要为第一个整数扫描实现错误输入检测功能。如果用户输入的是字符而不是整数,则跳过第二个 scanf,直接进入第三个 scanf。如果在 %d 上输入字符,我该如何阻止这种情况发生?如果用户输入的是字符而不是数字,我想再次请求输入

只需检查 scanf() 的 return 值,在您的情况下:

if ((scanf("%d", &n) != 1) /* should return 1 if 1 int is read */
{ 
  fprintf(stderr,"Input not a number\n");
  exit(EXIT_FAILURE) /* include stdlib or just use return */
}

请注意,在大数的情况下,scanf() 不会针对 算术溢出 提供任何保护。您可能想使用 fgets() 并稍后使用 strtol() 等函数解析该字符串以确保安全。

示例:https://godbolt.org/z/oaMhac983

如果您想再次要求输入,我建议您改用 fgets(),然后检查该字符串是否为非数字字符。

您可以使用 strspn(),它 return 是第一个参数中出现在第二个参数中的字符数。

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

#define MAX_N 13 /* save space [=11=] and \n */

int main(void) {
  int num = 0;
  char n[MAX_N] = {0};
  char *numbers = "-+0123456789";

  while (1) {
    if (fgets(n, MAX_N, stdin) == NULL) /* check return value of fgets() */
    {
      exit(EXIT_FAILURE);
    }
    if (strspn(n, numbers) ==
        strlen(n) - 1) /* only numbers were read (exclude '\n')*/
    {
      if (sscanf(n, "%d", &num) != 1) /* check return value of scanf() */
      {
        exit(EXIT_FAILURE);
      }
      break;
    }
  }

  printf("%d\n", num);

  return 0;
}

示例:https://godbolt.org/z/d5KTrTGGE

你的意思好像是下面这样

#include <stdio.h>

int main(void) 
{
    int n;
    const int MIN = 1, MAX = 30;
    
    do
    {
        printf( "\nEnter number of characters (%d-%d)> ", MIN, MAX );
        
        if ( scanf( "%d", &n ) != 1 )
        {
            clearerr( stdin );
            scanf( "%*[^\n]" );
            scanf( "%*c" );
            n = 0;
        }
    } while ( n < MIN || MAX < n );
    
    printf( "n = %d\n", n );
    
    return 0;
}

程序输出可能看起来像

Enter number of characters (1-30)> Hello
Enter number of characters (1-30)> 0
Enter number of characters (1-30)> 31
Enter number of characters (1-30)> Bye
Enter number of characters (1-30)> 10
n = 10

或类似

#include <stdio.h>

int main(void) 
{
    int n = 0;
    const int MIN = 1, MAX = 30;
    
    printf( "\nEnter number of characters (%d-%d)> ", MIN, MAX );
        
    if ( scanf( "%d", &n ) != 1 )
    {
        clearerr( stdin );
        scanf( "%*[^\n]" );
        scanf( "%*c" );
        n = 0;
    }

    char nf, sf;
    
    if ( n != 0 )
    {
        printf("\nInclude numbers (Y/N)> ");
        scanf( " %c", &nf );
    }
    else
    {
        printf("\nInclude symbols (Y/N)> ");
        scanf(" %c", &sf);
    }
    
    return 0;
}

How can I stop this from happening in case of a character input on %d?

检查 scanf() 的 return 值。

scanf("%d", &n); returns 不同条件下的 3 个值中的第 1 个:

1 扫描成功。在 n.
中扫描了 int 值 0 由于非数字输入(OP 感兴趣的情况),扫描失败。 n 中的值未更改。
由于没有更多输入(文件结束),EOF 扫描失败。 n 中的值未更改。
由于输入错误导致 EOF 扫描失败(罕见)。 n 中的值不确定。

do { 
  printf("\nEnter number of characters (1-30)> ");
  int retval = scanf("%d", &n);
  if (retval == EOF) {
    printf("End of file or input error.  Quitting\n");
    exit(-1);
  }
  if (retval == 0) {
    // read in rest of line (except \n) and toss it.
    scanf("%*[^\n]");
    continue; 
  }
  // If here, valid `int` input read, now testfor range.
} while (n < 1 || n > 30);

....

考虑编写 以编写提示并阅读 int