【问题标题】:How to prevent non-numeric input in C & ask user input again如何防止 C 中的非数字输入并再次询问用户输入
【发布时间】:2020-11-27 19:41:57
【问题描述】:

其实我在谷歌上很容易找到类似的问题,但还是不能解决我的问题。

How to prevent non-numeric input in C?

upper-link 类似情况。

这是我的代码

#include <stdio.h>
int main()
{
    int n;
    printf("Enter 1 or 2?\n");
    scanf("%d", &n);
    while(n != 1 && n != 2)
    {
      printf("Please do not enter other characters\n");
      printf("Enter 1 or 2?\n");
      scanf("%d", &n);
    }
}

我希望如果用户输入其他数字(例如1、45、656)、字符(例如a、f、u、e)或字符串(例如apple),上层程序可以打印出错误信息并询问再次用户输入。

是的!如果用户输入其他数字,程序可以做我想做的事。 但!如果用户输入其他字符、字符串,程序会一直循环。

我需要向这个程序添加什么?

【问题讨论】:

  • 使用fgets 读取输入。然后用sscanf解析用fgets读取的字符串。检查sscanf 的返回值。如果输入是有效整数,则为1,否则为0
  • @kaylum 谢谢!但是啊……我可以不使用 fgets 吗?那是因为我在Youtube上找到的,如果我需要使用fgets,我需要声明一个char数组。它会影响我程序中的其他功能...
  • 它会影响我程序中的其他功能。这听起来不是不使用fgets 的好理由。使用fgets 是最好的方法,如果您认为有一些问题阻止您这样做,请提供确切的详细信息。我敢打赌,这个原因实际上是无效的。
  • 考虑使用fgets() 读取并使用strtol() 提取值并允许您检查下一个无法转换的字符。如果输入不好,真的很容易循环输入另一个字符串。
  • 谢谢!让我先试试 fgets 并改进我的程序!总之,似乎 fgets 是解决我的程序的最佳方法

标签: c loops input character


【解决方案1】:

如何防止 C 中的非数字输入并再次询问用户输入

不要使用scanf()**。使用 fgets().
scanf("%d", ...) 不会消耗非数字输入。取而代之的是,有问题的输入仍保留在 stdio 中,以供下一个 scanf() 使用。

代码不能阻止非数字输入,除非它锁定键不被按下。相反,阅读所有输入,识别非数字文本,扔掉它并向用户提供新输入的反馈。

创建一个辅助函数来控制对其余代码的影响。

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

// return -1 on EOF
int read_int_in_range(const char *prompt, const char *reprompt, int lo, int hi) {
  if (prompt) {
    fputs(prompt, stdout);
    fflush(stdout);
  }
  char buf[100];
  while (fgets(buf, sizeof buf, stdin)) {
    char *endptr;
    errno = 0;
    long val = strtol(buf, &endptr, 10);
    // no overflow, conversion occurred, in range 
    if (errno == 0 && endptr > buf && val >= lo && val <= hi) {
      // Tolerate trailing white-space.
      while (isspace((unsigned char ) *endptr)) {
        endptr++;
      }
      // No junk after the numeric text
      if (*endptr == '\0') {
        return (int) val;
      }
    }
    if (reprompt) {
      fputs(reprompt, stdout);
      fflush(stdout);
    }
  }
  return EOF; // or `INT_MIN` or TBD code to distinguish `int` from an error.
}

用法

const char *prompt = "Enter 1 or 2?\n";
const char *reprompt = "Please do not enter other characters\n" "Enter 1 or 2?\n";
int n = read_int_in_range(prompt, reprompt, 1, 2); 

**我建议不要在任何地方使用scanf() 来读取用户输入,直到人们了解它的弱点和限制。

【讨论】:

    【解决方案2】:

    scanf 用于格式化输入,即:您知道将收到什么输入,在这种情况下,用户可能输入除int 以外的其他内容,您的程序就会崩溃。因此,要处理该未知数,请将输入视为字符串,然后分析该字符串。在这种情况下,您可以捕获buf 中的输入并使用函数atoi 将其转换为int,如下所示:

    #include <stdio.h>
    #include <stdlib.h> /* for atoi */
    
    int main()
    {
        int n;
        char buf[10]; /* this is new */ 
        printf("Enter 1 or 2\n");
        /*scanf("%d", &n);*/
        fgets(buf, 10, stdin);
        n = atoi(buf);
        while(n != 1 && n != 2)
        {
            printf("Please do not enter other characters\n");
            printf("Enter 1 or 2?\n");
            /*scanf("%d", &n);*/
            fgets(buf, 10, stdin);
            n = atoi(buf);
        }
    }   
    

    【讨论】:

    • char buf[10]; 对于大型 int(32 位)来说太小了,"-2147483648\n" 至少需要 13 个。
    • "1x\n""1 2\n" 这样的输入,甚至可能"4294967297\n" 会在这里传递,因为atoi(buf) 有利于良好的输入,而不是错误的输入。
    • 你是 100% 正确的,但他期待 1 或 2。另外@andyzzsyk 阅读了atoi,这太糟糕了,使用strtol 而不是atoi,但为了我使用 atoi 的简单性。
    【解决方案3】:

    fgets 是执行此操作的方法,但想发布类似的内容以实际避免 fgets 要求。可能会有一些兴趣。附加部分应该已委托给某些函数,并且缓冲区大小可能不是 10。无论如何:

    #include <stdio.h>
    #include <string.h>
    #include <stdlib.h>
    
    #define endl "\n"
    
    int main (void)
    {
        int   my_char = 0;
        short     bad = 0;
        char     text[10];
    
        memset (text, 0, 10);
        printf ("enter number: ");
    
        while ( (my_char = getchar()) )
        {
            if ( my_char < '0' || my_char > '9' )
            {
                if ( my_char != '\n' ) bad = 1;
            }
            else
            {
                size_t len = strlen (text);
                char *strtemp = malloc (len + 2);
                strcpy (strtemp, text);
                strtemp [len] = my_char;
                strtemp [len + 1] = '\0';
                strncpy (text, strtemp, 9);
                free (strtemp);
            }
    
            if ( my_char == '\n' )
            {
                if ( bad )
                {
                    printf ("enter again (just numbers): ");
                    fflush (stdout);
                    bad = 0;
                    memset (text, 0, 9);
                }
    
                else break;
            }
        }
    
        printf ("entered: %s"endl, text);
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2019-05-17
      • 2012-12-29
      • 2019-01-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-11-26
      相关资源
      最近更新 更多