当字符遇上 scanf() 要当心
当字符遇上 scanf() 要当心
看一下程序
char ch1,ch2;
printf("请输入ch1,ch2的值:");
scanf("%c %c",&ch1,&ch2);
printf("ch1 = %c, ch2 = %c\n",ch1,ch2);
printf("请再次输入ch1的值:");
scanf("%c",&ch1);
printf("请再次输入ch2的值:");
scanf("%c",&ch2);
printf("ch1 = %c, ch2 = %c\n",ch1,ch2);
运行结果如下:

第二次输出为什么会出现异常情况呢 ?
这里有两个问题
- 为什么出现了
请再次输入ch1的值:请再次输入ch2的值:的情况,按照原本的预测请应该是先出现请再次输入ch1的值:,键盘输入了一个字符之后再出现请再次输入ch2的值:,键盘再输入一个字符 - 为什么第二次输入ch1,的值后,直接就输出了ch1 和ch2 ,而且 ch1 = '\n', ch2 = 'C'?
第一个问题
首先需要知道CPU 的工作原理
由于输入设备和输出设备对于数据的读写速度比较慢,CPU为了降低输入输出次数,提高运行效率,避免长时间的等待,所以内核就在内存中提供了一块空间作为缓冲区,( 缓冲区也可以称为缓存(Cache),是属于内存空间的一部分。)
每当使用读操作函数,试图将数据读取出来时,数据都会流过标准*输入缓冲区*,然后再在适当的时刻冲洗(或称刷新,flush)到内核缓冲区,最后才真正得到数据。
所以CPU 并不是没每时每刻都在读取数据,而是在满足刷新条件时才会从出入缓冲区读取数据。刷新条件按形式分为三种:全缓冲、行缓冲、无缓冲。
全缓冲:指的是当缓冲区被填满就立即把数据冲刷到文件、或者在关闭文件、读取文件内容以及修改缓冲区类型时也会立即把数据冲刷到文件,一般读写文件的时候会采用
无缓冲:指的是没有缓冲区,直接输出,一般linux系统的标准出错stderr就是采用无缓冲,这样可以把错误信息直接输出。
行缓冲:指的是当缓冲区被填满(一般缓冲区为4KB,就是4096字节)或者缓冲区中遇到换行符’\n’时,或者在关闭文件、读取文件内容以及修改缓冲区类型时也会立即把数据冲刷到文件中,一般操作IO设备时会采用,比如printf函数就是采用行缓冲。
知道了CPU 工作原理之后,我们就知道了printf() 函数的刷新条件有四个:
- 程序结束;
- 遇到换行 ‘\n’;
- 缓冲区满;
- 利用函数fflush() 手动刷新.
这也就解释了为什么出现 请再次输入ch1的值:请再次输入ch2的值:的情况,是因为没有遇到刷新条件,所以在写程序时,非必要情况都需要加上换行‘\n’。
第二个问题
在解释CPU 工作原理是说过 Linux 系统读取数据,是先从键盘进入到输入缓冲区,再进入到内核缓冲区,最后读取到数据。所以在第一次输入ch1 ,ch2 的值为A B<手动输入'\n' ,缓冲区应该是字符串
"A B\n", CPU 先读取“A B”,光标位置在字符B 的后面,当再次从缓冲区读取字符型数据时读出来的是字符‘\n’ ,ch1 = '\n', ch2 读取的是后面输入的字母C 。
那么我们如何解决这个问题呢?
在读取字符之前先要清空缓冲区,使用函数getchar() ,让光标后移到正确的位置,如下:
char ch1,ch2;
printf("请输入ch1,ch2的值:");
scanf("%c %c",&ch1,&ch2);
printf("ch1 = %c, ch2 = %c\n",ch1,ch2);
getchar(); //读取换行符
printf("请再次输入ch1的值:");
scanf("%c",&ch1);
getchar(); //读取换行符
printf("请再次输入ch2的值:");
scanf("%c",&ch2);
printf("ch1 = %c, ch2 = %c\n",ch1,ch2);

