getchar函数输入与缓冲区

简介: getchar函数输入与缓冲区

前言

介绍了解getchar函数及其在缓冲区中的应用

一、

(1)缓冲区是什么?

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

586fe184660d43879ef45a053477060f.png4657127ca0be40879b46eac0247f020a.png

(2)为什么要有缓冲区?

首先,把若干字符作为一个块进行传输比逐个发送这些字符节约时间。其次,如果用户打错字符,可以直接通过键盘修正错误。当最后按下Enter键时,传输的是正确的输入。

二、

1.getchar函数与缓冲区

当getchar获取一个字符的时候,其实它不是从我们的键盘上直接输入获取的,而是在计算机内存空间中存在的缓冲区中。

看下面这段代码:

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

b8e5bace4f964a9ea5992f49128d1924.png 我们输入ABCDEF回车之后,直接输出了“确认失败”,而并没有让我们输入(Y/N)来确认密码,难道就是并没有执行int ch = getchar();吗?

6001fbe80b964533bc08783d3bbbbb29.jpg

我们输入密码之后,在缓冲区中不只是ABCDEF,还有‘\n’。缓冲区中的字符是A B C D E F \n 。


这时我们要知道scanf不吃\n(换行符),所以当ABCDEF被scanf取走之后继续执行下一行,到int ch = getchar();时,getchar函数发现缓冲区没有清空,还有一位“\n”,它就直接取走了,继续向下执行,因为‘\n’并不=='Y',所以执行else语句,输出“确认失败”。


注意:scanf在遇到空白符(如换行、空格等)会结束读取

那么我们知道为什么出现问题了之后,我们该如何处理呢?

我们只需要把缓冲区中的‘\n'清理掉就可以了,做法如下:


2.getchar清理缓存区

代码如下(示例):

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

b8e5bace4f964a9ea5992f49128d1924.png

这里在scanf后加了一个getchar(),当scanf读取结束后,getchar就会把缓冲区中残留的\n清理掉;但是这个方法只可以临时解决问题,存在很大弊端,看下面输入后的运行结果

338a82be3306493089769b2315536fd2.png

当输入的密码中包含了空格,因为scanf遇到空格会结束读取;这时scanf后的getchar只能清理一个字符,当把空格清理掉后,123后的’\n‘无法被清理而导致无法正常的密码确认。那我们该怎么办呢?

我们可以实现多次清理就可以完全解决这个弊端了,下面是优化后的清理缓存区的代码:

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

50fd83755f4043fca8c77844acf1755a.png

将scanf后的getchar()换成

while(getchar()!='\n')

{

;

}

总结

缓冲输入用起来比较方便,因为在把输入发送给程序之前,用户可以编辑输入。但是,在使用输入的字符时,它也会给程序员带来麻烦。前面示例中看到的问题是,缓冲输入要求用户按下Enter键发送输入。这一动作同时也传送了换行符’\n‘,程序员必须妥善的处理掉这个麻烦的换行符。

另外也要记住 scanf在遇到空白符(如换行、空格等)会结束读取

目录
相关文章
|
JSON 自然语言处理 物联网
基于PaddleNLP的ChatGLM-6B模型lora微调实现Data-To-Text 硬约束下的受控文本生成
基于PaddleNLP的ChatGLM-6B模型lora微调实现Data-To-Text 硬约束下的受控文本生成
589 0
|
NoSQL 网络协议 数据库
为什么 Lettuce 会带来更长的故障时间
本文详述了阿里云数据库 Tair/Redis 将使用长连接客户端在非预期故障宕机切换场景下的恢复时间从最初的 900s 降到 120s 再到 30s的优化过程,涉及产品优化,开源产品问题修复等诸多方面。
68825 11
为什么 Lettuce 会带来更长的故障时间
|
11月前
|
数据采集 前端开发 物联网
【项目实战】通过LLaMaFactory+Qwen2-VL-2B微调一个多模态医疗大模型
本文介绍了一个基于多模态大模型的医疗图像诊断项目。项目旨在通过训练一个医疗领域的多模态大模型,提高医生处理医学图像的效率,辅助诊断和治疗。作者以家中老人的脑部CT为例,展示了如何利用MedTrinity-25M数据集训练模型,经过数据准备、环境搭建、模型训练及微调、最终验证等步骤,成功使模型能够识别CT图像并给出具体的诊断意见,与专业医生的诊断结果高度吻合。
21173 162
【项目实战】通过LLaMaFactory+Qwen2-VL-2B微调一个多模态医疗大模型
|
关系型数据库 MySQL 测试技术
如何进行数据库的升级?
【7月更文挑战第21天】如何进行数据库的升级?
910 1
|
文字识别
【提取翻译竖排文字日文图片的软件】竖排的日语图片文字识别翻译,竖排的日语图片文字如何识别,竖排日语图片识别后转横排,竖排的日语识别比较友好的方法
这款软件专攻竖排日语图片文字识别,支持自动横排转换,能准确提取左右排版文字,并翻译成中文。用户可从百度网盘或腾讯云盘下载。功能包括图片打开、拖拽识别、截屏拾取、顺序识别、文字导出、快捷搜索及窗体操作。识别时注意保持文字等高以减少误差。附带视频教程(BV1vW4y1p7st)帮助快速上手。
2614 1
|
Python
都2024年了,还不知道如何选本地Python开发环境管理工具
文章介绍了几种Python开发环境管理工具,包括Virtualenv、Pipenv和Anaconda,并推荐了Pipenv和Anaconda,解释了它们的安装和使用方法,帮助读者选择适合自己的工具来管理Python开发环境。
1138 0
|
安全 关系型数据库 Linux
|
机器学习/深度学习 数据采集 人工智能
Python 高级实战:基于自然语言处理的情感分析系统
**摘要:** 本文介绍了基于Python的情感分析系统,涵盖了从数据准备到模型构建的全过程。首先,讲解了如何安装Python及必需的NLP库,如nltk、sklearn、pandas和matplotlib。接着,通过抓取IMDb电影评论数据并进行预处理,构建情感分析模型。文中使用了VADER库进行基本的情感分类,并展示了如何使用`LogisticRegression`构建机器学习模型以提高分析精度。最后,提到了如何将模型部署为实时Web服务。本文旨在帮助读者提升在NLP和情感分析领域的实践技能。
1087 0
|
SQL XML Go
MSSQL之八 实现视图与索引
MSSQL之八 实现视图与索引
147 0
|
编解码 文件存储 计算机视觉
YOLOv5改进 | 2023Neck篇 | BiFPN双向特征金字塔网络(附yaml文件+代码)
YOLOv5改进 | 2023Neck篇 | BiFPN双向特征金字塔网络(附yaml文件+代码)
1269 0