【问题标题】:Inputting float into a program that only deals with ints将浮点数输入到仅处理整数的程序中
【发布时间】:2011-10-18 20:14:22
【问题描述】:

我有一个程序,但是当我在程序要求输入时输入浮点数时,程序会突然跳过一步并移动到最终输出。程序如下:

#include <stdio.h>
#include <stdlib.h>

int main()
{
  int a,b,c;
  int i;

  printf("Please enter a number: ");
  scanf("%d", &a);
  printf("Please enter a number: ");
  scanf("%d", &b);

  c = 0; 
  for(i=0; i < b; i++)
    {
    c = c + a;
    } 

  printf("%d x %d = %d\n", a, b, c);

  return 0;
}

当我为a 输入一个int,为b 输入一个浮点数时,如果b 的小数点后的数字被截断,程序将按预期输出乘积。但是,当我为a 输入浮点数时,程序不会采用第二个数字b 的值,而是跳过该步骤并输出a x -858993460 = 0 的整数版本。

例如:

a = int, b = 浮点数

请输入一个数字:3
请输入一个数字:5.6
3 x 5 = 15

a = 浮动,b = 跳过

请输入一个数字 3.9
请输入一个数字:3 x -858993460 = 0

代码中的所有缺陷都是故意的,但我只是想知道为什么它的行为方式与我上面解释的方式相同。我知道这是因为尝试将浮点数输入有符号整数,但我不确定究竟是什么导致它跳过第二个scanf("%d", &amp;b)。谁能解释为什么会这样?

谢谢。

【问题讨论】:

标签: c floating-point int double


【解决方案1】:

如果要读取的下一个字符无法在格式说明符指定的当前格式下转换,scanf 将停止扫描和存储当前字段并移动到 下一个输入字段(如果有)。

并且该特定字符被视为未读,并用作下一个输入字段或任何后续读取操作的第一个字符。

在上面给出的示例中,它正在扫描3,然后无法将. 解析为格式说明符"%d"。因此它将3 存储在变量a 中,而将.9 保留为未读。当控件传递到下一个scanf 语句时,它会扫描.,但由于它无法将. 解析为格式说明符"%d",它会跳过对该字段的输入扫描。

现在由于变量b 未被分配,它包含一些垃圾值。任何带有垃圾值的算术运算都会产生垃圾值。

【讨论】:

    【解决方案2】:

    控制台输入是行缓冲;当您将 3.9 输入到 %d 格式说明符中时,仅消耗 3,剩余数据仍处于缓冲状态,因此第二次 scanf() 调用尝试根据其说明符对其进行转换,它会找到 '.' 并中止转换让 b 未定义。

    scanf() 将继续“失败”,直到输入数据末尾的'\n' 被消耗。你可以这样做:

      printf("Please enter a number: ");
      scanf("%d", &a);
      while( getchar() != '\n' ) { /* do nothing */ }
    
      printf("Please enter a number: ");
      scanf("%d", &b);
      while( getchar() != '\n' ) { /* do nothing */ }
    

    注意,如果格式说明符是%c,则需要修改“flush”代码,因为转换后的字符可能已经是'\n'

    scanf("%c", &c);
    while( c != '\n' && getchar() != '\n' ) { /* do nothing */ }
    

    【讨论】:

      【解决方案3】:

      看起来scanf() 在第二种情况下正在读取您的“3”,而忽略了“9”。

      然后当调用第二个scanf() 时,输入缓冲区中已经有文本(“.9”)。

      我无法准确说出它对“.9”的作用。它可能已经找到了该点,并在 b 未初始化的情况下中止了该点。通过调试器单步执行来确定正在发生的事情应该是一件简单的事情。

      但是,基本上,并不是所有的输入都被第一次调用scanf() 处理,所以这就是第二次调用试图读取的内容。这就是为什么它不会等待您为第二次调用输入任何数据。

      【讨论】:

      • 我们如何刷新/清空缓冲区?
      • 我可能会使用gets() 来阅读整行。然后你可以用它做任何你想做的事情,它不会弄乱后续的输入值。
      • scanf() 遇到与格式说明符不匹配的字符时的行为是中止转换并返回,其余不成功的转换保持变量不变,在这种情况下它是未初始化的.所以你可以“告诉确切地”,因为它定义明确。
      猜你喜欢
      • 2021-12-06
      • 1970-01-01
      • 2021-09-30
      • 2022-12-03
      • 1970-01-01
      • 2018-06-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多