鱼C论坛

 找回密码
 立即注册
查看: 1979|回复: 3

[技术交流] I/O缓冲区

[复制链接]
发表于 2022-4-12 15:38:00 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x
此帖记录缓冲区在编程中产生的各种影响及引发的相关问题
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

 楼主| 发表于 2022-4-12 15:55:15 | 显示全部楼层
本帖最后由 风车呼呼呼 于 2022-4-12 16:28 编辑

1.scanf()函数

scanf()输入结束后,将在缓冲区留下'\n',下一次向缓冲区取数据时,务必先将'\n'取出(使用getchar()

验证:
  1. #include <stdio.h>

  2. int main() {
  3.         int a, b;
  4.         scanf("%d", &a);
  5.         printf("a: %d\n", a);
  6.         b = getchar();
  7.         printf("b: %d\n", b);
  8.         return 0;
  9. }
复制代码


输出结果:
  1. a
  2. a: 7
  3. b: 10
复制代码


缓冲区留有'\n'所引发的问题:
  1. #include <stdio.h>

  2. int main() {
  3.         int a;
  4.         char b, c;
  5.         scanf("%d", &a);
  6.         printf("a: %d\n", a);
  7.         scanf("%c", &b);
  8.         printf("b: %c\n", b);
  9.         c = getchar();
  10.         printf("c: %c\n", c);
  11.         return 0;
  12. }
复制代码

输出结果:
  1. 5
  2. a: 5
  3. b:

  4. k
  5. c: k
复制代码
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2022-4-12 16:28:03 | 显示全部楼层
本帖最后由 风车呼呼呼 于 2022-4-12 17:26 编辑

2.getchar()与while()

先上代码
  1. #include <stdio.h>

  2. int main() {
  3.         char i;
  4.         while((i = getchar()) != '\n'){
  5.                 putchar(i);
  6.         }
  7.         putchar('\n');
  8.         return 0;
  9. }
复制代码

输出结果:
  1. Hello World!
  2. Hello World!
复制代码


思考:根据while()的逻辑以及getchar()和putchar()的特性,为什么不是输入一个字符,界面上就紧接着打印这个字符,而是全部输出结束后才一起打印出来呢?

稍稍修改一下代码,给while换一个判断条件
  1. #include <stdio.h>

  2. int main() {
  3.         char i;
  4.         while((i = getchar()) != 'a'){
  5.                 putchar(i);
  6.         }
  7.         putchar('\n');
  8.         return 0;
  9. }
复制代码

输出结果:
  1. x
  2. x
  3. y
  4. y
  5. z
  6. z
  7. a

复制代码


这下符合原先认为的逻辑了,那么开始找两者的差别
为什么判断条件设置为'\n'就不能逐一打印呢?

单独运行一条getchar语句会发现,getchar()调用结束的标志正是'\n',而while顺利循环下去的条件则是输入非换行符
那么说明,只要while不结束,甚至第一次调用的getchar语句都没有调用完

What???我在键盘上都输入了那~么一大串字符,你现在跟我讲它连第一个字符都没有读入?
没错!就是这么出乎意料,匪夷所思

下面来重新捋一捋getchar()是怎么工作的
实际上,与其说getchar()是获取用户在键盘上输入的一个字符,真实情况却是在缓冲区中获取一个字符
缓冲区为空时,它会允许用户向缓冲区中输入数据
缓冲区中存在数据时,它会直接取走缓冲区中的第一个字符,用户根本不需要输入


现在,返回刚才的代码讨论
我们说到在while判断条件为假之前,第一次对getchar的调用都无法结束。
第一次调用getchar()时,由于缓冲区中并没有数据,所以开始允许用户向缓冲区中输入数据
又因为一直接收不到'\n'作为函数结束标志,故在此期间用户可以一直输入(要是缓冲区满了就另说了)


假设我们输入的内容是
  1. abc
复制代码

(这便是缓冲区中的内容)
接着按下回车...

注意了!注意了!注意了!
虽然while退出的条件正是回车,但这个时候还远远没到退出循环的时候呢

这时我们对getchar()的第一次调用才刚刚准备结束

还记得getchar是要干嘛吗?没错,就是从缓冲区里取走第一个字符

所以第一次getchar()取走了'a',并且把它赋值给了变量i
紧接着进行条件判断,'a' != '\n' 成立,putchar()在屏幕上打印出字符a

然后开始第二轮循环,同理getchar()取走了'b',putchar()紧接在字符a后面打印出了字符b(putchar函数并没有自带换行,所以是挨着a后边打印)

第三轮循环,同理打印出字符c,此时屏幕上显示的正是

  1. abc
复制代码

最后第四轮循环,此时缓冲区中还留有一个'\n'
getchar()将其取出并赋值给变量i,'\n' != '\n' 关系表达式为假
不进入循环体,while循环结束

想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2022-4-13 13:49:27 | 显示全部楼层
原来如此,我懂了..可是i/o缓冲区好像是最后一节课的内容诶
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2024-5-22 21:29

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表