scanf函数失败,为什么? [英] scanf fails why?

查看:226
本文介绍了scanf函数失败,为什么?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

结果
当我写这一点,编译和运行:

  INT X;
scanf函数(%d个,&安培; X);
而(X!= 4){
    scanf函数(%d个,&安培; X);
}

和插入char或双号小于4时,它进入无限循环。结果
当插入双大于4则终止。结果
任何解释?


解决方案

从的 C语言标准(n1256)


7.19.6.2 fscanf函数的结果
...结果
4 fscanf函数执行依次格式的每个指令。如果指令失败,详情如下,该函数返回。故障被描述为输入失败(由于编码错误的发生或输入字符的可用性),或匹配
故障(由于不适当的输入)。结果,
...结果
7这是一个转换规范的指令定义一组匹配的输入序列,按下面的每一个符描述。 A转换规范在下面的步骤执行:结果
结果
8输入空白字符(由isspace为函数指定)被跳过,除非
该规范包括A [ C N 的说明。 250)结果
结果
9的输入项目是从流中读取,除非该规范包括 N 的说明。一输入项被定义为不超过任何指定的字段宽度并且是,或者是,一个匹配的输入序列的preFIX输入字符的最长序列 251)功能的第一个字符,如果有的话,之后的输入项保持未读。如果输入项的长度为零,则该指令的执行失败;这个条件是一个匹配失败,除非,编码错误,或从流,在这种情况下,它是一个输入失败读误差prevented输入文件结束-
结果
结果
10除了在A 的说明中,输入项(或者,在一个的%正的指令的情况下,输入字符的计数)被转换为一个类型的情况下适当的转换说明。 如果输入项不是一个匹配序列,该指令的执行失败:该条件是一个匹配失败的除非分配SUP pression被一个*所示,转换的结果是。放置在目标指向下一个尚未收到转换结果的格式参数的第一个参数。如果该对象不具有一个适当的类型,或者如果转换的结果不能被重新$ P $在对象psented,行为是不确定的。

在第10段的补充重点%d个转换说明希望输入的文本格式化为十进制整数。如果不是,则转换失败以及造成转换失败的字符被留在输入信息流中。还呼吁 scanf()的%d个转换说明会呛相同的字符。

scanf()的返回成功作业的数量;你需要检查这个结果,看看是否转换成功,像这样:

  INT X = 0;
而(X!= 4)
{
  INT结果= scanf函数(%d个,&安培; X);
  如果(结果!= 1)
  {
    的printf(最后的调用scanf()的失败;退出\\ n);
    打破;
  }
}

不幸的是,你仍然有错误的输入卡输入流。有许多用于处理这一策略。你可以用的getchar 删除有问题的字符,然后再试一次:

 而(X!= 4)
{
  INT TMP;
  如果(scanf函数(%d个,&安培; TMP)== 0)
    的getchar();
  其他
    X = tmp目录;
}

或者你可以尝试读取到下一个新行,假设所有其余的输入b0rked:

 而(X!= 4)
{
  INT TMP;
  如果(scanf函数(%d个,&安培; TMP)== 0)
    而(的getchar()!='\\ n')
      ;
  其他
    X = tmp目录;
}

或者你可以尝试读取输入作为的文本的和转化利用为整数与strtol()(我的preferred技术):

 字符输入[SOME_SIZE]
INT X = 0;
...
而(X!= 4)
{
  如果(与fgets(输入,输入的sizeof,标准输入))
  {
    字符*检查;
    INT TMP =(INT)与strtol(输入,功放及;检查,10);
    如果(isspace为(*检查)及!&安培;!*检查= 0)
    {
      的printf(%s不是有效的整数:再试一次的\\ n,输入);
    }
    其他
    {
      X = tmp目录;
    }
  }
  其他
  {
    的printf(请仔细阅读标准输入\\ n错误);
    打破;
  }
}

这是更多的工作,但它可以让你抓住它被分配到 X 的前错误输入的


when I wrote this ,compile and run:

int x;   
scanf ("%d", &x);  
while (x!=4) {  
    scanf ("%d", &x);  
}

and when inserting char or double number less than 4 it enter an infinite loop.
when inserting double greater than 4 it terminates.
Any explanation?

解决方案

From the C language standard (n1256):

7.19.6.2 The fscanf function
...
4 The fscanf function executes each directive of the format in turn. If a directive fails, as detailed below, the function returns. Failures are described as input failures (due to the occurrence of an encoding error or the unavailability of input characters), or matching failures (due to inappropriate input).
...
7 A directive that is a conversion specification defines a set of matching input sequences, as described below for each specifier. A conversion specification is executed in the following steps:

8 Input white-space characters (as specified by the isspace function) are skipped, unless the specification includes a [, c, or n specifier.250)

9 An input item is read from the stream, unless the specification includes an n specifier. An input item is defined as the longest sequence of input characters which does not exceed any specified field width and which is, or is a prefix of, a matching input sequence.251) The first character, if any, after the input item remains unread. If the length of the input item is zero, the execution of the directive fails; this condition is a matching failure unless end-of-file, an encoding error, or a read error prevented input from the stream, in which case it is an input failure.

10 Except in the case of a % specifier, the input item (or, in the case of a %n directive, the count of input characters) is converted to a type appropriate to the conversion specifier. If the input item is not a matching sequence, the execution of the directive fails: this condition is a matching failure. Unless assignment suppression was indicated by a *, the result of the conversion is placed in the object pointed to by the first argument following the format argument that has not already received a conversion result. If this object does not have an appropriate type, or if the result of the conversion cannot be represented in the object, the behavior is undefined.

Emphasis added in paragraph 10. The %d conversion specifier expects the input text to be formatted as a decimal integer. If it isn't, the conversion fails and the character that caused the conversion to fail is left in the input stream. Further calls to scanf() with the %d conversion specifier will choke on the same character.

scanf() returns the number of successful assignments; you need to check this result to see if the conversion succeeded, like so:

int x = 0;
while (x != 4)
{
  int result = scanf("%d", &x);
  if (result != 1)
  {
    printf("Last call to scanf() failed; exiting\n");
    break;
  }
}

Unfortunately, you still have the bad input stuck in the input stream. There are a number of strategies for dealing with this. You could remove the offending character with getchar and try again:

while (x != 4)
{
  int tmp;
  if (scanf("%d", &tmp) == 0)
    getchar();
  else
    x = tmp;
}

Or you could try to read up to the next newline, assuming that all remaining input is b0rked:

while (x != 4)
{
  int tmp;
  if (scanf("%d", &tmp) == 0)
    while (getchar() != '\n')
      ;
  else
    x = tmp;
}

Or you could try to read the input as text and convert to integer using strtol() (my preferred technique):

char input[SOME_SIZE];
int x = 0;
...
while (x != 4)
{
  if (fgets(input, sizeof input, stdin))
  {
    char *check;
    int tmp = (int) strtol(input, &check, 10);
    if (!isspace(*check) && *check != 0)
    {
      printf("%s is not a valid integer: try again\n", input);
    }
    else
    {
      x = tmp;
    }
  }
  else
  {
    printf("Read error on standard input\n");
    break;
  }
}

It's more work, but it allows you to catch bad input before it gets assigned to x.

这篇关于scanf函数失败,为什么?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