在看K&R的时候对于getchar()产生了一点疑问,下面根据自己的理解和几个例子说明一下。
Q1:关于EOF
#include <stdio.h>
int main() {
int c;
while((c = getchar()) != EOF)
putchar(c);
return 0;
}
如果输入hello回车,输出结果如下:
hello
hello
此时再输入ctrl+D(即linux下的EOF表示),程序结束。如果输入hello之后不输入回车,而是EOF,此时程序并没有结束,而是可以继续输入,但并不换行。若再直接ctrl+D那么程序结束。
这说明,当getchar()读取到换行符的时候,认为此次输入结束。程序换行,执行putchar()输出刚才输入的内容。如果不以回车,而以EOF作为结尾,getchar()仍然并且只是认为此次输入结束,而不是结束程序。当EOF单独出现的时候,getchar()才认为是输入行为终止。
Q2:getchar()获取几个字符?如何执行的?
在上面的例子中,输入hello,输出hello。那程序执行的过程是不是getchar()获取到了hello,将其赋给c,判断c!=EOF,输出c?看下面这个例子
#include <stdio.h>
int main() {
int c;
c = getchar();
putchar(c);
/*
c = getchar();
putchar(c);
*/
return 0;
}
还用'hello'作为例子,当我们输入hello回车时,程序输出h,然后结束。很显然,getchar()只获取到了一个字符。
当把注释去掉,再次执行程序。输入hello回车,输出he。程序中出现了两次getchar(),但整个过程中只有一次键盘输入过程,也即第一次getchar(),第二次getchar()并没有要求终端输入。看来,将getchar()理解为请求终端获取输入也不完全正确。其实getchar()的执行的原理是这样的(有部分个人理解):
用键盘输入字符的时候,输入的字符被放入了缓冲区,直到用户按下回车结束本次输入(回车符也被放入缓冲区)。其实getchar()是从输入流缓冲区中读取数据的,如果缓冲区中没有数据,则会进入等待,直到缓冲区有数据。这也就是程序执行到第一个getchar()时会等待用户输入的原因。当缓冲区有数据时,getchar()会从缓冲区获取第一个字符(显然,缓冲区是FIFO的),在例子中就是h,putchar(c)输出h,再次执行getchar(),获取到了e,putchar(c)输出e,程序结束。
当然,假设只输入一个字符'a'的时候,也只需要一次键盘输入,程序就会结束。因为回车也算作一个字符,所以输入的其实是两个字符。直接输入回车的话,就需要输入两次才能结束程序。
最后再看一个例子证明一下上面的判断:
#include <stdio.h>
int main() {
int ch1, ch2;
ch1 = getchar();
ch2 = getchar();
printf("%d %d", ch1, ch2);
return 0;
}
输入hello,输出104 101。这两个数字也正是h和e的ascii码。
Q3:关于getch()
getch()和getchar()类似,也是获取一个字符。
不同的是getch()不从缓冲区获取,而是直接从键盘输入获取,也即输入一个字符,立刻返回一个字符,不需要按回车。
Q4:关于scanf()
scanf()类似getchar(),略有不同的是结束标志。看下面的例子:
#include <stdio.h>
int main() {
char chs1[10], chs2[10];
scanf("%s", chs1);
printf("%s\n", chs1);
scanf("%s", chs2);
printf("%s\n", chs2);
return 0;
}
输入hello world,发现只需要一次输入,程序会输出两次,然后结束。scanf()与getchar()一样,也是从输入流缓冲区获取数据,不同的是,scanf()获取数据时如果
遇到回车、空格或TAB则会停止,一次获取数据过程结束。第二个scanf()会继续从输入流缓冲区获取数据。
在Q1中,如果输入hello回车,仔细观察的话会发现,输出也是hello回车,说明getchar()也获取了缓冲区的回车符。如果在上面这个例子中输入hello回车,输出也是hello回车,并且程序没有结束而是继续等待用户输入,这说明第二个scanf()从缓冲区获取不到数据了,然后等待用户输入,输入world回车,输出world,程序结束。即下面的结果:
hello
hello
world
world
首先说明,
scanf()丢弃了输入hello后的那个回车符,也即scanf()读取字符串会丢弃结尾的回车符。从这个例子中也可以看出,输入hello回车,输出也是hello回车,但是printf()中有一个\n换行符,如果scanf()能获取到hello后面的回车的话,输出结果应该下面这个样子的:
hello
hello
world
world
这也说明了scanf()会丢弃字符串结尾的回车符。
但注意,回车符并没有被scanf()跳过而残留在缓冲区内,而是被scanf()获取但是丢弃了,此时缓冲区内的回车符已经不存在了。
Q5:关于gets()
gets和scanf()的用法类似,但是gets()可以获取带空格的字符串,看这个例子:
#include <stdio.h>
int main() {
char chs1[10], chs2[10];
gets(chs1);
printf("%s\n", chs1);
gets(chs2);
printf("%s\n", chs2);
return 0;
}
输入hello world,输出hello world,并继续等待用户输入,输入helloTABworld,输出helloTABworld(TAB代表键盘的tab键,输入制表符),程序结束。
hello world
hello world
hello world
hello world
gets()并不会因为字符串中有空格或者TAB而结束字符的获取,但和scanf()一样,会忽略字符串结尾的回车符。
清除缓冲区内的残留数据
1、利用函数fflush(stdin)
注意:ANSI C中并没有将这个函数作为标准的一部分,是编译器支持的,并不是所有编译器都支持这个函数。所以,严格的讲,这样并不具备绝对的可移植性。
2、手动取出缓冲区里的残留数据
scanf("%[^\n]",str);
分享到:
相关推荐
嵌入式八股文面试题库资料知识宝典-华为的面试试题.zip
训练导控系统设计.pdf
嵌入式八股文面试题库资料知识宝典-网络编程.zip
人脸转正GAN模型的高效压缩.pdf
少儿编程scratch项目源代码文件案例素材-几何冲刺 转瞬即逝.zip
少儿编程scratch项目源代码文件案例素材-鸡蛋.zip
嵌入式系统_USB设备枚举与HID通信_CH559单片机USB主机键盘鼠标复合设备控制_基于CH559单片机的USB主机模式设备枚举与键盘鼠标数据收发系统支持复合设备识别与HID
嵌入式八股文面试题库资料知识宝典-linux常见面试题.zip
面向智慧工地的压力机在线数据的预警应用开发.pdf
基于Unity3D的鱼类运动行为可视化研究.pdf
少儿编程scratch项目源代码文件案例素材-霍格沃茨魔法学校.zip
少儿编程scratch项目源代码文件案例素材-金币冲刺.zip
内容概要:本文深入探讨了HarmonyOS编译构建子系统的作用及其技术细节。作为鸿蒙操作系统背后的关键技术之一,编译构建子系统通过GN和Ninja工具实现了高效的源代码到机器代码的转换,确保了系统的稳定性和性能优化。该系统不仅支持多系统版本构建、芯片厂商定制,还具备强大的调试与维护能力。其高效编译速度、灵活性和可扩展性使其在华为设备和其他智能终端中发挥了重要作用。文章还比较了HarmonyOS编译构建子系统与安卓和iOS编译系统的异同,并展望了其未来的发展趋势和技术演进方向。; 适合人群:对操作系统底层技术感兴趣的开发者、工程师和技术爱好者。; 使用场景及目标:①了解HarmonyOS编译构建子系统的基本概念和工作原理;②掌握其在不同设备上的应用和优化策略;③对比HarmonyOS与安卓、iOS编译系统的差异;④探索其未来发展方向和技术演进路径。; 其他说明:本文详细介绍了HarmonyOS编译构建子系统的架构设计、核心功能和实际应用案例,强调了其在万物互联时代的重要性和潜力。阅读时建议重点关注编译构建子系统的独特优势及其对鸿蒙生态系统的深远影响。
嵌入式八股文面试题库资料知识宝典-奇虎360 2015校园招聘C++研发工程师笔试题.zip
嵌入式八股文面试题库资料知识宝典-腾讯2014校园招聘C语言笔试题(附答案).zip
双种群变异策略改进RWCE算法优化换热网络.pdf
内容概要:本文详细介绍了基于瞬时无功功率理论的三电平有源电力滤波器(APF)仿真研究。主要内容涵盖并联型APF的工作原理、三相三电平NPC结构、谐波检测方法(ipiq)、双闭环控制策略(电压外环+电流内环PI控制)以及SVPWM矢量调制技术。仿真结果显示,在APF投入前后,电网电流THD从21.9%降至3.77%,显著提高了电能质量。 适用人群:从事电力系统研究、电力电子技术开发的专业人士,尤其是对有源电力滤波器及其仿真感兴趣的工程师和技术人员。 使用场景及目标:适用于需要解决电力系统中谐波污染和无功补偿问题的研究项目。目标是通过仿真验证APF的有效性和可行性,优化电力系统的电能质量。 其他说明:文中提到的仿真模型涉及多个关键模块,如三相交流电压模块、非线性负载、信号采集模块、LC滤波器模块等,这些模块的设计和协同工作对于实现良好的谐波抑制和无功补偿至关重要。
内容概要:本文探讨了在工业自动化和物联网交汇背景下,构建OPC DA转MQTT网关软件的需求及其具体实现方法。文中详细介绍了如何利用Python编程语言及相关库(如OpenOPC用于读取OPC DA数据,paho-mqtt用于MQTT消息传递),完成从OPC DA数据解析、格式转换到最终通过MQTT协议发布数据的关键步骤。此外,还讨论了针对不良网络环境下数据传输优化措施以及后续测试验证过程。 适合人群:从事工业自动化系统集成、物联网项目开发的技术人员,特别是那些希望提升跨协议数据交换能力的专业人士。 使用场景及目标:适用于需要在不同通信协议间建立高效稳定的数据通道的应用场合,比如制造业生产线监控、远程设备管理等。主要目的是克服传统有线网络限制,实现在不稳定无线网络条件下仍能保持良好性能的数据传输。 其他说明:文中提供了具体的代码片段帮助理解整个流程,并强调了实际部署过程中可能遇到的问题及解决方案。
基于C#实现的检测小说章节的重复、缺失、广告等功能+源码+项目文档,适合毕业设计、课程设计、项目开发。项目源码已经过严格测试,可以放心参考并在此基础上延申使用,详情见md文档 基于C#实现的检测小说章节的重复、缺失、广告等功能+源码+项目文档,适合毕业设计、课程设计、项目开发。项目源码已经过严格测试,可以放心参考并在此基础上延申使用,详情见md文档~ 基于C#实现的检测小说章节的重复、缺失、广告等功能+源码+项目文档,适合毕业设计、课程设计、项目开发。项目源码已经过严格测试,可以放心参考并在此基础上延申使用,详情见md文档 基于C#实现的检测小说章节的重复、缺失、广告等功能+源码+项目文档,适合毕业设计、课程设计、项目开发。项目源码已经过严格测试,可以放心参考并在此基础上延申使用,详情见md文档 基于C#实现的检测小说章节的重复、缺失、广告等功能+源码+项目文档,适合毕业设计、课程设计、项目开发。项目源码已经过严格测试,可以放心参考并在此基础上延申使用,详情见md文档 基于C#实现的检测小说章节的重复、缺失、广告等功能+源码+项目文档,适合毕业设计、课程设计、项目开发。项目源码已经过严格测试,可以放心参考并在此基础上延申使用,详情见md文档
少儿编程scratch项目源代码文件案例素材-火柴人终极之战.zip