scanf函数
与printf函数一样,都被定义在头文件stdio.h里,因此在使用scanf函数时要加上#include <stdio.h>。它是格式输入函数,即按用户指定的格式从键盘上把数据输入到指定的变量之中。
函数原型: int scanf(const char *format,...);
函数 scanf() 是从标准输入流stdio (标准输入设备,一般是键盘)中读内容的通用子程序,
可以根据说明的格式读入若干个数据,并保存在对应地址的变量中。
其调用形式为: scanf("<格式说明字符串>",<变量地址列表>);变量地址要求有效,并且与格式说明的次序一致。
scanf()函数返回成功赋值的数据项数,读到文件末尾出错时则返回EOF。
例如 scanf
(
"%d %d"
,&a,&b);
如果a和b都被成功读入,那么scanf的返回值就是2
如果只有a被成功读入,返回值为1
如果a和b都未被成功读入,返回值为0
如果遇到错误或遇到end of file,返回值为EOF。
且返回值为int型.
例:使用scanf函数输入数据。
#include<stdio.h> int main(void) { int a,b,c; printf("输入a,b,c\n"); scanf("%d%d%d",&a,&b,&c); printf("a=%d,b=%d,c=%d\n",a,b,c); fflush(stdin); return 0; }
&a,&b,&c中的&是地址运算符,&a指a在内存中的地址。scanf的作用是:按照a,b,c的内存地址将输入的数据存到a,b,c中去。变量a,b,c的地址是在编译连续阶段分配的(存储顺序由编译器决定)。
这里注意:如果scanf中%d是连着写的如“%d%d%d”,在输入数据时,数据之间不可以加逗号,只能是空格或tab键或者回车键——“2 3 4” 或 “2(按tab)3(按tab)4(按tab)”。若是“%d,%d,%d”,则在输入数据时需要加“,”,如“2,3,4”.
问题一
1 #include<stdio.h> 2 int main(void) 3 { 4 char str[80]; 5 scanf("%s",str); 6 printf("%s",str); 7 return 0; 8 }
输入:I love you!
上述程序并不能达到预期目的,scanf()扫描到"I"后面的空格就认为对str的赋值结束,并忽略后面的"love you!".这里要注意是"love you!"还在键盘缓冲区(关于这个问题,网上我所见的说法都是如此,但是,我经过调试发现,其实这时缓冲区字符串首尾指针已经相等了,也就是说缓冲区清空了,scanf()函数应该只是扫描stdin流,这个残存信息是在stdin中)。我们改动一下上面的程序来验证一下:
1 #include<stdio.h> 2 #include<windows.h> 3 int main(void) 4 { 5 char str[80],str1[80],str2[80]; 6 scanf("%s",str);/*此处输入:Iloveyou!*/ 7 printf("%s\n",str); 8 Sleep(5000);/*这里等待5秒,告诉你程序运行到什么地方*/ 9 /* 10 不是sleep(5) 11 1,函数名是Sleep不是sleep。 12 2,C/C++中,unsignedSleep(unsigned)应该是毫秒ms. 13 */ 14 scanf("%s",str1);/*这两句无需你再输入,是对stdin流再扫描*/ 15 scanf("%s",str2);/*这两句无需你再输入,是对stdin流再扫描*/ 16 printf("%s\n",str1); 17 printf("%s\n",str2); 18 return 0; 19 }
输入:I love you!
输出:
I
love
you!
1 #include<stdio.h> 2 int main(void) 3 { 4 char str[50]; 5 scanf("%[^\n]",str);/*scanf("%s",string);不能接收空格符*/ 6 printf("%s\n",str); 7 return 0; 8 }
问题二
1 #include<stdio.h> 2 int main(void) 3 { 4 int a; 5 char c; 6 while(c!='N') 7 { 8 scanf("%d",&a); 9 scanf("%c",&c); 10 printf("a=%dc=%c\n",a,c);/*printf("c=%d\n",c);*/ 11 } 12 return 0; 13 }
scanf("%c", &c);这句不能正常接收字符,什么原因呢?我们用printf("c = %d\n", c);将C用int表示出来,启用printf("c = %d\n", c);这一句,看看scanf()函数赋给C到底是什么,结果是c=10 ,ASCII值为10是什么?换行即\n.对了,我们每击打一下"Enter"键,向键盘缓冲区发去一个“回车”(\r),一个“换行"(\n),在这里\r被scanf()函数处理掉了(姑且这么认为吧^_^),而\n被scanf()函数“错误”地赋给了c.解决办法:可以在两个scanf()函数之后加getchar()。
也可以使用fflush函数。fflush()函数冲洗流中的信息,该函数通常用于处理磁盘文件。
1 #include<stdio.h> 2 int main(void) 3 { 4 int a; 5 char c; 6 while(c!='N') 7 { 8 scanf("%d",&a); 9 fflush(stdin); 10 scanf("%c",&c); 11 fflush(stdin); 12 printf("a=%dc=%c\n",a,c); 13 } 14 return 0; 15 }
问题三
1 #include<stdio.h> 2 int main(void) 3 { 4 int a=0,b=0,c=0,ret=0; 5 ret=scanf("%d%d%d",&a,&b,&c); 6 printf("第一次读入数量:%d\n",ret); 7 ret=scanf("%d%d%d",&a,&b,&c); 8 printf("第二次读入数量:%d\n",ret); 9 return 0; 10 }
但是当输入内容与格式换字符串不匹配时,结果会令人大跌眼镜。
将代码作如下修改,可以有力的证明上述结论。
1 #include<stdio.h> 2 int main(void) 3 { 4 int a=0,b=0,c=0,ret=0; 5 ret=scanf("%d%d%d",&a,&b,&c); 6 printf("第一次读入数量:%d\n",ret); 7 ret=scanf("%c%d%d",&a,&b,&c); 8 printf("第二次读入数量:%d\n",ret); 9 return 0; 10 }
当把第二个scanf函数内的格式化字符串改为”%c%d%d”时,运行结果如下
1 #include<stdio.h> 2 int main(void) 3 { 4 int a=0,b=0,c=0,ret=0; 5 ret=scanf("%d%d%d",&a,&b,&c); 6 fflush(stdin); 7 printf("第一次读入数量:%d\n",ret); 8 ret=scanf("%d%d%d",&a,&b,&c); 9 fflush(stdin); 10 printf("第二次读入数量:%d\n",ret); 11 return 0; 12 }
运行结果:
问题四
1 #include<stdio.h> 2 int main(void) 3 { 4 int a,b,c; 5 scanf("%d,%d",&a,&b); 6 c=a+b;/*计算a+b*/ 7 printf("%d+%d=%d",a,b,c); 8 return 0; 9 }
如上程序,如果正确输入a,b的值,那么没什么问题,但是,你不能保证使用者每一次都能正确输入,一旦输入了错误的类型,你的程序不是死锁,就是得到一个 错误的结果,呵呵,这可能所有人都遇到过的问题吧?解决方法:scanf()函数执行成功时的返回值是成功读取的变量数,也就是说,你这个scanf() 函数有几个变量,如果scanf()函数全部正常读取,它就返回几。但这里还要注意另一个问题,如果输入了非法数据,键盘缓冲区就可能还个有残余信息问题。正确的例程:
1 #include<stdio.h> 2 int main(void) 3 { 4 int a,b,c; 5 while(scanf("%d%d",&a,&b)!=2) 6 fflush(stdin); 7 c=a+b; 8 printf("%d+%d=%d",a,b,c); 9 return 0; 10 }
1 /*此函数可以和scanf函数一起使用,但使用%c输入时要注意,即此函数只能用于缓冲区非空的情况*/ 2 #include<stdio.h> 3 void flush() 4 { 5 charc; 6 while((c=getchar())!='\n'&&c!=EOF); 7 } 8 intmain(void) 9 { 10 int a,b,c;/*计算a+b*/ 11 while(scanf("%d%d",&a,&b)!=2) 12 flush(); 13 c=a+b; 14 printf("%d+%d=%d",a,b,c); 15 return 0; 16 }
程序示例:
1 #include<stdio.h> 2 int main(void) 3 { 4 int i,c; 5 while(1) 6 { 7 printf("Pleaseinputaninteger:"); 8 scanf("%d",&i); 9 if(feof(stdin)||ferror(stdin)) 10 { 11 //如果用户输入文件结束标志(或文件已被读完),或者发生读写错误,则退出循环 12 //dosomething 13 break; 14 } 15 //没有发生错误,清空输入流。通过while循环把输入流中的余留数据“吃”掉 16 while((c=getchar())!='\n'&&c!=EOF); 17 //可直接将这句代码当成fflush(stdin)的替代,直接运行可清除输入缓存流 18 //使用scanf("%*[^\n]");也可以清空输入流,不过会残留\n字符。 19 printf("%d\n",i); 20 } 21 return 0; 22 }