C++ 标准输入流 std::cin 完整详解

一、基础概念

  1. 头文件
#include <iostream>
  1. 命名空间
    标准输入流对象 cin 属于 std 命名空间,两种使用方式:
// 方式1:每次加std::
std::cin >> num;

// 方式2:全局引入命名空间(工程/练习常用)
using namespace std;
cin >> num;
  1. 本质
    std::cinistream 类的全局实例,绑定键盘缓冲区;所有输入先存入内存缓冲区,程序再从缓冲区读取数据。
    配套输出流:std::cout

二、提取运算符 >>(基础读取)

1. 特性

  • 自动跳过空白字符:空格 、换行 \n、制表符 \t
  • 按数据类型自动解析,遇到空白停止读取;
  • 支持链式连续读取。

2. 示例代码

#include <iostream>
#include <string>
using namespace std;

int main() {
    int a;
    double b;
    char ch;
    string str;

    // 链式读取
    cin >> a >> b >> ch >> str;
    cout << a << " " << b << " " << ch << " " << str;
    return 0;
}

输入示例:10 3.14 A hello,全部正常读取。

3. 缺陷

读取字符串时无法接收带空格内容,输入 hello world 只会读到 hello,剩余 world 留在缓冲区。

三、整行读取 getline()(读取含空格字符串)

1. 函数原型

istream& getline(istream& is, string& str);

作用:读取一整行,直到换行符 \n 为止,换行符会被丢弃,不存入字符串。

2. 基础示例

string s;
getline(cin, s);
cout << s;

输入 I love C++ 可完整输出。

3. 经典坑:cin >> 与 getline 混用

cin >> 读取数字/字符后,回车 \n 残留在缓冲区,后续 getline 会直接读到空字符串。
解决方案:cin.ignore() 清空换行。

int num;
cin >> num;
cin.ignore(); // 吃掉缓冲区残留的换行
string s;
getline(cin, s);

四、cin 常用成员函数(缓冲区操作)

1. cin.get()

两种重载:

  1. int cin.get():读取缓冲区任意单个字符(空格、回车全部读取)
char c = cin.get();
  1. istream& cin.get(char& ch)
char c;
cin.get(c);

2. cin.ignore(个数, 终止字符)

丢弃缓冲区指定数量字符,遇到终止字符停止,常用于清换行:

cin.ignore(1000, '\n'); // 最多丢弃1000个字符,直到遇见回车

3. cin.peek()

偷看缓冲区下一个字符,不取走,返回ASCII码:

if (cin.peek() == '\n')
    cout << "下一个是换行";

4. cin.putback(ch)

把字符放回输入缓冲区,用于回退读取。

五、cin 状态标记(输入错误处理核心)

cin 内部维护4种状态位,读取失败(如输入字母给int变量)会触发错误标记,流直接锁死,无法继续读取。

状态函数 作用
cin.good() 流正常,无错误
cin.fail() 格式错误(类型不匹配,如数字读入字母)
cin.bad() 严重IO硬件错误,流损坏
cin.eof() 读到文件/输入末尾

完整容错模板

#include <iostream>
using namespace std;

int main() {
    int x;
    while (true) {
        cout << "请输入整数:";
        cin >> x;
        if (cin.fail()) {
            cout << "输入非法,请重新输入\n";
            cin.clear(); // 1. 清除错误标记,解锁输入流
            cin.ignore(999, '\n'); // 2. 清空错误的残留字符
        } else {
            cout << "输入正确:" << x;
            break;
        }
    }
    return 0;
}

六、缓冲区原理

  1. 键盘输入内容不会直接给程序,先存入输入缓冲区
  2. cin >> / getline 从缓冲区取数据,缓冲区空时程序阻塞等待键盘输入;
  3. 换行、空格是读取分隔标记;
  4. 读取失败时缓冲区脏数据残留,必须 ignore 清理,否则循环持续报错。

七、字符数组老式读取(C风格字符串)

cin.getline(char数组, 长度)

char buf[100];
cin.getline(buf, 100); // 最多读取99个字符,自动补'\0'

区别:

  • std::getline(cin, string):C++ string专用;
  • cin.getline(字符数组, 长度):兼容C char[]。

八、标准输入重定向(进阶)

可以不从键盘读,直接读取文件:

#include <fstream>
ifstream fin("data.txt");
cin.rdbuf(fin.rdbuf()); // 将cin绑定文件,cin自动读文件内容

九、核心对比总结

  1. cin >>
    • 优点:简单自动解析数字、字符串;
    • 缺点:空格截断,不能读整行;
  2. getline(cin, str)
    • 优点:读取整行含空格;
    • 缺点:需处理 cin >> 遗留换行;
  3. cin.get()
    • 优点:读取空格、回车;
    • 缺点:只能单字符读取。

更多推荐