简体   繁体   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");
  }

I need to implement a faulty input detection functionality for the first integer scan.我需要为第一个 integer 扫描实现错误输入检测功能。 If the user enters a character instead of an integer the second scanf is skipped and it goes directly to the 3rd scanf.如果用户输入一个字符而不是 integer,则跳过第二个 scanf 并直接进入第三个 scanf。 How can I stop this from happening in case of a character input on %d?如果在 %d 上输入字符,如何阻止这种情况发生? I want to ask for the input again if the user enters a character instead of a number如果用户输入字符而不是数字,我想再次要求输入

Just check the return value of scanf() , in your case:只需检查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 */
}

Note that scanf() doesn't provide any protection from arithmetic overflow , in the case of a big number.请注意,在大数字的情况下, scanf()不提供任何算术溢出保护。 You might want to use fgets() and later parse that string with a function such as strtol() for safety.您可能希望使用fgets()并稍后使用 function 解析该字符串,例如strtol()以确保安全。

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

If you want to ask for input again, I would suggest that you use fgets() instead and later check that string for non-digit characters.如果您想再次要求输入,我建议您改用fgets()并稍后检查该字符串是否有非数字字符。

You can use strspn() ,it returns the number of characters from the first argument that are present in the second argument.您可以使用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;
}

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

It seems you mean something like the following看来您的意思类似于以下内容

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

The program output might look like程序 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

Or something like或者类似的东西

#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?如果在 %d 上输入字符,如何阻止这种情况发生?

Check the return value of scanf() .检查scanf()的返回值。

scanf("%d", &n); returns 1 of 3 values under various conditions:在各种条件下返回 3 个值中的 1 个:

1 Scanning succeed. 1 扫描成功。 Scanned int value in n . n中扫描的int值。
0 Scanning failed due to non numeric input (the case OP is interested in). 0 由于非数字输入而导致扫描失败(OP 感兴趣的情况)。 Value in n is unchanged. n中的值不变。
EOF Scanning failed due to no more input (End-of-file).由于没有更多输入(文件结尾),EOF 扫描失败。 Value in n is unchanged. n中的值不变。
EOF Scanning failed due to input error (rare).由于输入错误(罕见),EOF 扫描失败。 Value in n is indeterminate. 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);

....

Consider coding a helper function to write a prompt and read an int .考虑编写一个帮助程序 function来编写提示并读取int

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

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