关于c语言的scanf用来读取字符的一些总结
scanf() 是带有缓冲区的。遇到 scanf() 函数,程序会先检查缓冲区中是否已经有数据
- 如果没有,就等待用户输入。用户从键盘输入的每个字符都会暂时保存到缓冲区,直到按下回车键,输入结束,scanf() 再从缓冲区中读取数据,赋值给变量。
- 如果有数据,哪怕是一个字符,scanf() 也会直接读取,不会等待用户输入。
- 注意:scanf() 匹配到想要的数据后,会将匹配到的数据从缓冲区中删除,而没有匹配到的数据仍然会留在缓冲区中。
scanf("%c",&ch)类型
1.单纯使用%c
#include<stdio.h>
#include<stdlib.h>
int main(){
system("color F4");
int i=0;
char c;
char s[5];
for(i=0;i<5;i++){
scanf("%c",&s[i]);
c = s[i];
printf("%c %c\n",s[i],c);
}
return 0;
}
输入过程理解:
第一次:你认为你输入的是a
,缓存区里面是a'\n'
结果就是s[0]=c=a,打印a,a 然后换行,i=1;缓存区剩下'\n'
,然后是s[1] = s[1] = ‘\n’,打印 ‘\n’,’\n’,然后换行。i=2,缓冲区空。
第二次:同理,你认为你输入了c
,缓冲区里面是c'\n'
结果就是s[2]=c=‘c’,打印c,c 然后换行,i=3;缓冲区剩下'\n'
,然后是s[3] = s[3] = ‘\n’,打印 ‘\n’,’\n’,然后换行。i=4,缓冲区空。
第三次:你认为你输入了d
,缓冲区里面是d'\n'
结果就是s[4]=c=‘d’,打印d,d 然后换行,i=5,结束。
解决办法
修改格式,我们忽略缓冲区上一次的残留。
scanf(" %c",&s[i]);
2.当要输入整数又要输入字符时
#include<stdio.h>
#include<stdlib.h>
int main()
{
system("color F4");
char a,b,c;
int number;
scanf("%d",&number);
scanf("%c%c%c",&a,&b,&c);//"%c %c %c"三个%c之间没有空格
if(a == 10) printf("字符a是换行\n");
else if(a == 32) printf("字符a是空格\n");
else printf("a = %c\n",a);
if(b == 10) printf("字符b是换行\n");
else if(b == 32) printf("字符b是空格\n");
else printf("b = %c\n",b);
if(c == 10) printf("字符c是换行\n");
else if(c == 32) printf("字符c是空格\n");
else printf("c = %c",c);
return 0;
}
我们就能知道scanf读取的过程了。所以要十分注意。
可以适当的加上语句getchar()来接受输入时带来的换行或者空格(空格可以在scanf()双引号中的格式中控制)。
scanf函数 注意事项及使用的形式
使用形式
- 返回值
scanf函数返回成功读入的数据项数,读入数据时遇到了“文件结束”则返回EOF。如:scanf("%d %d",&a,&b);
函数返回值为int型。如果a和b都被成功读入,那么scanf的返回值就是2;如果只有a被成功读入,返回值为1;如果a和b都未被成功读入,返回值为0;如果遇到错误或遇到end of file,返回值为EOF。end of file为Ctrl+z 或者Ctrl+d。 - 非空白符与空白符
非空白符使 scanf() 在流中读一个匹配的字符并忽略之。例如,"%d,%d" 使 scanf() 先读入一个整数,读入中放弃逗号,然后读另一个整数。如未发现匹配,scanf() 返回。空白字符会使scanf函数在读操作中略去输入中的一个或多个空白字符。 - 百分号(%)与格式符之间的星号(*)表示读指定类型的数据但不保存。因此,如:scanf("%d%*c%d",&x,&y);对 10/20 的读入操作中,10 放入变量 x,20 放入 y。
- 格式命令可以说明最大域宽。 在百分号(%)与格式码之间的整数用于限制从对应域读入的最大字符数。例如,希望向 address 读入不多于 20 个字符时,可以书写成如下形式:
scanf("%20s",address);
如果输入流的内容多于 20 个字符,则下次 scanf() 从此次停止处开始读入。 若达到最大域宽前已遇到空白符,则对该域的读立即停止;此时,scanf() 跳到下一个域。 - ANSI C 标准向 scanf() 增加了一种新特性,称为扫描集(scanset)。 扫描集定义一个字符集合,可由 scanf() 读入其中允许的字符并赋给对应字符数组。 扫描集合由一对方括号中的一串字符定义,左方括号前必须缀以百分号。 例如,以下的扫描集使 scanf() 读入字符 A、B 和 C:
%[ABC]
使用扫描集时,scanf() 连续吃进集合中的字符并放入对应的字符数组,直到发现不在集合中的字符为止(即扫描集仅读匹配的字符,返回时,数组中放置以 null 结尾、由读入字符组成的字符串。用连字符可以说明一个范围(C99无)
如%[A-Z]则可以读取A-Z的字符 "%n[a-z]"
读入最多n个字符,如果遇到非a-z的字符,停止;"%[^=]"
读入任意多的字符,直到遇到"=“停止;”%n[^=]"
读入"="号前的至多n 个字符
注意事项
- 在高版本的 Visual Studio 编译器中,scanf 被认为是不安全的,被弃用,应当使用scanf_s代替 scanf。
- 对于字符串数组或字符串指针变量,由于数组名可以转换为数组和指针变量名本身就是地址,因此使用scanf()函数时,不需要在它们前面加上"&"操作符。
- scanf中要求给出变量地址,如给出变量名则会出错。经常可能会犯的,要注意!!!
- scanf函数中没有类似printf的精度控制。如scanf("%5.2f",&a); 是非法的。不能企图用此语句输入小数为2位的实数
一些例子
One 如何让scanf()函数正确接受有空格的字符串?如: I love you!
解决办法是修改输入的格式
Two 键盘缓冲区残余信息问题
除了scanf(" %c",&s[i]);加空格忽略上一次的缓冲区字符,使用getchar()吃掉也行。
百度百科