代码之家  ›  专栏  ›  技术社区  ›  Raúl Roa

如何使用scanf验证输入

  •  5
  • Raúl Roa  · 技术社区  · 16 年前

    如何使用scanf验证用户输入。现在我有这样的东西,但不起作用。

    注意:我有ATOI只是为了验证scanf验证是否有效。

    scanf("%[0987654321.-]s",buf);
    
    i = atoi(buf);
    
    if(i)
        index = i;
    
    6 回复  |  直到 14 年前
        1
  •  15
  •   Community CDub    8 年前

    使用 scanf() 对于用户输入通常是一个坏主意,因为失败会导致 FILE 指针位于未知位置。那是因为 scanf 代表“扫描格式化”,而且没有更多 未格式化的 而不是用户输入。

    我建议使用 fgets() 排队,然后 sscanf() 对字符串进行实际检查和处理。

    这还允许您检查字符串中所需的字符(通过循环或使用正则表达式),其中 斯坎夫 家庭职能并不真正适合。

    举例来说,使用 SCAN() 用一个 "%d" "%f" 将在第一个非数字字符处停止,因此不会捕获尾随错误,例如 "127hello" 只会给你127。用它来表示 %s 只是 乞求 缓冲区溢出。

    如果你真的必须使用 [] 格式说明符(在 斯坎夫 sscanf )我不认为这意味着 s .

    而且,对于使用该建议的健壮输入解决方案,请参见 here . 一旦将输入行作为字符串,就可以 sSCANF 心满意足。

        2
  •  5
  •   Community CDub    8 年前

    您似乎想验证一个字符串作为输入。它取决于您是否要验证字符串包含double或int。下面检查double(允许使用前导和尾随空格)。

    bool is_double(char const* s) {
        int n;
        double d;
        return sscanf(s, "%lf %n", &d, &n) == 1 && !s[n];
    }
    

    sscanf 将返回已转换的项(不带“%n”)。 n 将设置为已处理的输入字符的数量。如果处理了所有输入,s[n]将返回终止0字符。两个格式说明符之间的空格说明了可选的尾随空格。

    以下是对int的检查,使用了相同的技术:

    bool is_int(char const* s) {
        int n;
        int i;
        return sscanf(s, "%d %n", &i, &n) == 1 && !s[n];
    }
    

    有个问题要问 here 它还包括更多的C++方式,比如使用String流和Boost中的函数,如ListalyCost等等。它们通常比scanf等函数更受欢迎,因为很容易忘记将一些“%”传递给scanf或某些地址。scanf不会认识到这一点,而是会做任意的事情,而词汇强制转换,例如,如果任何事情不正确,都会抛出异常。

        3
  •  1
  •   qrdl    16 年前

    我的方法是将用户输入读取为字符串,然后使用 strtol() . 斯特罗() 返回指向输入字符串中未能处理的第一个字符的指针,因此通过检查该字符,您将知道是否已分析完整的字符串,如下所示:

    char *string;
    char *endptr;
    long result;
    
    scanf("%as", string);
    errno = 0;
    result = strtol(string, &endptr, 10);
    if (ERANGE == errno)
        printf("Input number doesn't fit into long\n");
    else if (*endptr)
        printf("%s is not a valid long number - it contains invalid char %c\n",
            string, *endptr);
    else
        printf("Got %ld\n", result);
    

    在这个片段中 scanf() 指示自动分配 string 使用格式修饰符“A”(这是GNU扩展)足够大。如果您不在GNU上,请分配 一串 手动并限制最大尺寸 SCAN() 格式。

    这种方法允许更好的错误处理。

        4
  •  0
  •   Jonathan Leffler    16 年前

    在第一个参数中指定的内容 scanf 转换说明符 . 斯坎夫 将尝试将输入转换为格式,但有时您可能会惊讶它将与以下内容匹配:)

    您应该做的第一个检查是来自scanf的返回值(它将给出匹配输入的数量)。如果您没有得到您期望的数字,那么您就知道输入有问题。在你的情况下应该是1。

    if( scanf("%[0987654321.-]s", buf) == 1 )
    {
          if( sanit_check( buf ) ) 
          {
          /* good input */
          }
          else
          {
          /* invalid input */
          }
    }
    else 
    {
    /* invalid input */
    }
    

    除此之外,你还需要自己对你要求的转化进行健全的检查。 斯坎夫 去做。

        5
  •  -1
  •   SoapBox    16 年前

    如果您试图只读取数字,请使用:

    int i;
    scanf( "%d", &i );
    

    如果你需要做更复杂的检查,你必须自己做。斯坎夫不会帮你的。

        6
  •  -4
  •   prestomation    16 年前

    “buf”必须是指针。看起来你是在传递价值。