设为首页 加入收藏

TOP

C++缓冲区scanf,getline,cin问题
2023-07-23 13:38:39 】 浏览:50
Tags: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;
}

image

个人理解

回车换行符:回车键
当我们输入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 缓冲区 清除回车符

】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
上一篇QT MySQL 连接出错报 QSqlDatabas.. 下一篇c语言以及高级语言中的float到底..

最新文章

热门文章

Hot 文章

Python

C 语言

C++基础

大数据基础

linux编程基础

C/C++面试题目