当前位置:编程学习 > C/C++ >>

scnaf使用格式化字符串%d接受小数的情况

在使用scanf的时候,因为需要传递整数,所以,很显然格式化字符串使用“%d”,但是在测试的时候,有人就使用了小数,也就是误输入,那情况就糟糕了,举一个简单的例子:
[cpp] 
#include <stdio.h> 
int main() 

 int a,b,c; 
 //printf("a=%d,b=%d,c=%d\n",a,b,c); 
 while(1) 
 { 
   //fflush(stdin); 
   scanf("%d",&a); 
   scanf("%d",&b); 
   scanf("%d",&c); 
   printf("a=%d,b=%d,c=%d\n",a,b,c); 
   printf("---------------\n"); 
 } 
 return 0; 

如果输入三个正确的正整数的话,那么程序运行正常,例如输入 1,2,3,那么运行的结果就是
1 2 3
a=1,b=2,c=3
---------------
但是,如果不慎输入小数的话,那么整个程序就会崩溃的,因为显示的太快了,于是我修改了一下程序,让程序在下一个while循环的时候,休眠了两秒钟,如下:
[cpp] 
#include <stdio.h> 
#include <windows.h> 
int main() 

 int a,b,c; 
 //printf("a=%d,b=%d,c=%d\n",a,b,c); 
 while(1) 
 { 
     //fflush(stdin); 
   scanf("%d",&a); 
   scanf("%d",&b); 
   scanf("%d",&c); 
   printf("a=%d,b=%d,c=%d\n",a,b,c); 
   printf("---------------\n"); 
   Sleep(2000); 
 } 
 return 0; 

下面的假设我误输入了小数,看一下情况会怎么样:
2.3
a=2,b=-858993460,c=-858993460
---------------
a=2,b=-858993460,c=-858993460
---------------
a=2,b=-858993460,c=-858993460
---------------

程序一直死循环我们可以看到a的值是2,而b和c的值都是随机值,然后通过通过在使用之前输出a,b,c值,如下:
printf("a=%d,b=%d,c=%d\n",a,b,c);
输出结果:
a=-858993460,b=-858993460,c=-858993460
可以看到每次循环的时候,它们的值都没有发变化。想到了scanf的使用,我猜想一直死循环的原因就是scanf对输入变量的记忆,如果把内存清空的话,是不是就不会发生类似的情况了呢?
于是,我在while循环的最开始添加了语句fflush(stdin);然后运行:
即使第一次输入小数的时候,程序也不会崩溃。运行如下:
a=-858993460,b=-858993460,c=-858993460
4.2
a=4,b=-858993460,c=-858993460
---------------
1 2 3
a=1,b=2,c=3
---------------
.5
a=1,b=2,c=3
---------------
虽然没有崩溃,但是,我们看到最后输入“.5”的时候,a,b,c的值都没有发生变化。
那如何在程序中识别这种情况呢?同桌给我了下面的一个程序:
[cpp] 
#include<stdio.h> 
int main() 

    int x,y; 
 printf("num3:%d\n",x); 
    while((y=scanf("%d",&x))==1) 
 { 
  printf("num1:%d\n",x); 
        printf("num2:%d\n",y); 
 } 
 printf("num3:%d\n",x); 
 printf("num3:%d\n",y); 
 return 0; 

下面是运行过程:
运行一:
x=-858993460
4
num1:4 --正常执行
num2:1 --scnaf的返回值表示成功读入变量的个数,该程序返回1表示读取正常
4.2
num1:4
num2:1 --当输入小数的时候,第一次读取的时候,读取的是整数部分,通过返回的1可以看出来,变量赋值正确
num3:4 --但是,为什么,它又退出程序了呢,而且第二次的返回值竟然是0,也就是赋值失败,我只是输入一个值
num4:0
Press any key to continue
运行2:
x=-858993460
.2
num3:-858993460 --当值输入一个小数的时候,我们可以看到,其实变量x并没有赋值,还是原来产生的那个随机值
num4:0
Press any key to continue

通过上面的例子,我们可以看到,当我们通过scanf的时候,如果参数列表是“%d”,但是在运行的时候输入的是小数的话,那么第一次变量获取的是小数点前面的部分,如果小数点前面有整数的话,那么scanf就可以正常读取输入的值。但是,倘若我们接下来还有一个scanf的话,那么该scanf就会去取输入的小数去掉整数的部分,例如,当输入“3.2”的时候,第一次读取的是3,第二个scanf函数就不会读取你输入内容,而是会接受内存中没有读取的“.2”,这个时候,我们的变量就不会得到新的值,如果该变量(例如上面的x)原来赋值的话(获取小数4.2的整数部分4),那么它还是4,如果没有赋值的话,它还是原来的随机值,也就是,该变量中的值并没有更新。其实避免影响第二次scanf的方法就是在执行第二个scanf的之前,清空内存,例如使用“fflush(stdin);”
如果把它放到了while循环的最后,例如去掉源程序中注释的内容,重新编辑运行:
x=-858993460
2
num1:2 --整数正常
num2:1
5.6
num1:5 --小数获取整数部分
num2:1 --正常
.2
num3:5 --变量的值并没有重新写入
num4:0 --读取新值失败,退出
Press any key to continue
从运行的结果可以看出,只要第一次输入的内容不是以小数点开头的话,那么就可以继续运行下去。
那么在自己的程序中怎么预防这样的问题呢?
下面通过一个小例子来说明一下:
[cpp] 
#include <stdio.h> 
void main() 

 int num,ret; 
 while ((ret=scanf("%d",&num))!=1) 
 { 
  printf("输入错误,请重新输入:"); 
  fflush(stdin); 
  continue; 
 } 
 printf("你输入的值是:%d,下面就可以使用了!\n",num); 

运行情况如下:
.2     --输入的整数误输入多一个小数点
输入错误,请重新输入:2  --提示重新输入
你输入的值是:2,下面就可以使用了!
Press any key to continue

3.6    --输入了小数
你输入的值是:3,下面就可以使用了!--可以正确读取其中的整数部分
Press any key to continue


如果担心上面的误操作会影响下面的scanf操作,那么可以在使用该函数之前,使用“fflush(stdin);”清空一下内存。

 

补充:软件开发 , C++ ,
CopyRight © 2012 站长网 编程知识问答 www.zzzyk.com All Rights Reserved
部份技术文章来自网络,