getchar、scanf以及缓冲区的概念

Linux下科大讯飞离线语音识别SDK从下载到实战(附常见问题解决) 本文详细介绍了在Linux系统下,如何从科大讯飞开放平台获取离线语音识别SDK,完成环境准备、编译部署到实战开发的完整流程。文章重点解析了SDK目录结构、语法词典定制、示例代码修改,并针对开发中常见的“词典加载失败”、音频格式、交叉编译及性能优化等问题提供了深度解决方案,助力嵌入式与IoT开发者快速实现稳定可靠的离线命令识别功能。 阅读详情
     1、getchar()是stdio.h中的库函数,它的作用是从stdin流中读入一个字符,也就是说,如果stdin有数据的话不用输入它就可以直接读取了。

      getch()和getche()是conio.h中的库函数,它的作用是从键盘接收字符,getchar带有回显。

      与前面两个函数的区别在于: getchar()函数等待输入直到按回车才结束(前提是缓冲区没有数据),回车前的所有输入字符都会逐个显示在屏幕上。但只有第一个字符作为函数的返回值。
#include "stdio.h"
#include "stdlib.h"
int main(void)
{
	char c;
	while((c=getchar())!='\n')     //每个getchar()依次读入一个字符
		printf("%c",c);            //按照原样输出
	printf("\n");
	system("pause");
	return 0;
}

       程序运行时,首先停下来,等你输入一串字符串,输入完毕后,它把你输入的整个字符串都输出来了,咦,你不是说getchar()只返回第一个字符么,这里怎么?

      因为我们输入的字符串并不是取了第一个字符就把剩下的字符串丢掉了,它还在我们的内存中,好比,开闸放水,我们把水放到闸里去以后,开一次闸就放掉一点,开一次就放掉一点,直到放光了为止,这里开闸动作就相当于调用一次getchar()。我们输入的字符串也是这么一回事,首先我们输入的字符串是放在内存的缓冲区中的,我们调用一次getchar()就把缓冲区中里出口最近的一个字符输出,也就是最前面的一个字符输出,输出后,就把它释放掉了,但后面还有字符串,所以我们就用循环把最前面的一个字符一个个的在内存中释放掉,直到满足循环条件退出为止。

     例子中循环条件里的'\n '实际上就是你输入字符串后的回车符,所以意思就是说,直到遇到回车符才结束循环,而getchar()函数就是等待输入(或缓冲区中的数据)直到按回车才结束,所以实现了整个字符串的输出。当然,我们也可以把循环条件改一下,比如while ((c=getchar())!='a'),什么意思呢,意思就是遇到字符'a'就停止循环,当然意思是如果你输入“12345a213123 ”那么只会输出到a前面的那个字符,结果是12345。

     再次注意:用getchar()它是从“流”中间去读取,所以第一个getchar()接受的是刚刚中断的流队列中即将出列的第一个字符(不限于回车符,上面举过例子了),如果流队列不为空,执行getchar()就继续放水,直到把回车符也放空为止,空了之后再在执行getchar()就停下等待你的输入了;我们用getch()为什么每次都是等待用户的输入呢?因为getch()是从键盘接收,即时的接收,并不是从stdin流中去读取数据。

     下面是我的讨论:

     先来一段code:

#include "stdio.h"
#include "stdlib.h"
int main(void)
{
	char c;
	for(;(c=getchar())!='a';)
		printf("%c",c);
	getchar();
	c=getchar();
	printf("%c",c);
	system("pause");
	return 0;
}

输入:  ssss回车

得到:   ssss

           光标处(等待输入)

说明:由于一直没有输入字符a,所以此时程序没有结束,进入到for循环后一直没有退出。键入回车后,运行c=getchar(),依次从缓冲区内取出(for循环):'s''s''s''s'' ' 包括回车的换行符,并将其全部打印了出来。。

如果我们输入:ssssa回车

得到:ssss光标处(等待输入)

说明:程序读入到字符a的时候跳出了for循环,但是由于我们用getchar();清除了换行符'\n ',后面第7句c=getchar();需要你输入一个字符(因为ssssa后面并没有新的字符),所以程序仍然没有结束。如果我们注释掉getchar();这一句,那么c=getchar();这行代码就可以读取ssssa后面的回车符号了,就可以得到这样的输出:  

       ssss

       光标处(程序结束)

