1.scanf( )函数介绍
C库中包含了多个输入函数,scanf( )是通用的一个,因为他可以读取不同格式的数据。如果想输入整数100,就要键入字符1、0、0,那么scanf()要做的就是将字符依次转换成数值。
头文件:#include<stdio.h>
用法:
int scanf(const char *format, ...);
其调用格式为: scanf("<格式化字符串>",<地址表>);
例如:scanf(“%d%d”,&a,&b); //a和b为int类型变量
%d // 转换说明,表明目标数据类型为int型
功能:
scanf()函数是格式化输入函数,它从键盘(标准输入设备)输入,读取输入字符,根据格式字符串表明字符输入流的目标数据类型。
返回值:
scanf()函数返回成功赋值的数据项数,出错时则返回EOF。
2.转换说明
什么是转换说明呢?既然scanf( )是标准格式输入函数,那么输入的数据就要存储到目标变量中,而目标变量又会有很多种类型,例如int、char、float等,scanf( )如何区分呢?于是,转换说明出现了,他指明了scanf( )把输入解释成什么数据类型,存储到相对应的目标变量中。就像一家啤酒厂商,生产出的啤酒是雪花啤酒,就要放入雪花啤酒瓶中,淡爽啤酒就要放入淡爽啤酒瓶中,同理转换说明就起到了我们输入的数据要解释成与目标变量相对应的数据类型。
ANSI中scanf( )的转换说明
转换说明 含义
%c 把输入解释成字符
%d 把输入解释成有符号十进制整数
%e、%f、%g、%a 把输入解释成浮点数
%E、%F/、%G、%A 把输入解释成浮点数
%i 把输入解释成有符号的十进制整数
%o 把输入解释成有符号的八进制整数
%p 把输入解释成指针
%s 把输入解释成字符串
%u 把输入解释成无符号十进制整数
%x、%X 把输入解释成有符号十六进制整数
3.scanf函数用法
3.1 输入整数(%d)
(1)scanf(“%d%d%d”,&a,&b,&c);
#include <stdio.h>
int main()
{
int a,b,c;
scanf("%d%d%d",&a,&b,&c);
printf("%d,%d,%d\n",a,b,c);
return 0;
}
1) 输入:2<enter>3<enter>4<enter>
输出:2,3,4
2) 输入:<space> 2 <space> 3 <space> 4 <space>
输出:2,3,4
※思考与总结※
scanf函数每次读取一个字符,跳过所有空白字符,直至遇到第一个非空白字符才开始读取,因为要读取整数,所以希望发现一个数字字符或者一个符号(+或-),如何找到一个数字或符号,便保存字符,并读取下一个字符,直至遇到非数字字符。如果遇到非数字字符,便认为读到了末尾,然后scanf把非数字字符放回输入。这就意味着程序在下一次读取输入时,首先读到的是上一次读取丢弃的非数字字符。
空白字符会使scanf()函数在读操作中略去输入中的一个或多个空白字符,空白符可以是space,tab,newline等等,直到第一个非空白符出现为止。
<tab> 2 <tab> 3 <tab> 4 <tab> // 输出同上,<tab>为空白字符
3) 输入:c<enter>
#include <stdio.h>
int main()
{
int a,b,c;
printf("%d,%d,%d\n",a,b,c);//增加一行代码
scanf("%d%d%d",&a,&b,&c);
printf("%d,%d,%d\n",a,b,c);
}
输出:
输入:2<enter>d<enter>
输出:2输入成功,d输入不匹配,当不匹配时结束scanf()
※思考与总结※
scanf语句执行时,首先试图从缓冲区中读入一个%d类型的数据,如果和第一个参数匹配,则继续从缓冲区中读取数据和第二个参数进行匹配,依次进行下去,直到匹配完所有的参数;如果其中有一个参数不匹配,那就从这个地方跳出(第二个参数开始不匹配就从第二个参数出跳出,第一个参数匹配有效),忽略这个scanf后面所有的参数,结束scanf( )函数,继续向下执行下一条语句。
4)scanf( )存在缓存区
#include <stdio.h>
int main()
{
int a[3];
int i;
for(i = 0; i < 3; i++)
{
printf("Please input number:\n");
scanf("%d",&a[i]);
}
for(i = 0; i < 3; i++)
{
printf("%d,",a[i]);
}
printf("\n");
return 0;
}
输入:2<space>3<spacer>4<space>
输出:
※思考与总结※
发现,还没有等输入第二次,程序已经结束了。当一次性输入‘2 3 4’时,会存储到缓存区中,下一次输入直接在缓存区中取,若参数匹配,输入成功,若不匹配同上scanf( )结束。即此时:
for( )循环体内的三次scanf(“%d”,&a[i])等价 scanf(“%d%d%d”,&a[0],&a[1],&a[2]);
(2)scanf(“%d,%d,%d”,&a,&b,&c); / / %d与%d之间多了“,”
#include <stdio.h>
int main()
{
int a,b,c;
scanf("%d,%d,%d",&a,&b,&c);
printf("%d,%d,%d\n",a,b,c);
}
输入:
a)1, 2,3
b)1,<space>2,<space><space>3
c)1<space>,2,3
输出:
a)
b)
c)
※思考与总结※
scanf()的格式控制串可以使用其它非空白字符例如a)、b)没有问题,但在输入时必须输入这些字符并且位置与格式控制串相一致,如上c)例子,“,”号必须紧跟在输入整数后,不能被空白字符隔开。
3.2 输入字符串(%s)
#include <stdio.h>
int main()
{
char a[100];
scanf("%s",a);
printf("%s\n",a);
return 0;
}
输入:hello<space>world
输出:hello
※思考与总结※
如果使用%s转换说明,scanf( )会读取除空白符以外的所有字符,scanf( )跳过空白符开始读第一个非空白符,并保存非空白符直到再次遇到空白符。这就意味着scanf( )根据%s转换说明读取一个单词,即不包含空白字符的字符串。后要注意:scanf( )将字符串放入指定数组中时,它会在字符序列的末尾加上’\0’。
那么world哪里去了呢?在缓存区中,修改程序如下:
#include <stdio.h>
int main()
{
char a[100];
printf("Please input string:\n");
scanf("%s",a);
printf("print:%s\n",a);
scanf("%s",a);
printf("print:%s\n",a);
return 0;
}
输入:hello<space>world
输出:
3.3 输入字符(%c)
#include <stdio.h>
int main()
{
char ch1,ch2;
scanf("%c%c",&ch1,&ch2);
printf("ch1 : %c ch2 : %c\n",ch1,ch2);
return 0;
}
输入:a<enter>b<enter>//输入a<enter>后程序已经结束
输出:
※思考与总结※
ch2里存了什么字符呢?我们选择%d的格式将ch1和ch2以%d格式打印即:printf("ch1 : %d ch2 : %d\n",ch1,ch2);
输出:
通过man ascii查询得到
10对应的是’\n’换行符,13对应的是’\r’回车,每当敲击<enter>键,’\r’被输入缓存区,’\n’被“错误”的赋给了ch2(暂且这么认为)。
可以这样解决问题
#include <stdio.h>
int main()
{
char ch1,ch2;
scanf("%c",&ch1);
getchar(); //字符输入函数,吸收敲击回车产生的’\n’
scanf("%c",&ch2);
printf("ch1 : %d ch2 : %d\n",ch1,ch2);
return 0;
}