5

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

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

scanf("%[0987654321.-]s",buf);

i = atoi(buf);

if(i)
    index = i;
4

6 回答 6

15

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

我建议使用fgets()输入一行,然后sscanf()在字符串上实际检查和处理它。

这还允许您检查字符串中是否有您想要的字符(通过循环或使用正则表达式),这scanf是函数系列并不真正适合的。

例如,scanf()"%d"or一起使用"%f"将在第一个非数字字符处停止,因此不会捕获尾随错误,例如"127hello",只会给您 127。而与无界一起使用它%s只是乞求缓冲区溢出。

如果你真的必须使用[]格式说明符(in scanf or sscanf),我认为它不应该被s.

并且,对于使用该建议的稳健输入解决方案,请参见此处。一旦您将输入行作为字符串,您就sscanf可以满足您的需求。

于 2009-01-19T01:44:52.137 回答
5

您似乎想验证一个字符串作为输入。这取决于您是否要验证您的字符串是否包含双精度数或整数。以下检查双精度(允许前导和尾随空格)。

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

这里有一个问题,其中还包括更多的 C++ 方法,比如使用来自 boost 的字符串流和函数,比如 lexical_cast 等等。它们通常比 scanf 之类的函数更受欢迎,因为很容易忘记将一些 '%' 传递给 scanf 或一些地址。scanf 不会认识到这一点,而是会做任意的事情,而 lexical_cast,例如,如果任何事情都不正确,就会抛出异常。

于 2009-01-19T01:45:25.693 回答
1

我的方法是将用户输入读入字符串,然后使用strtol(). 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 上,请手动分配并限制格式string的最大大小。scanf()

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

于 2009-01-19T07:27:40.277 回答
0

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

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

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

除此之外,您还需要对您要求scanf进行的转换进行自己的健全性检查。

于 2009-01-19T01:43:18.583 回答
-1

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

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

如果您需要进行更复杂的检查,则必须自己进行。Scanf 不会为你做这件事。

于 2009-01-19T01:38:25.817 回答
-4

“buf”需要是一个指针。看起来你是按价值传递的。

于 2009-01-19T01:43:37.053 回答