基本说明
- 功能: 按用户指定的格式从键盘上把数据输入到指定的变量之中。
- 头文件:
#include <stdio.h>
- 标准格式:
scanf("<控制串>",变量地址)
输入一个整数:scanf("%d",&a);
- 返回值:scanf()函数返回成功赋值的数据项数,读到文件末尾出错时则返回EOF。(后面详解)
实例
返回值
scanf函数就是返回正确输入的数据个数,返回值int型,以下代码说明:
#include <stdio.h>
int main()
{
int a,b,c;
c=scanf("%d%d",&a,&b);
printf("%d",c);
}
输入 | 输出 |
---|---|
1 2 | 2 |
1 a | 1 |
a b | 0 |
如果遇到错误或遇到end of file,返回值为EOF,所以经常见到
while(scanf("%d",&a)!=EOF)
控制串说明
控制串有三种类型:格式说明符
(也是最常用的)、空白符
,非空白符
1.经常使用的格式说明符就不多说了,比如输入一个整数一个字符
scanf("%d%c",&a,&c);
比如键入 1x
那么就将1赋值给变量a 将’x’赋值给变量c。
2.空白符
空白字符会使scanf()函数在读操作中略去输入中的一个或多个空白字符。
其中空白字符包括space,tab,newline等等。比如
scanf("%d%d",&a,&b);
printf("%d %d",a,b);
若输入10 20
则就将10赋给a ,20 赋给b , 输入时候的空格则忽略;
注:如果格式是字符 char的话,空格或者转义字符会被当做普通字符:
int a;char c;
scanf("%d%c",&a,&c);
printf("%d%c",a,c);
若输入10 a
输出将会是10
而不是10 a
这是因为空格赋值给了c
而 'a'
则继续留在缓冲区内,如果再下面再加一句scanf("%c",&c)
(不用再次输入),那么此时c的值就是'a'
;
本质上,控制串中的空白符使 scanf() 在输入流中读,但不保存结果,直到发现非空白字符为止。
3.非空白符[过滤]
非空白字符会使scanf()函数在读入时剔除掉与这个非空白字符相同的字符;这个在实际应用中挺常用的;
1,比如我想输入的字符串是’a=2 b=3’,而且还需要将a,b赋值成2,3,,可以这样实现。
scanf("a=%db=%d",&a,&b);
这样输入的时候直接输入a=2b=3
scanf()就会自动剔除掉不需要的字符,而将2赋值给a,3赋值给b
这里空格space,同样可以使用
scanf("%d %d",&a,&b)
这样同样可以实现空格输入:输入10 20
同,space将相当于一个普通字符。
2, 宽度设置
在百分号(%)与格式码之间的整数用于限制从对应域读入的最大字符数。例如,希望向name 读入不多于 10个字符时,可以书写成如下形式:
scanf("%10s",name);
如果输入流的内容多于 10 个字符,则下次 scanf()
从此次停止处开始读入。 若达到最大域宽前已遇到空白符,则对该域的读立即停止;此时,scanf() 跳到下一个域。
3,省略指定的数据类型*
符号
比如
scanf("%d%*c%d",&a,&b);
比如输入10a20,得到的是a=10,b=20
再如
char c[20];
scanf("%*s%s",&c);
printf("%s",c);
若输入"hello, world"
则会输出world
因为world之前的space终止了%*s.
注:%
是选择满足条件的,%*
是过滤掉满足条件的。可以配合下面所说的扫描集使用。
4.scanf的”正则表达式”—扫描集
扫描集定义一个字符集合,可由 scanf() 读入其中允许的字符并赋给对应字符数组。 扫描集合由一对方括号中的一串字符定义,左方括号前必须缀以百分号。
遇到不属于扫描集的结束;有点像正则表达式,其实用法也很类似。
比如 :
char s[10];
scanf("%[abc]",s);
输入 | 输出 |
---|---|
abc | abc |
bc | bc |
abdf | ab |
abdcb | ab |
就类似一个过滤。
下面是一些常用符号:
- ^
表示补集: %[^abc] 遇到abc停止
- ‘-‘表示区间: %[A-Z] A-Z范围
- %[^\n] 表示可以吸收空格,回车结束;
char s[10];
scanf("%s",s);
printf("%s",s);
比如输入的是'I love you'
那么输出的s 是I, 而不是I love you
因为空格作为了分隔符。
而想要吸收空格可以用 扫描集
char s[10];
scanf("%[^\n]",s);
printf("%s",s);
表示只有输入回车才结束
此时再输入 I love you
将完整输出 I love you
再看一个例子:
要去出一个邮箱的域名,经常用正则,那么这里用scanf的该怎么使用呢?
char s[30];
scanf("%*[^@]@%[^\.]",s);
printf("%s",s);
这个可以 输入mymail@gmail.com
输出就会是 gmail
;
首先分成三部分%*[^@]
和@
和%[^\.]
;
%*[^@]
表示过滤前面的不是@
的部分,这部分读取到了mymail
但是不保存到变量 s
。第二部分@
是指过滤掉 缓存区中的 @
字符。 最后一部分%[^\.]
则表示选择不是.
的部分,对应字符串中的gmail
部分,并且赋值给s。
注:
1. 在scanf()正则里面 最多只能有一个%
表示选择。而过滤%*
可以有多个
2. 上述所讲的正则规则 与sscanf()函数完全适用。只不过是输入方式不同。
其实 scanf()用正则比较少。sscanf()就比较常用了。很方便的处理字符串。
5.scanf()缓冲区问题总结
int a;
char c;
scanf("%d",&a);
scanf("%c",&c);
printf("a=%d c=%c",a,c);
比如输入20 a
那么输出将会是 20
和一个空格[前面已经提到过]
如果打算想 输入20
之后 回车再输入’a’ 结果会是输入回车之后 就会输出。这时候如果输入c的ASCII码值就会发现是 10 正好是\n
这样就对了,\n
被scanf()函数“错误”地赋给了c;
常见的解决方法:
1. 在第一个scanf()之后加入getchar()函数可以消掉回车。具体原理还不太懂。。
2. 还有就是利用fflush(stdin);
刷新或者清空缓冲区,这样输入一个20
之后 按回车的话就可以,继续输入字符 赋值给c,如下:
#include <stdio.h>
int main()
{
int a,b;
char c;
scanf("%d",&a);
fflush(stdin);
scanf("%c",&c);
printf("a=%d c=%d\n",a,c);
}
这样就可以了。
上面是学了以scanf的一些总结, 虽然平时使用的很简单,但是总感觉不太踏实,因为总时不时的出错。这次记录一下学习收获挺大的。