scanf函数
scanf函数,与printf函数一样,都被定义在stdio.h里,因此在使用scanf函数时要加上#include。它是格式输入函数,即按用户指定的格式从键盘上把数据输入到指定的变量之中,其关键字最末一个字母f即为“格式”(format)之意。
1.函数原型:
2.返回值
3.字符说明
3.其他字符--当任何其他字符出现载格式字符串中的,下一个字符必须于与它相匹配。包括空格、制表符和新行符,都用于从输入流中匹配并放弃字符,被匹配的字符都放弃。如果不匹配,函数不再读取直接返回。
4.注意问题
① 遇空格、“回车”、“跳格”键。
② 遇宽度结束。
③ 遇非法输入。
先看测试案例:
#include <stdio.h>
#include <stdlib.h>
#define N 100
int main()
{
while(1)
{
int i,j,k;
printf("Input i,j,k:\n");
scanf("%d",&i);
scanf("%d %d",&j,&k);
printf("i=%d,j=%d,k=%d",i,j,k);
printf("\n");
}
return 0;
}
测试结果:
由测试案例可以看出 3个整形值,输入的时候 无论有多少个空格或者回车键都不影响i,j,k三个值的输入。都会自动过滤掉空格或者回车键。
然后我们测试下 char 类型的:
测试案例:
#include <stdio.h>
#include <stdlib.h>
#define N 100
int main()
{
// while(1)
// {
int i;
char j,k,c,d;
printf("Input i,j,k:\n");
scanf("%d",&i);
scanf("%c %c",&j,&k);
printf("i=%d,j=%c,k=%c",i,j,k);
printf("\n");
scanf("%c",&c);
printf("c=%c",c);
scanf("%c",&d);
printf("d=%c",d);
// }
return 0;
}
来看一下测试结果:
#代表空格 ,*代表回车
从上面的这张测试图我们可以看出:显然没有达到我们预期的效果,我们在输入了1*a#b* (我们的本意是1赋值给i,a 和b 分别赋值给j,k )但是 不等我们输入c和d的值,它就全部打印出来了。
原因如下:j,k,c,d 都是字符型的值,它可以接收 回车 空格和Tab键,当scanf函数以%c格式接收单个字符时,空格、回车、Tab键将不再作为分隔符,它们以ASCII码形式存储到对应参数地址所在内存空间。
看一下内存缓冲区的概念:
缓冲区是为了提高存储器访问效率的存在。绝大多数输入输出流是完全缓冲的,数据流先进入内存缓冲区,当它写满时才会刷新(flush)到设备或文件中。“读取”和“写入”操作实际是从缓冲区(buffer)来回复制数据。但使用标准输入或输出时,并不一定会等到缓冲区满才执行刷新操作,缓冲状态由编译器决定。
scanf函数从标准输入流(stdin)读取数据,按照格式说明参数,将数据写入参数地址所在空间。标准输入流默认的是键盘的输入流。但由于操作系统的缓冲区管理机制,从键盘上输入的数据并不是立刻被scanf函数读取,而是暂存于内存缓冲区,只有敲回车键的时候scanf函数才开始工作(尤其要注意,最后敲的回车键('/n')也会送入缓冲区)。也就是说,scanf函数取读的数据是缓冲区里的数据,只有当缓冲区为空的时候程序才会暂停下来,等待用户输入;反之,缓冲区不为空时它就不需要等待用户输入了,转而执行下一句程序指令!
对于我们的测试程序而言,我们在输入了1*a#b*之后,scanf开始工作 开始按照格式参数说明来匹配字符,首先找到1匹配给i,然后回车键* 批给给j a匹配给k,这时候我们的本意是等待c和d的输入,但是此时缓冲区中还存在#b*这3个字符,所以系统便没有等待这两个字符的输入,直接匹配。空格匹配给c,b匹配个d。
最后一个测试函数:
#include <stdio.h>
int main()
{
int a;
char c;
do
{
scanf("%d", &a);
scanf("%c", &c);
printf("a = %d c = %c\n", a, c);
} while(c != 'N');
return 0;
}
执行结果如下:
从上图我们看出:首先输入a+回车。这个时候a获得1 c获得回车,然后我们继续输入一个a和回车,此时也直接打印恶劣a和c的值。a=1,c=a。
对于这里我是这么理解的。首先我们输入a和回车的时候 。缓冲区里面有a和回车。
第一个scanf开始找整形d的值,找遍缓冲区。没找到。退出该scanf函数,
然后第二个scanf开始找字符型c的值,找到a输出a,而a是在dowhile外面定义的。根据上一步的1.打印出1.
如果这样理解有错误,请高手指出!~
使用scanf函数进行输入,必须指定输入的数据的类型和格式,不仅繁琐复杂,而且很容易出错.C++保留scanf只是为了和C兼容,以便过去用C语言写的程序可以在C++的环境下运行。C++的编程人员都愿意使用cin进行输入,很少使用scanf。