Chinaunix首页 | 论坛 | 博客
  • 博客访问: 804937
  • 博文数量: 87
  • 博客积分: 2571
  • 博客等级: 少校
  • 技术积分: 726
  • 用 户 组: 普通用户
  • 注册时间: 2010-01-19 15:04
个人简介

重新开始,做回自我,爱拼的男人最牛!

文章分类
文章存档

2021年(2)

2020年(3)

2019年(17)

2014年(1)

2011年(1)

2010年(63)

我的朋友

分类: C/C++

2019-12-09 11:24:20

原文链接:

scanf() 是带有缓冲区的。遇到 scanf() 函数,程序会先检查输入缓冲区中是否有数据:

  • 如果没有,就等待用户输入。用户从键盘输入的每个字符都会暂时保存到缓冲区,直到按下回车键,输入结束,scanf() 再从缓冲区中读取数据,赋值给变量。
  • 如果有数据,哪怕是一个字符,scanf() 也会直接读取,不会等待用户输入。


请看下面的例子:

	
  1. #include
  2. #include
  3. int main()
  4. {
  5. int a, b, c;
  6. scanf("%d", &a);
  7. scanf("%d", &b);
  8. scanf("%d", &c);
  9. printf("a=%d, b=%d, c=%d\n", a, b, c);
  10. system("pause");
  11. return 0;
  12. }

运行结果:
100 200 300↙
a=100, b=200, c=300

程序执行到第一个 scanf(),由于缓冲区中没有数据,所以会等待用户输入。从键盘输入100 200 300后按下回车键,输入就结束了,scanf() 开始从缓冲区中读取数据。由于控制字符串是"%d",所以它会读取一个整数,这里匹配到的整数是100。接下来将100赋值给变量 a,并将100从缓冲区中删除,此时缓冲区中剩下200 300。

注意:scanf() 匹配到想要的数据后,会将匹配到的数据从缓冲区中删除,而没有匹配到的数据仍然会留在缓冲区中。

执行到第二个 scanf() 时,检测到缓冲区中有内容,所以不会等待用户输入,而是直接从缓冲区中读取。此时缓冲区中的内容为200 300,scanf() 会匹配到整数200,并将200从缓冲区中删除,剩下300。

执行到第三个 scanf() 时,同理会匹配到300,并将300赋值给变量 c。

再来看一个例子:

	
  1. #include
  2. #include
  3. int main()
  4. {
  5. int a, b=999;
  6. char str[30];
  7. printf("b=%d\n", b);
  8. scanf("%d", &a);
  9. scanf("%d", &b);
  10. scanf("%s", str);
  11. printf("a=%d, b=%d, str=%s\n", a, b, str);
  12. system("pause");
  13. return 0;
  14. }

运行结果:
b=999
100 c.biancheng.net↙
a=100, b=999, str=c.biancheng.net

程序执行到第一个 scanf() 时等待用户输入。从键盘输入100 c.biancheng.net,按下回车键,scanf() 匹配到100,赋值给变量a,同时将100从缓冲区中删除。

执行到第二个 scanf() 时,缓冲区中有数据,会直接读取。由于此时缓冲区中的内容为 c.biancheng.net,并不是 scanf() 想要的整数,所以匹配失败,不会给变量b赋值,这就是两次输出变量b的值相同的原因。匹配失败也意味着不会从缓冲区中删除任何数据。

执行到第三个 scanf() 时,缓冲区中的内容仍然是 c.biancheng.net,明显是字符串,所以匹配成功并赋值给 str。

值得一提的是,在控制台中输入的任何内容本质上都是字符串,都会被%s所匹配。对于上面的程序,不妨换成下面的输入内容:

 

b=999
100 200 300↙
a=100, b=200, str=300

看,300 也被 %s 匹配成功。

缓冲区引发的问题

缓冲区虽然能够让输入更加方便,但有时也会引发奇怪的问题。例如:

	
  1. #include
  2. #include
  3. int main()
  4. {
  5. int a=0, b=0;
  6. scanf("a=%d", &a);
  7. scanf("b=%d", &b);
  8. printf("a=%d, b=%d\n", a, b);
  9. system("pause");
  10. return 0;
  11. }

运行结果:
a=100↙
a=100, b=0

遇到第一个 scanf(),输入a=100并回车,就会将100赋值给a,并将a=100从缓冲区中删除。遇到第二个 scanf() 时,缓冲区中不是没有内容了吗,为什么不会等待用户输入呢?

其实当用户按下回车键时,回车换行符也会被保存到缓冲区,只是大多数情况下 scanf() 会忽略,前面的两个例子就是这样。但是当控制字符串不是以 %xxx 开头时,回车换行符就起作用了,scanf() 会对它进行匹配,只是匹配失败而已。该例中第二个 scanf() 就是匹配回车换行符失败,所以既不等待用户输入,也不给b赋值。

将第二个 scanf() 的控制字符串改成下面的样子:

scanf("%d", &b);

运行结果:
a=100↙
200↙
a=100, b=200

此时 scanf() 就会忽略缓冲区中的回车换行符,等待用户输入。

阅读(1785) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~