这个输入ssssa中的回车中的换行符'\n '就被c=getchar();这一句读取并输出了。

        总结:

       键盘输入的字符都存到缓冲区内,一旦键入回车,getchar就进入缓冲区读取字符,一次只返回第一个字符作为getchar函数的值,如果有循环或足够多的getchar语句,就会依次读出缓冲区内的所有字符直到'\n '。要理解这一点,之所以你输入的一系列字符被依次读出来,是因为循环的作用使得反复利用getchar在缓冲区里读取字符,而不是getchar可以读取多个字符,事实上getchar每次只能读取一个字符。如果需要取消' \n'的影响,可以用getchar();来清除,这里getchar();只是取得了'\n '但是并没有赋给任何字符变量,所以不会有影响,相当于清除了这个字符,还要注意的是这里你在键盘上输入ssss看到的回显正是来自于getchar的作用,如果用getch就看不到你输入了什么。

          2、scanf

      scanf这个库函数比较奇怪,而且存在一定的缺陷,所以很多人都不用了,这里还是要简单介绍一下。

      scanf输入字符串、整型、实型等数据判断的方式都一样,回车、空格、tab键都认为是一个数据的结束,当然字符的话,一个字符就是结束了。回车、空格等都有对应的ASCII码,所以用scanf输入字符时要小心这些东西被当成字符输进去,而输入字符串和整型、实型等数据时这些都被当成分隔符而不会被输入到字符数组或变量里。当然如果输入格式不是"%s%s"而是"%s,%s"分隔符就是逗号了。

     说了这么多举几个例子:

#include "stdio.h"
int main(void)
{
	char n1[10];
	char n2[10];
	scanf("%s",n1);
	scanf("%s",n2);
	printf("n1=%s,n2=%s",n1,n2);
	return 0;
}

输入:

hello回车

world回车

得到如下的输出:

n1=hello,n2=wolrd光标处(程序结束)

       这里hello后面就是输入再多个回车、空格也不会被赋值到n2中的,因为使用scanf函数输入字符串的时候他们只是被当做分隔符。另外就是输入n2的时候,n2后面的那个回车也被当做了分隔符,所以输出的时候,只是简单的输出了n1和n2的内容,而没有输出回车换行符。


如果输入:

hello回车

光标处(等待输入)

说明回车被认成分隔符,所以程序还要你输入一个字符串来赋给n2。

其实这时缓冲区里是有一个'\n '被留下来的,程序改成这样:

#include "stdio.h"
int main(void) 
{
	char n1[10]; 
	char n2[10];
	char n3,n4; 
	scanf("%s",n1); 
	scanf("%s",n2); 
	printf("n1=%s,n2=%s",n1,n2);
	n3=getchar();      //n3读取了n2后面的那个回车字符并输出
	printf("%c",n3);
	//n4=getchar();
	//printf("%c",n4); 
	return 0;
}

输入:

hello回车

world回车

得到:  

n1=hello,n2=wolrd

光标处(程序结束)

如果取消最后两行的注释,同样的输入得到:

 n1=hello,n2=wolrd

光标处(等待输入)

说明此时缓冲区内只有一个'\n ',第二个getchar就需要你再输入一个字符了,缓冲区内已经没有字符了。

   scanf不会把回车、空格赋给字符串但是会赋给字符,就如同getchar一样,这时就要考虑'\n '的存在了。

比如:

#include "stdio.h"
int main(void) 
{
	char n1[10];
	char n2;
	scanf("%s",n1);
	scanf("%c",&n2);
	printf("n1=%s,n2=%d",n1,n2);
	return 0;
}

输入:

hello回车

得到:

n1=hello,n2=10光标处(程序结束)    //10是'\n '的ASCII码.

如果输入:

hello 空格回车(一定要有回车,因为scanf也是要等回车,准确说是' \n'才会去读缓冲区的。)

得到:

n1=hello,n2=32光标处(程序结束)    //32是空格的ASCII码。

再罗嗦一下,如果最后一句输出n2=%d改成n2=%c,则输入:

hello回车

得到:

n1=hello,n2=

光标处(程序结束)

是不是和getchar一样可以把'\n '读出来呢,呵呵。

总结一下就是:

如果scanf输入的不是字符,那么分隔符为回车,空格、tab键时,两个数据之间的分隔符只是起区别两个数据的作用,把分隔好的两个数据分别赋值到各自定义好的变量或数组中去,两个数据之间的分隔符被从缓冲区读出但是不起任何作用,当然最后一个'\n '会被留在缓冲区内,除非用getchar();或scanf("%c",&c);把它读出来。

回车是一定要有的,不管getchar还是scanf只要是通过缓冲区输入数据的函数都是等待回车键'\n '出现才进入缓冲区的。再来个整型数据、字符串、字符的混合例子:

#include "stdio.h"
int main(void) 
{
	int a,b,c;
	char n1[10];
	char n2,n3;
	scanf("%d%d",&a,&b);
	scanf("%c",&n2);
	scanf("%d",&c);
	scanf("%s",n1);
	scanf("%c",&n3);
	printf("a=%d,b=%d,n2=%c,c=%d,n1=%s,n3=%c",a,b,n2,c,n1,n3);
	return 0;
}

输入:

12(若干空格或回车都不影响结果,这里用了回车)

34(这里还要求输入,因为scanf只得到了一个整型数据,而缓冲区内没有整型数据了。要有回车或空格表示这个数据结束了,留下来的空格或回车被下个%c接受,这里用了回车,可以试一下空格)

45 jfdkjfa(回车)

得到:

a=12,b=34,n2=

,c=45,n1=jfdkjfa,n3=

光标处(程序结束)

       这里说明一下过程:在前两个整型数据输入时,两个数据之间无论是回车还是若干空格都被scanf当做分隔符,好了,scanf读到分隔符(回车或空格)时,把第一个整型数据送到变量a中,缓冲区中留下分隔符和下面的整型数据,这时scanf再读当然先读分隔符,但是要求输入的还是整型数据(%d),所以分隔符被忽略,如果这时要求输入字符%c(不是字符串%s),那么分隔符将以一个字节的形式送到字符变量里,就如同这里的n2。同理可以知道c和n1的保存过程,最后的n3正是接收了输入时的最后一个回车。

好了如果看到这里你都理解了那么看最后一个例子:

#include "stdio.h"
int main(void)
{
	int a;
	char ch;
	scanf("%d",&a);
	ch=getchar();
	printf("%d,%c",a,ch);
	return 0;
}

输入:

95回车

得到:

95,

光标处(程序结束)

很明显这是由于分隔符(回车)被getchar读取并输出了,如果加入一句:getchar();

#include "stdio.h"
int main(void)
{
	int a;
	char ch;
	scanf("%d",&a);
	getchar();
	ch=getchar();
	printf("%d,%c",a,ch);
	return 0;
}

输入:

95回车

c回车

得到:

95,c光标处(程序结束)





别再死记硬背了!用TwinCAT 3手把手教你配置EtherCAT伺服驱动的PDO映射(DS402协议) 本文详细介绍了如何使用TwinCAT 3配置EtherCAT伺服驱动的PDO映射(DS402协议),涵盖环境准备、设备扫描、PDO映射实战及高级技巧。通过具体操作步骤和常见问题排查,帮助工程师快速掌握EtherCAT通信配置,提升运动控制系统的效率和稳定性。 阅读详情

相关推荐

深入解析HAL_UART_Receive_IT:如何高效配置串口中断接收

本文深入解析了STM32 HAL库中`HAL_UART_Receive_IT`函数的工作原理与高效配置方法。该函数并非直接接收数据,而是作为中断接收的启动器和配置器,通过开启相关中断,由`UART_Receive_IT`在后台完成数据搬运。文章详细对比了中断与轮询模式的区别,并提供了不定长数据接收的完整实战流程、常见问题避坑指南及高级应用技巧,帮助开发者构建稳定高效的串口通信。

weixin_29162439的博客 639

C语言scanf缓冲区去掉多余回车键

因为scanf具有缓冲区,使用完之后缓冲区是没有被清理的,数字i被读取进去了,但是回车\n还在缓冲区中。我们经过打断点调试,发现c输出的是回车,这个回车是我们再scanf输入数字时,多读的那个回车。这段代码我们预期的结果是输入数字,然后等待输入一个字符。输入完数字后,直接结束了。我们使用fflush清理。

暴力扬 2681

硬件工程师入门进阶,一文搞懂,看这篇就对了

每家公司的datasheet都有严格的规范,及独特的风格,有时候还会穿插一些原理性的介绍,比如ADI公司的一些ADC/DAC器件资料里面,还会包含AD/DA转换的原理性讲解内容,Datasheet既可以是我们设计上的好帮手,也是学习的好资料。在出货量大的产品中,尽量减少物料种类,比如开头说的,1%的电阻不得不用,那么5%的替换成1%的,物料种类就减少一种,量就大了,能不能争取更优的价格呢?如果说前面学的是内功,那这一关,是招式、是工具的使用,原理图和PCB设计都有对应的工具,教程也很多,且比较容易上手。

一路带飞的博客 5万+

内存缓冲区的存在 && 如何读取缓冲区中的字符(换行符等其他字符)

内存缓冲区 & 如何读取内容缓冲区中的一个字符

weixin_64603510的博客 739

手把手教你用Arduino Uno控制meArm机械臂(附完整代码+避坑指南)

本文提供了一份详尽的meArm机械臂控制指南,涵盖从Arduino Uno硬件连接到Servo库编程的完整流程。重点讲解了如何通过独立供电、软件限位和平滑运动函数实现稳定控制,并设计了串口指令协议与高级功能,帮助创客有效规避舵机抖动、电源不足等常见问题,让机械臂运行更流畅可靠。

gpt4scribbler的博客 541

linux系统下安装nexus做私服仓库

1.下载地址 官网地址:https://www.sonatype.com/download-oss-sonatype选择相应的版本即可 2.示例环境 linux系统:CentOS 7 JDK: 1.8 Nexus:nexus-3.16.2-01-unix.tar.gz 3.环境安装 从官网上下载安装包拷贝到linux环境中并解压; 如上图,进入bin目录中,然后运行./nexu...

chang18829350947的博客 1581

c/c++中缓冲区,scanf,getchar的使用及关系

让我们深入探讨一下缓冲区的概念,scanf和getchar的使用,以及它们之间的关系。这些概念在C/C++编程中非常重要,特别是在处理用户输入时。

2302_76543887的博客 431

DRAM刷新refresh相关知识归类-基础小知识(三)

RAM每一位数据都是通过芯片内的一个小电容充电(或低电平)存储的。但随着时间的推移,电容逐渐失去电荷。为避免丢失存储的数据,必须定期刷新以将电荷(如果存在)恢复到其原始级别。此刷新过程包括读取每个位的值,然后将其写回。在此“刷新”期间,内存被占用,无法执行加载或存储位等正常操作。知道了应该这么做,但怎么去做以及有什么办法更有效率去做,就是接下来要整理的内容。

Paul 安的博客 1万+

学习笔记:scanf的缓冲区机制(超详解)以及getchar的吸收用法和注意事项

上一次的scanf的有效空白字符会留在缓冲区里,新的scanf输入会覆盖缓冲区,其新的有效输入后的有效空白字符会留在缓冲区里,故连续使用scanf时,只需在最后一个scanf后吸收即可。

2302_77109193的博客 2254

强网杯Web题ezphp解题全记录:利用PHP反序列化与条件竞争拿下服务器

本文详细解析了强网杯Web题目ezphp的解题过程,通过PHP反序列化与条件竞争漏洞的组合利用,成功获取服务器权限。文章深入剖析了反序列化链的构造、文件上传绕过技巧以及条件竞争的实际应用,为CTF选手和Web安全研究者提供了宝贵的实战经验。

weixin_29006187的博客 383

2023全国职业技能大赛 网络系统管理 服务部署 Linux部分--基础配置

服务器和客户端基本配置如下表,各虚拟机已预装系统。一、关闭防火墙和Selinux。七、需要使用到的命令详解。三、修改root密码。

weixin_62926639的博客 1001

scanf,getchar读取字符和缓冲区

文章目录程序代码缓冲区scanf和getchar()程序的修改 程序代码 首先我们来看这样一段代码 #include<stdio.h> int main() { char password[10] = { 0 }; printf("请输入密码:"); scanf("%s", password); printf("请确认密码(Y/N):"); int ch = getchar(); if (ch == 'Y') { printf("确认成功\n"); } else {

DR5200的博客 849

全功能爬虫框架:Botasaurus 的详细使用(现代化、反检测、高并发的智能爬虫框架)

Botasaurus是一个基于 Python 的全栈式智能数据采集框架。它深度融合了以下关键技术: 无头浏览器自动化(Headless Browser Automation):基于 Playwright 或 Puppeteer,支持 Chromium、Firefox、WebKit; 高级反检测引擎(Anti-Detection Engine):自动绕过 WebDriver、Canvas、AudioContext 等 50+ 种指纹检测; 声明式任务模型(Declarative Task Model):用装

数据知道的博客 4371

scanf和getchar读取缓冲区问题

关于scanf与getchar的使用以及缓冲区的一些问题

lazyxx的博客 812

pscad IEEE标准系统搭建说明

pscad IEEE标准系统搭建说明,包含典型的IEEE 9节点、14节点、30节点、39节点和118节点系统。内含标准测试系统的原始数据和潮流结果。

