1、语句“scanf("%4d%3d",&x,&y);”的作用是什么?
【分析】%4d表示输入一个整数,整数宽度不能超过4位,包括符号。超过部分不会作为整数的一部分。
【结论】该语句的作用是:先从输入缓冲区读取宽度不超过4位的整数(读取时确保宽度最大化),再从输入缓冲区读取宽度不超过3位的整数。
【示例】(假定输入缓冲区为空)
1、执行该语句时输入:-12345678回车,则x=-123,y=456。
注意:这时输入缓冲区非空。如果再执行scanf("%d",&x);会直接得到x=78。
2、执行该语句时输入:123回车,则x=123,程序继续等待输入y的值。再输入:-5678回车,则y=-56。
2、执行以下代码时,输入23后回车,为什么直接输出23,10而没有等待输入字符?
main()
{ int m;char c;
scanf("%d",&m);
scanf("%c",&c);
printf("%d,%d",m,c);
}
【分析】
scanf函数本质上是从输入缓冲区读取数据。只有当输入缓冲区为空时,才会等待输入。所有输入都会存储到输入缓冲区,直到按回车。按回车有二个作用:其一,将换行符'\n'保存到输入缓冲区。其二,结束输入,scanf函数开始从输入缓冲区读取数据。
以上代码的执行流程是:
(1)执行语句:int m;char c;
(2)执行语句:scanf("%d",&m);
这时,输入缓冲区为空,等待输入。
(3)输入23后回车
(4)输入缓冲区有二个数据:23和换行符'\n'
(5)scanf函数从输入缓冲区读取数据,得到m=23
(6)输入缓冲区有一个数据:换行符'\n'
(7)执行语句:scanf("%c",&c);
这时输入缓冲区有换行符,直接读取,c='\n'。换行符的ASCII码值为10,因此,本质上,c=10。
(8)执行语句:printf("%d,%d",m,c);
【结论】
(1)执行类似“scanf("%d",&m);”的语句后,如果需要接受键盘输入的字符,则必须先清空输入缓冲区。
(2)清空输入缓冲区的方法主要有:
A、使用stdio.h中的setbuf函数。如:setbuf(stdin,NULL);
B、使用stdio.h中的fflush函数。仅VC6支持。如:fflush(stdin);
C、使用getc(stdin)或getchar()函数循环读取,直到输入缓冲区为空。
(3)getc(stdin)函数和getchar()函数本质上也是从输入缓冲区读取数据。也需要注意输入缓冲区是否需要清空的问题。
3、如何控制输入数据的有效性?
【分析】 scanf 函数的返回值表示正确输入的数据个数。如果需要输入多个数据,而输入的数据中存在不匹配的数据,则函数返回不匹配数据之前正确输入的数据个数。如果输入全部不匹配,则返回值为0。
例如,执行“scanf("%d%d”,&x,&y);”时:
(1)输入:23abc。函数的返回值为1(x=23)。
(2)输入:abv,45。函数的返回值为0。
【结论】 可以根据scanf 函数的返回值进行判断。
【示例】以下代码确保输入的是一个[0,100]上的整数。
#include <stdio.h>
int main()
{
int a,n;
while(1)
{ setbuf(stdin,NULL);
n=scanf("%d",&a);
if(n!=1)continue;
if(a<0||a>100)continue;
break;
}
printf("%d",a);
}
思考:如果不调用setbuf函数会出现什么情况?请分析原因。