C++缓冲区scanf,getline,cin问题
名词引入
名词介绍
缓冲区
缓冲区是内存空间的一部分,也就是说在内存空间中预留了一定大小的存储空间,这些存储空间用来缓冲输入或输出的数据,这部分预留的空间就叫做缓冲区,根据其对应的是输入设备还是输出设备,分为输入缓冲区和输出缓冲区。
输入原理介绍
当调用输入函数 scanf() 时,输入函数会将我们输入的数字输入到输入缓冲区,而当我们的输入缓冲区有内容时,再次输入将不会被执行,而是直接跳过执行,将输入缓冲区的内容赋给变量。
cin 读取数据也是从输入缓冲区中获取数据,输入缓冲区为空时,cin的成员函数会阻塞等待数据的到来,一旦输入缓冲区中有数据,就触发cin的成员函数去读取数据。正因为cin对象是直接从缓冲区取数据的,所以有时候当缓冲区中有残留数据时,cin对象会直接取得这些残留数据而不会请求键盘输入
列子引入
int a;
while (cin >> a) {
cout << a <<endl;
}
当我们输入1 2 3 4 5
,控制台输出是:
**过程分析:我们可以理解为我们用键盘输入的 "1 2 3 4 5"输入完按下ENTER键之后,这些字节发送到了输入缓冲区。cin从阻塞状态中醒来,读取输入缓冲区中的数据,把第一个数据“1”放入变量a中,然后读取到空格结束本次读取,返回一个非0返回值,然后进入循环打印出变量a的内容。此时缓冲区中仍然存在"2 3 4 5\n",然后继续如此循环,直至结束。 **
cin返回值问题具体参考:https://www.cnblogs.com/CooCoChoco/p/11932985.html
/*
* @Author: DEFT:errornotfound@qq.com V:NOTFOUND6O6
* @Date: 2023-02-22 19:02:35
* @LastEditors: Please set LastEditors
* @LastEditTime: 2023-02-28 12:30:36
* @FilePath: \WenkaiC\test.cpp
* @Description:
*
* Copyright (c) 2023 by 1zPeasy, All Rights Reserved.
*/
#include <iostream>
using namespace std;
struct Books{
string name;
double price;
};
int main() {
int n;cin >> n;
cout << "输入的数量为:" << n << endl;
struct Books b[n];
for(int i=0; i < n; i++){
//char ch;scanf("%c", &ch);
//cin.ignore(1024, '\n');
getline(cin,b[i].name);
cin >> b[i].price;
}
cout << "-----以下为输出:-------" << endl;
for(int j=0; j<n; j++){
cout << b[j].name << endl;
cout << b[j].price << endl;
}
return 0;
}
个人理解
回车换行符:回车键
当我们输入2Enter的时候,实际上是先发送到内存中的输入缓冲区中了,此时输入缓冲区中2\n
。然后第一个cin读取到2,然后再读到一个非数字(\n)后结束,赋值给n,但是此时的\n
还在输入缓冲区中。但是此时在没清空的情况下,又进行getline()函数等待输入,getline函数首先读取到输入缓冲区中\n直接结束,string类型的name没赋值,默认值为空,与此同时\n也被从输入缓冲区中抛弃。此时进行到cin >> b[i].price
,我们在键盘中又开始输入"math"回车,发送到输入缓冲区中。此时输入缓冲区中math\n
,这个时候cin读取到缓冲区中m,字符串"m"类型不匹配double,没给double类型的price正确赋值,所有b[0].price就是默认值0。可是为什么第二循环走都没走呢?但是按理来说此时输入缓冲区中仍然存在math\n,会被赋值给第二次循环的b[1].name。
解决方法
原理:当输入缓冲区中有内容时,不会等待输入,而把原本输入缓冲区中残留的首个\n赋值给了ch。
char ch;scanf("%c", &ch);
或者
原理:cin.ignore(a,ch)方法是从输入流(cin)中提取字符,提取的字符被忽略(ignore),不被使用。它的一个常用功能就是用来清除以回车结束的输入缓冲区的内容,消除上一次输入对下一次输入的影响。
cin.ignore(1024, '\n');
或者
原理:每次从缓冲区中读取一个字符,包括空格、制表符、换行符等空白符;
getchar();
参考文章
C++cin详解及清空输入缓冲区
iostream 缓冲区详解(cin和cout)
c++中getline()读取缓冲区中回车,以及cin结束符的问题:#运行过程分析:行
C++cin详解及清空输入缓冲区
C++ getline函数用法详解
【C/C++】scanf()函数用法详解(缓冲区、格式控制、fflush)
cin.ignore()函数的用法
C++中关于 getline() 读取缓冲区中回车,以及cin 结束符的问题
【令人烦恼困惑的scanf (共5集)】 【精准空降到 15:09】
\r \n 回车换行符详解
getchar scanf 缓冲区 清除回车符
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 使用C#创建一个MCP客户端
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 按钮权限的设计及实现