繁体   English   中英

使用 %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");
  }

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

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

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()并稍后使用 function 解析该字符串,例如strtol()以确保安全。

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

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

您可以使用strspn() ,它返回第二个参数中存在的第一个参数的字符数。

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

#define MAX_N 13 /* save space \0 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;
}

程序 output 可能看起来像

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;
}

如果在 %d 上输入字符,如何阻止这种情况发生?

检查scanf()的返回值。

scanf("%d", &n); 在各种条件下返回 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);

....

考虑编写一个帮助程序 function来编写提示并读取int

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM