【C语言】getchar 函数的正确使用

【C语言】getchar 函数的正确使用目录一、getchar函数二、缓冲区1、什么是缓冲区2、为什么要存在缓冲区3、缓冲区的类型4、缓冲区的刷新三、getchar函数的正确使用1、getchar的换行问题2、getchar与scanf的混合使用一、getchar函数从上面的介绍来看,我们要正确使用getchar函数,首先得了解什么是缓冲区。二、缓冲区1、什么是缓冲区缓冲区又称为缓存,它是内存空间的一部分。也就是说,在内存空间中预留了一定的存储空间,这些存储空间用来缓冲输入或输出的数据,这部分预留的空间就叫做缓冲区。

大家好,又见面了,我是你们的朋友全栈君。如果您正在找激活码,请点击查看最新教程,关注关注公众号 “全栈程序员社区” 获取激活教程,可能之前旧版本教程已经失效.最新Idea2022.1教程亲测有效,一键激活。

Jetbrains全系列IDE稳定放心使用


一、getchar 函数

在这里插入图片描述从上面的介绍来看,我们要正确使用getchar函数,首先得了解什么是缓冲区。


二、缓冲区

1、什么是缓冲区

缓冲区又称为缓存,它是内存空间的一部分。

也就是说,在内存空间中预留了一定的存储空间,这些存储空间用来缓冲输入或输出的数据,这部分预留的空间就叫做缓冲区。

缓冲区根据其对应的是输入设备输出设备,分为输入缓冲区和输出缓冲区。


2、为什么要存在缓冲区

我们为什么要引入缓冲区呢?

比如我们从磁盘里取信息,我们先把读出的数据放在缓冲区,计算机再直接从缓冲区中取数据,等缓冲区的数据取完后再去磁盘中读取,这样就可以减少磁盘的读写次数,再加上计算机对缓冲区的操作大大快于对磁盘的操作,故应用缓冲区可大大提高计算机的运行速度。

又比如,我们使用打印机打印文档,由于打印机的打印速度相对较慢,我们先把文档输出到打印机相应的缓冲区,打印机再自行逐步打印,这时我们的CPU可以处理别的事情。现在您基本明白了吧,缓冲区就是一块内存区,它用在输入输出设备和CPU之间,用来缓存数据。它使得低速的输入输出设备和高速的CPU能够协调工作,避免低速的输入输出设备占用CPU,解放出CPU,使其能够高效率工作。


3、缓冲区的类型

缓冲区分为三种类型:全缓冲、行缓冲和不带缓冲。

1、全缓冲
在这种情况下,当填满标准I/O缓存后才进行实际I/O操作。全缓冲的典型代表是对磁盘文件的读写。

2、行缓冲
在这种情况下,当在输入和输出中遇到换行符时,执行真正的I/O操作。这时,我们输入的字符先存放在缓冲区,等按下回车键换行时才进行实际的I/O操作。典型代表是键盘输入数据

3、不带缓冲
也就是不进行缓冲,标准出错情况stderr是典型代表,这使得出错信息可以直接尽快地显示出来。


4、缓冲区的刷新

以下四种情况会引发缓冲区刷新:

  1. 缓冲区满时;
  2. 执行 flush 语句;
  3. 执行 endl 语句;
  4. 关闭文件。

三、getchar 函数的正确使用

1、getchar 的换行问题

我们来观察下面这段代码

#include<stdio.h>
int main()
{ 
   
	int ch = 0;
	while ((ch = (getchar())) != EOF)
	{ 
   
		putchar(ch);
	}
	return 0;
}

在这里插入图片描述我们可以看到我们每次从键盘输入一个字符并回车后,putchar输出时会自动换行,就是因为我们每次除了输入字符外,还敲了一个回车,而这个回车会被存储在缓冲区中,当我们用getchar读取字符时,会从缓冲区中依次逐个读取所有的字符(包括换行、空格、Tab),直到缓冲区中没有数据,每读取一个字符就用putchar打印一下,所以这里会自动换行。
在这里插入图片描述^Z:Ctrl+Z,输入后会被认定为EOF,从而来结束循环(VS中有些时候要重复按三次才会结束循环,其他编译器都是按一次)。


2、getchar 与 scanf 的混合使用

我们来观察下面这段代码:

#include<stdio.h>
int main()
{ 
   
	char password[20] = { 
    0 };
	printf("请输入密码:>");
	scanf("%s", password);
	printf("请确认密码(Y/N):>");
	int ch = getchar();
	if (ch == 'Y')
	{ 
   
		printf("确认成功\n");
	}
	else
	{ 
   
		printf("确认失败\n");
	}
	return 0;
}

在这里插入图片描述我们可以看到程序并没有等待我们输入Y/N来确认密码,而是直接结束,原因就是我们缓冲区中存放的是abcdef\n,而scanf函数是遇到空格、换行符(\n)、Tab时结束,所以\n并没有被读取走,而是继续留在了缓冲区中,而当getchar读取数据时发现缓冲区中并不为空,所以直接读取了\n,然后判断if条件,结束程序,而不会等待我们输入Y/N。


那么要如何避免这种情况发生呢?有两种方法:
法一:在scanf后面加一个getchar(不推荐)

#include<stdio.h>
int main()
{ 
   
	char password[20] = { 
    0 };
	printf("请输入密码:>");
	scanf("%s", password);
	getchar();  //读取剩下的\n
	printf("请确认密码(Y/N):>");
	int ch = getchar();
	if (ch == 'Y')
	{ 
   
		printf("确认成功\n");
	}
	else
	{ 
   
		printf("确认失败\n");
	}
	return 0;
}

在这里插入图片描述我们在scanf函数后面加上一个getchar函数,用于清空缓冲区里面多余的\n,但是这种方法有弊端,不推荐使用,具体弊端如下:在这里插入图片描述
如图:我们从键盘输入abcd ef,我们可以看到,程序并没有等待我们输入Y/N,而是直接执行if语句,这是因为 scanf函数遇到空格、换行符(\n)、Tab时会停止读取,所以缓冲区中剩下的字符是_ef\n,一次getchar无法清空缓冲区。所以说,法一只能解决一部分情况,想要彻底解决scanf缓冲区残留的问题需要用到法二。


法二:在scanf后面加 while( getchar() != ‘\n’) 语句(推荐)

#include<stdio.h>
int main()
{ 
   
	char password[20] = { 
    0 };
	printf("请输入密码:>");
	scanf("%s", password);
	getchar();  //读取剩下的\n
	printf("请确认密码(Y/N):>");
	while (getchar() != '\n')
	{ 
   
		;
	}
	int ch = getchar();
	if (ch == 'Y')
	{ 
   
		printf("确认成功\n");
	}
	else
	{ 
   
		printf("确认失败\n");
	}
	return 0;
}

在这里插入图片描述在这里插入图片描述程序中的while( getchar() != ‘\n’)语句会不断读取缓冲区中的字符,直到把\n读取走,从而达到清空缓冲区的目的。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/180276.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • bios设置pcie通道_PCI LAN

    bios设置pcie通道_PCI LANPCIewithlspciPCIeWidth#lspci-s81:00.0-vvv|grepWidthLnkCap:Port#0,Speed8GT/s,Widthx16,ASPMnotsupported,ExitLatencyL0sunlimited,L1unlimited…

    2025年10月14日
    4
  • Python翻译Excel文件

    Python翻译Excel文件朋友需要翻译大量 Excel 文件内容 看我是否能搭把手 我的思路很简单 就是将 Excel 文件内容读出后 调用翻译软件的 API 然后再爬回翻译好的内容 写入 Excel 读取 Excel 文件内容的方法 我这里要处理的是 xlsx 文件 可以 importopenpy 如果要处理 xls 文件 就不能用这个 而是 importxlrd 或者先将 xks 文件转为 xlsx 文件再使用本文代码 具体这两个包提

    2025年10月4日
    2
  • matlab保存图片清晰度_图片分辨率300dpi怎么设置

    matlab保存图片清晰度_图片分辨率300dpi怎么设置用print函数:如:t=1:100plot(t,sin(t));print(gcf,’-dpng’,’sin.png’);用saveas()如:t=1:100;plot(t,sin(t));saveas(gcf,’my_picture.bmp’,’bmp’);print(‘-depsc’,’-tiff’,’-r300′,’picture1.eps’)%满足dpi的要求savesthecurr…

    2025年11月8日
    2
  • android 8原生系统下载地址,android8.0下载地址 android8.0系统下载网址[通俗易懂]

    android 8原生系统下载地址,android8.0下载地址 android8.0系统下载网址[通俗易懂]android8.0系统下载网址:大家期待的android8.0,命名为androido终于正式公布了,对于大家最关心的android8.0发布时间和新特性方面,谷歌表示今年夏季末,用户就可以升级了。本次开发者大会上,谷歌并没有公布android8.0的新功能,围绕新系统只有两点FluidExperience(流畅体验)和Vitals(核心功能)。简单来说就是,FluidExperience的内容…

    2022年6月19日
    56
  • C++的后端框架从头开发[通俗易懂]

    C++的后端框架从头开发[通俗易懂]基于C++的后端框架Ratel简介:从开发到现在已经半个月了,我会进行长期地开发、维护和优化,直到它变得完善。各种建议和错误读者都可以和我联系,从公众号中就可以找到我的联系方式~Ratel后端框架目前采用C++作为开发语言,理想的效果是实现一个通用的、灵活的、高效的后端开发框架,可以自由选择不同的I/O复用机制,可以自由选择采用多线程、多进程或协程方式实现,并且可以跨平台Linux和Window平台编译和运行。目前已有功能:Linux和Windows跨平台运行

    2022年6月9日
    137
  • python查找字符串最长公共前缀_python leetcode

    python查找字符串最长公共前缀_python leetcodepython(leetcode)-14最长公共前缀

    2022年4月21日
    69

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号