C 如何处理错误输入?

C 如何处理错误输入?,c,error-handling,scanf,C,Error Handling,Scanf,我想创建一个以整数为变量的程序。我想要一种方法来处理在缓冲区上扫描字符串或字符时引起的错误。我的代码如下所示: int输入; printf(“输入一个整数:”); scanf(“%d”,输入(&I)); 就像这样简单,但我想让程序在仍使用scanf的情况下,在缓冲区中输入“test”时打印出类似“Please enter a number”的内容,,关于scanf和%d转换说明符,需要记住两件事: %d告诉scanf跳过任何前导空格,然后读取任何十进制数字字符,直到第一个非十进制数字字符 s

我想创建一个以整数为变量的程序。我想要一种方法来处理在缓冲区上扫描字符串或字符时引起的错误。我的代码如下所示:

int输入;
printf(“输入一个整数:”);
scanf(“%d”,输入(&I));

就像这样简单,但我想让程序在仍使用scanf的情况下,在缓冲区中输入“test”时打印出类似“Please enter a number”的内容,,关于
scanf
%d
转换说明符,需要记住两件事:

  • %d
    告诉
    scanf
    跳过任何前导空格,然后读取任何十进制数字字符,直到第一个非十进制数字字符

  • scanf
    返回成功转换和分配的项目数

  • 因此,以下是
    scanf(“%d”,&input)
    将如何根据不同的输入进行操作:

    Input text        Value saved to input        Return value
    ----------        --------------------        ------------
       "  abc"                         n/a                   0
       "  12c"                          12                   1
       "  1b3"                           1                   1
       "  123"                         123                   1
    
    在所有情况下,
    %d
    转换说明符告诉
    scanf
    跳过前导空格

    如果输入的第一个非空白字符是非数字字符,
    scanf
    将在该点停止读取,
    input
    将不会更新,它将返回
    0

    如果第一个非空白字符是十进制数字,
    scanf
    将读取第一个非十进制数字字符,然后将结果数字字符串转换并分配给
    input
    。不幸的是,这不能帮助您捕获像
    “12c”
    “1b3”
    这样的情况-只要字符串中至少有一个十进制数字,
    scanf(“%d”…)
    将视为成功并返回
    1

    因此,如果要验证用户是否输入了有效的十进制整数字符串,必须执行两项操作:

  • 您必须检查
    scanf
    的返回值
  • 您必须检查输入结束后的第一个字符是否为空白
  • 有两种方法可以完成第二部分。您可以立即读取十进制整数输入后面的字符-如果它不是空格,则输入无效:

    char dummy;
    int itemsRead = scanf( "%d%c", &input, &dummy );
    
    if ( itemsRead == 0 || itemsRead == 2 && !isspace( dummy ) )
    {
      fprintf( stderr, "Input is not valid, try again!\n" );
      while ( getchar() != '\n' )
        ; // empty loop
    }
    
    如果
    itemsRead
    0
    ,则第一个输入字符不是十进制数字字符,输入不正确

    如果
    itemsRead
    2
    并且
    dummy
    不是空白字符,那么我们会遇到类似
    “12c”
    “1b3”
    的情况,并且输入不好

    如果输入不好,则编写一条错误消息,并使用
    getchar
    将任何剩余字符的输入流拖到下一个换行符

    如果
    itemsRead
    1
    ,那么我们只在十进制数字字符后看到EOF,因此输入良好,无需其他操作。如果
    itemsRead
    2
    并且
    dummy
    是空白,那么输入是好的,没有其他事情可做(我假设您不需要将空白推回到输入流上)

    或者,您可以将输入读取为文本,并使用
    strtol
    将其转换为整数
    strtol
    还将设置指向未转换的第一个字符的指针:

    #define MAX_INPUT_SIZE 11 // A 32-bit integer takes up to 10 decimal digits,
                              // plus a possible sign character. 
    
    char buffer[MAX_INPUT_SIZE + 1];  // +1 for string terminator
    
    if ( fgets( buffer, sizeof buffer, stdin ) )
    {
      char *chk;
      int tmp = (int) strtol( buffer, &chk, 10 ); // convert decimal digit string
                                                  // to an integer value
      if ( isspace( *chk ) || *chk == 0 )
      {
        input = tmp;
      }
      else
      {
        fprintf( stderr, "%s is not a valid input, try again\n", buffer );
      }
    }
    else
    {
      // error on input
    }
       
    

    您会注意到,我将
    strtol
    的结果分配给了一个临时-最好在验证输入是否正确之前不要更新目标。

    您使用
    fgets()
    (和
    strtol()
    )进行用户输入。。。然后从工具箱中删除
    scanf()
    。看看这个关于错误处理的答案:如果你想继续使用
    scanf
    ,至少你可以在这里测试这个函数的返回值是否等于1。无论出于何种目的,这个问题都不可能用
    scanf
    解决。如果您想编写一个在错误输入时表现优雅的程序(这是一个好而高尚的目标!),那么实现它的唯一明智的方法是使用
    scanf
    以外的技术。先看看吧
    scanf
    无法很好地处理错误的输入,尝试添加代码以使其处理良好会遇到越来越多的困难,直到可以更容易地从其他内容开始。为什么要使用
    scanf
    ?是因为你的老师告诉你必须这样做,还是因为你觉得用C语言进行用户输入是正确的?如果你的老师坚持,我帮不了你,但如果你不这么做,请接受你想必是来寻找的专家建议,并了解
    scanf
    基本上是可怕的。要想做任何新奇的事情,使用
    scanf
    以外的东西比使用
    scanf
    要容易得多。而且,不幸的是,就scanf而言,“如果用户键入错误,则提示用户”肯定算作“花哨的东西”。