当字符遇上 scanf() 要当心的更多相关文章
- 前端遇上Go: 静态资源增量更新的新实践
前端遇上Go: 静态资源增量更新的新实践https://mp.weixin.qq.com/s/hCqQW1F8FngPPGZAisAWUg 前端遇上Go: 静态资源增量更新的新实践 原创: 洋河 美团 ...
- DP在字符匹配上的实现
在此保存下近段时间做的DP在字符匹配上的实现的题目 对于不同的字符串来说,2者只能不断将下标往后推移来实现匹配从而得到的最大匹配数 如 abcd 和 dcba 这个最大匹配数只能为1,因为两个d匹配后 ...
- html实体编码遇上js代码
单双引号 在js代码中 在js中单.双引号引起来的是字符串,如果我们要在字符串中使用单.双引号,需要反斜杠进行转义 let str='user\'s name'; // or let str=&quo ...
- MVC遇上bootstrap后的ajax表单模型验证
MVC遇上bootstrap后的ajax表单验证 使用bootstrap后他由他自带的样式has-error,想要使用它就会比较麻烦,往常使用jqueyr.validate的话只有使用他自己的样式了, ...
- 敏捷遇上UML-需求分析及软件设计最佳实践(郑州站 2014-6-7)
邀请函: 尊敬的阁下:我们将在郑州为您奉献高端知识大餐,当敏捷遇上UML,会发生怎样的化学作用呢?首席专家张老师将会为您分享需求分析及软件设计方面的最佳实践,帮助您掌握敏捷.UML及两者相结合的实 ...
- 敏捷遇上UML—软创基地马年大会(广州站 2014-4-19)
我们将在广州为您奉献高端知识大餐,当敏捷遇上UML,会发生怎样的化学作用呢?首席专家张老师将会为您分享需求分析及软件设计方面的最佳实践,帮助您掌握敏捷.UML及两者相结合的实战技巧. 时间:2 ...
- 敏捷遇上UML——软创基地马年大会(深圳站 2014-3-15)
邀请函: 尊敬的阁下: 我们将在深圳为您奉献高端知识大餐,当敏捷遇上UML,会发生怎样的化学作用呢?首席专家张老师将会为您分享需求分析及软件设计方面的最佳实践,帮助您掌握敏捷.UML及两者相结合的实战 ...
- 初识genymotion安装遇上的VirtualBox问题
想必做过Android开发的都讨厌那慢如蜗牛的 eclipse原生Android模拟器吧! 光是启动这个模拟器都得花上两三分钟,慢慢的用起来手机来调试,但那毕竟不是长久之计,也确实不方便,后来知道了g ...
- SQL SERVER 2008 R2 SP1更新时,遇上共享功能更新失败解决方案
SQL SERVER 2008 R2 SP1更新时,遇上共享功能更新失败的问题,可作如下尝试: 更新失败后,在windows的[事件查看器→应用程序]中找到来源为MsiInstaller,事件ID为1 ...
- 当创业遇上O2O,新一批死亡名单,看完震惊了!
当创业遇上O2O,故事就开始了,总投入1.6亿.半年开7家便利店.会员猛增至10万……2015半年过去后,很多故事在后面变成了一场创业“事故”,是模式错误还是烧钱过度?这些项目的失败能给国内创业者带来 ...
随机推荐
- CTFshow pwn53 wp
PWN53 那么先看保护 虽然没有开canary但是本题在ida打开看见他是模拟了canary的效果,不同的是他的是固定的canary,但是一样要爆破 而且发现还有后门函数 在ctfshow函数我们发 ...
- #计数,记忆化搜索#C 连边方案
分析 设\(dp[i][j][k][l]\)表示处理到\([i-l+1,i]\)的连边,二进制状态(奇点还是偶点)为\(k\)的方案数, 最后一维是为了避免算重,那么如果第\(i-l+1\)位是偶点可 ...
- Transformer从入门到精通(The Annotated Transformer翻译)
Transformer从入门到精通(The Annotated Transformer) Attention is All You Need v2022: Austin Huang, Suraj Su ...
- openGauss3.1.0 版本的gs_stack功能解密
openGauss3.1.0 版本的 gs_stack 功能解密 不管是测试还是研发,工作中总有遇到各种各样的问题.比如,你有没有遇到过在数据库中执行某个 SQL,却一直不返回结果,这时候的你是不是非 ...
- 优先队列的基本实现【数据结构与算法—TypeScript 实现】
笔记整理自 coderwhy 『TypeScript 高阶数据结构与算法』课程 特性 效率比普通队列高 每个出队元素拥有最高优先级 可以用 数组.链表 等数据结构实现,但是 堆结构 是最常用的实现方式 ...
- 动态规划(五)——坐标dp
传纸条 题目描述 小渊和小轩是好朋友也是同班同学,他们在一起总有谈不完的话题.一次素质拓展活动中,班上同学安排做成一个m行n列的矩阵, 而小渊和小轩被安排在矩阵对角线的两端,因此,他们就无法直接交谈了 ...
- mysql 重新整理——索引优化explain字段介绍二 [十]
前言 紧接上文. 正文 type type字段有如下类型: 1.all 2.index 3.rang 4.ref 5.eq_ref 6.const,system 7.null 最好到最差的顺序为: s ...
- node 父子进程传递对象
背景 node的父子进程中可以传递这是肯定的,但是传递对象,这是一个稀奇的地方. code 发送 server 对象 sendHandle 参数可用于将一个 TCP server 对象句柄传给子进程, ...
- Hologres+Hologres+Flink流批一体首次落地4982亿背后的营销分析大屏Flink流批一体首次落地4982亿背后的营销分析大屏
简介: 本篇将重点介绍Hologres在阿里巴巴淘宝营销活动分析场景的最佳实践,揭秘Flink+Hologres流批一体首次落地阿里双11营销分析大屏背后的技术考验. 概要:刚刚结束的2020天猫双1 ...
- JVM性能提升50%,聊一聊背后的秘密武器Alibaba Dragonwell
简介: 你要知道的关于Alibaba Dragonwell一些重要优化措施. 今年四月五日,阿里云开放了新一代ECS实例的邀测[1],Alibaba Dragonwell也在新ECS上进行了极致 ...