VC中sqlite的使用

在VC中对sqlite的使用,实现数据库大批数据的快速插入,读取数据库中的数据在ListCtrl中显示

C语言清除缓冲区:scanf()和getchar()

当我们输入一个int类型的数据,为什么可以输入123这样的多位数字;而对于字符类型char,却只能识别一个字符,比如‘1’;字符串的情况又有不同,其实就是用到了缓冲区。 缓冲区的优点很明显,它加快了程序的运行速度,减少了硬件的读写次数,让整个计算机变得流畅起来;但是数据的冗余和C/C++对于输入,输出的限制,使缓冲区的存在有了一些负面影响,比如printf()在输出操作时是先将要输出的东西放在缓冲...

BlackShadowT的博客 1888

霍尼韦尔SoftMaster使用说明

霍尼韦尔SoftMaster使用说明

getchar scanf以及缓冲区的概念

getchar scanf以及缓冲区的概念

fguihbfg的博客 224

RU DOS版、EFI版32bit/64bit BIOS常用工具

DOS版、EFI版的RU工具,可用来查看IO、MEM、PCI、SMBIOS等资源。亲测在EFI SHELL下可用。

通过scanf和getchar了解缓冲区

初级c++,scanf,getchar,缓冲区

m0_71202744的博客 351

getchar,scanf以及缓冲区的概念(转)

转自http://blogold.chinaunix.net/u1/39867/showart_319880.html 你肯定会奇怪为什么一开始先说这个,一开始不都是数据类型什么的嘛,这个写在最前面因为后面的程序即使最简单的code都会用到输入输出,输出比较简单,可以放在后面再说,但是输入就不同了,如果不先了解一下,可能会得到和你预想不同的结果哦^_^.也正是由于和一般的c语言介绍方式不同,为了

william0615的专栏 411

输入( Getchar/Scanf ) 输出( Putchar/Printf ) , 与缓冲区

getchar putchar 缓冲区相关知识

m0_64618651的博客 972

关于scanf_s(),getchar()的输入字符与内存缓冲区

2:为了避免出现空格的现象对getchar定义的ret输入的影响,我们想保证在对ret变量赋值时候的getchar的输入缓冲区是空白的,因此想到采用while循环,利用getchar不断读取输入缓冲区的值,直至将最后一个\n读取出来。如果想要实现我们的原意,不希望getchar将\n读取,修改方法思路是需要保证getchar在读取缓冲区的时候只要没有字符,缓冲区是空白的,这样就可以保证getchar需要从键盘重新输入。6:if分支进行判断,\n不是"Y",故会执行else的语句,直接打印出 NO。

2301_80401772的博客 631

getchar,scanf的缓冲区输入规则

/getchar读取一个字符,且需要定义为整形。//scanf读取数据时,在空格处停止。} //scanf,getchar读取数据时都通过中继区进行操作。printf("请确认密码:%s Y/N\n",possword);printf("请输入密码->");//此循环刷新中继区。

2301_81861851的博客 380

getchar,scanf以及缓冲区的概念

getchar()是stdio.h中的库函数,它的作用是从stdin流中读入一个字符,也就是说,如果stdin有数据的话不用输入它就可以直接读取了。 <br />getch()和getche()是conio.h中的库函数,它的作用是从键盘接收字符。getchar带有显示。 <br />     与前面两个函数的区别在于: getchar()函数等待输入直到按回车才结束(前提是缓冲区没有数据),回车前的所有输入字符都会逐个显示在屏幕上。但只有第一个字符作为函数的返回值。 <br />#include <br

wolfzone025的专栏 859

关于scanf、getchar、getch、getche缓冲区分析——C语言

缓冲区 根据数据刷新的时机可以将缓冲区的类型分为:全缓冲、行缓冲、无缓冲 (注意:Windows下的输出设备没有缓冲区,意思是printf是无缓冲的,但是在Linux下printf就是行缓冲的,至于为什么Windows下printf是无缓冲的,后文会提到) 全缓冲:当缓冲区被填满以后才进行真正的输入输出操作 行缓冲:当在输入或者输出的过程中遇到换行符时,才执行真正的输入输出操作 无...

weixin_30493321的博客 415
上一篇: 程序员面试100题之十二:求数组中最长递增子序列
下一篇: 不用比较运算符及循环控制语句,判断int型的a、b两数的大小
hackbuteer1
博客等级 码龄15年 1万+粉丝 251原创
评论 6
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值