【问题标题】:How to improve the arguments check in scanf?如何改进scanf中的参数检查?
【发布时间】:2018-03-19 17:42:35
【问题描述】:

我有下一个代码:

#include <stdio.h>
int main(){
    char* a;
    int b;
    if(fscanf(stdin,"%s%d",a,&b)!=2){
        printf("Bad Args!!");
    }
  return 0;
}

当我尝试添加下一个输入时 -

F52352354

5F2352354

我得到下一个输出

对于第一个 - Bad Arg

第二个没什么

另一件麻烦事是,当我尝试检查大数字时,int 的范围和 double 的范围内我得到输入是好的。

我的问题是,是否有一种优雅的方式来检查参数(在 C 中而不是在 C++ 中)

【问题讨论】:

  • 我不明白你在问什么,但是:1. a 在对 fscanf 的调用中未初始化。未定义的行为。 2. 不要使用scanf 进行用户输入。
  • @melpomene 感谢您的回答。 2. 你对从用户那里获得意见的建议是什么?
  • @melpomene 为什么我们不应该使用scanf()
  • @J...S 它从根本上不符合用户的期望(例如,按 Enter 应该做一些事情:接受输入,或打印错误,或任何事情)。很难正确使用。即使您做对了并检测到错误,从这些错误中恢复也更加困难或不可能。

标签: c types scanf


【解决方案1】:

您创建了一个char 指针。但它只是一个指针,不是一个数组。

如果你使用一个未初始化的指针,它有一些不确定的(垃圾)值,它指向的某个位置甚至可能不是程序被允许访问的位置,或者更糟的是可能指向另一个进程的内存,这将进而导致错误。

要么使用动态内存分配,如

char *a=malloc(sizeof(char)*100);
if(a==NULL)
{
    perror("Not enough space");
}

在与free(a) 一起使用后必须解除分配。

或者制作一个静态分配的数组,比如

char a[100]; 

您似乎希望先读取一个字符串,然后再读取一个数字。如果输入是一个没有数字的字符串,然后是一个数字,你可以使用

scanf("%99[^0-9]%d", a, &b);

scanf() 最多会读取 99 个字符,直到遇到一个数字,将其放在 a 中,并且该数字存储在 b 中。

正如@David 指出的那样,这不会跳过前导空格。如果您想在写入a 之前跳过前导空格,请在%99[^0-9] 之前使用一个空格,例如

scanf(" %99[^0-9]%d", a, &b);

检查scanf()的返回值,看看scanf()是否和你一样成功。

请注意,如果scanf() 失败,一些字符仍会留在输入缓冲区中,您可能需要将其删除。

您可以这样做以从输入缓冲区消耗直到下一个 \n

int ch;
while( (ch=getchar())!='\n' && ch!=EOF );

fscanf(stdin, ........) 等价于scanf(.........)

【讨论】:

  • while((ch = getchar()) != '\n'); --> while((ch = getchar()) != '\n' &amp;&amp; ch != EOF); 避免潜在的无限循环。
  • 另请注意,"%99[^0-9]%d" 不会跳过前导空格字符,而 OP 的 "%s%d" 会跳过前导空格。
  • @DavidBowling 添加前面的空格,如“ %99[^0-9]%d” 会跳过前导空格吗?
  • 你说“程序甚至可能无法访问”是一件坏事,但这是可能的最佳结果。指向某些进程的(可写)内存会更糟!正如您所说,关键是没有(适当的)数组。
  • @J...S:因为你得到一个信号并立即知道你的程序是错误的(甚至是错误的大致位置)。未定义的行为有许多比这更糟糕的可能性!
【解决方案2】:

我认为你至少有 2 个问题。 a 是一个指向 char 的指针,但 scanf 需要一个 char 数组。此外,在输入完成或空格之前,%s 将获得尽可能多的字符,因此在它后面加上 %d 意味着 %s 将获得所有输入,而 %d 将一无所获。

【讨论】:

  • %d 将获得下一个数字。例如。 foo 123 将被接受。
  • 是的,因为它们之间有一个空格,但 foo123 不会在 %d 说明符中添加任何内容,并且会使 if() 失败。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-12-25
  • 2019-02-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多