默认参数只能从右到左一个一个指定 对于派生类,可以用一个基类的引用来引用这个实现多态 函数重载,要看能不能区别函数,但是const,volatile,&这3个不影响区别 函数模板,template只作用于下一个函数,使用时确定会用实例化和具体化 在用函数模板和函数重载时,几乎一定会出现一个函数调用能用几个定义好的函数, 这个要看最佳匹配,优先常规函数,再是提升转换,规则转换,最后用户定义的转换 在模板的使用中,有decltype这个关键字,用于自动推断类型 decltypr(A) x; // x是A的类型 decltypr(func()) x; // x是返回值的类类型 decltypr((A)) x; // x是A的引用类型 decltypr(10+1.0) x; // x是表达试的类型 还需要后置返回值 template<class T1,class T2> auto func(T1 x,T2 y) -> decltype(x+y){ }

名称 链接到标题

cin >> , cin.get() , cin.getline() , getline() — C++ 标准输入函数

概述 链接到标题

函数 返回值 读到的内容 是否读走 \n 是否储存 \n
cin >> var istream& 跳过前导空白,读到空白前 否 —
cin.get() int 一个字符(含 \n) — —
cin.get(ch) istream& 一个字符(含 \n) — —
cin.get(buf, len) istream& 一行,最多 len-1 个字符 否 否
cin.get(buf, len, delim) istream& 读到 delim 前,最多 len-1 个字符 否 否
cin.getline(buf, len) istream& 一行,最多 len-1 个字符 是 否
cin.getline(buf, len, delim) istream& 读到 delim 前,最多 len-1 个字符 是 否
getline(cin, str) istream& 一行 是 否
getline(cin, str, delim) istream& 读到 delim 前 是 否

istream 如何转换为 bool 链接到标题

istream 可在 if / while 中直接作为条件判断,通过 explicit operator bool()(C++11 起)。

工作原理 链接到标题

operator bool 内部返回 !fail() —— 即流没有 failbit 或 badbit 时为 true,出错或到 EOF 后下一次读取失败时为 false。

if (cin)             // cin.fail() 为 false 时进入
if (cin >> n)        // 读取成功时进入,失败则不进
while (cin.get(ch))  // 读到 EOF 自动退出
while (getline(cin, s)) // 读到 EOF 自动退出

关键:不检查 eofbit 链接到标题

仅 eofbit 置位而 failbit/badbit 未置位时,流仍为 true。只有下一次读取失败导致 failbit 也置位后,才转为 false。

历史 链接到标题

C++98/03 使用 operator void*(返回空指针表示失败),存在漏洞(如 cin == true 可通过编译)。C++11 起改为 explicit operator bool,禁止了这类荒唐用法,但 if(cin) 仍正常工作。


1. cin >> — 格式化提取运算符 链接到标题

头文件 链接到标题

#include <iostream>

语法 链接到标题

cin >> var;

说明 链接到标题

从输入流中提取数据存入变量 var。读取前跳过所有前导空白字符(空格、制表符、换行符),读取到下一个空白字符前停止,且不会读走停止时的那个空白字符(留在缓冲区中)。

支持的类型:int、double、char、string 等重载了 operator>> 的类型。

返回值 链接到标题

返回 istream&(即 cin 自身的引用),可链式调用:cin >> a >> b >> c;。

流状态反映了操作成败:

  • cin.good() — 读取成功
  • cin.fail() — 类型不匹配(如输入字母给 int)
  • cin.eof() — 读到文件末尾

示例 链接到标题

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

int main()
{
    int n;
    string s;

    cout << "输入一个整数和字符串: ";
    cin >> n >> s;          // 输入: 42 hello

    cout << "n = " << n << endl;  // n = 42
    cout << "s = " << s << endl;  // s = hello
    return 0;
}

陷阱:残留的换行符 链接到标题

int n;
string line;
cin >> n;                  // 输入 "42\n",读走 42,\n 留在缓冲区
getline(cin, line);        // 立刻读到 \n,line 为空串!

解决方法:在 cin >> n 后用 cin.ignore() 吃掉残留的 \n。


2. cin.get() — 无参版本 链接到标题

语法 链接到标题

int cin.get();

说明 链接到标题

从输入流中读取一个字符(包括空白、换行符),并以 int 类型返回其 ASCII 码。读到文件末尾返回 EOF(通常为 -1)。

返回值 链接到标题

返回 int 类型:成功时返回所读字符的 ASCII 码(0–255);读到文件末尾或出错时返回 EOF(通常为 -1,定义在 <cstdio>)。

示例 链接到标题

#include <iostream>
using namespace std;

int main()
{
    cout << "输入: ";
    int ch = cin.get();    // 输入 A
    cout << "读取字符: " << (char)ch
         << " (ASCII " << ch << ")" << endl;
    return 0;
}

3. cin.get(ch) — 单参数版本 链接到标题

语法 链接到标题

istream& cin.get(char& ch);

说明 链接到标题

从输入流中读取一个字符(包括 \n)存入 ch,返回 istream&,支持链式调用。读到文件末尾返回 EOF,流状态变为 fail。

返回值 链接到标题

返回 istream&(即 cin 自身的引用)。可通过条件判断检验成败:

while (cin.get(ch))   // 读取成功时为 true
    process(ch);

读到文件末尾时 cin.fail() 返回 true,可用于条件退出的布尔转换。

示例 链接到标题

#include <iostream>
using namespace std;

int main()
{
    char ch;
    cout << "逐个读取字符,按 # 结束:\n";
    while (cin.get(ch) && ch != '#')
        cout << "读到: " << ch << endl;
    return 0;
}

4. cin.get(buf, len) 和 cin.get(buf, len, delim) — 双参/三参版本 链接到标题

语法 链接到标题

istream& cin.get(char* buf, streamsize len);
istream& cin.get(char* buf, streamsize len, char delim);

说明 链接到标题

从输入流中读取字符存入 C 风格字符串 buf:

  • 最多读取 len-1 个字符(剩余一个位置自动补 \0)
  • 遇到分隔符 delim(默认 \n)时停止
  • 不会读走分隔符 — 分隔符留在缓冲区中
  • 如果下一个字符就是分隔符则立即停止,buf 为空串

返回值 链接到标题

返回 istream&。若未读到任何字符就遇到分隔符或 EOF,则设置 failbit,可通过 cin.fail() 检测。

示例 链接到标题

#include <iostream>
using namespace std;

int main()
{
    char buf[100];
    cout << "输入一行: ";
    cin.get(buf, 100);        // 输入: hello world\n
    cout << "buf = " << buf << endl;  // buf = hello world

    // \n 还在缓冲区里!
    cout << "缓冲区下一个字符的 ASCII: " << cin.peek() << endl; // 10 (即 \n)
    return 0;
}

连续读取必须吃掉分隔符:

char a[100], b[100];
cin.get(a, 100);             // 读第一行,\n 留在缓冲区
cin.get();                   // 吃掉残留的 \n
cin.get(b, 100);             // 读第二行

5. cin.getline(buf, len) 和 cin.getline(buf, len, delim) 链接到标题

语法 链接到标题

istream& cin.getline(char* buf, streamsize len);
istream& cin.getline(char* buf, streamsize len, char delim);

说明 链接到标题

与 cin.get(buf, len, delim) 类似,但关键区别是:会读走并丢弃分隔符。

  • 最多读取 len-1 个字符,自动补 \0
  • 遇到分隔符(默认 \n)停止并将其从缓冲区中读走(丢弃)
  • 如果一行长度超过 len-1,流状态会变为 fail

返回值 链接到标题

返回 istream&。若未读到任何字符就遇到分隔符或 EOF,设置 failbit;若一行长度超过 len-1,也设置 failbit。

示例 链接到标题

#include <iostream>
using namespace std;

int main()
{
    char a[100], b[100];
    cout << "输入两行:\n";
    cin.getline(a, 100);     // \n 被读走丢弃
    cin.getline(b, 100);     // 直接读下一行,无需 cin.get()
    cout << "a = " << a << endl;
    cout << "b = " << b << endl;
    return 0;
}

6. getline(cin, str) 和 getline(cin, str, delim) 链接到标题

头文件 链接到标题

#include <string>

语法 链接到标题

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

说明 链接到标题

从输入流中读取一行存入 std::string:

  • 遇到分隔符(默认 \n)停止
  • 读走并丢弃分隔符
  • 不会将分隔符存入 str
  • 自动管理内存,无需预设长度

返回值 链接到标题

返回 istream&(第一个参数的引用)。读到文件末尾设置 eofbit,无字符可读时设置 failbit。

示例 链接到标题

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

int main()
{
    string name;
    cout << "你的名字?";
    getline(cin, name);             // 输入: Zhang San\n
    cout << "你好, " << name << "!" << endl; // 你好, Zhang San!
    return 0;
}

自定义分隔符:

string item;
getline(cin, item, ',');  // 用逗号分隔,读取 "张三,李四,王五" 时依次得到 "张三" "李四" "王五"

核心对比:cin.get(buf,len) vs cin.getline(buf,len) 链接到标题

char a[100], b[100];

// --- get() 版本:\n 留在缓冲区 ---
cin.get(a, 100);  // 输入: abc\n  → a="abc",  \n 仍在缓冲区
cin.get();        // 必须手动吃掉 \n
cin.get(b, 100);  // 才能读下一行

// --- getline() 版本:\n 被自动丢弃 ---
cin.getline(a, 100);  // 输入: abc\n  → a="abc",  \n 被读走丢弃
cin.getline(b, 100);  // 直接读下一行

相关函数 链接到标题

函数 作用
cin.peek() 查看缓冲区下一个字符但不读走
cin.ignore(n, delim) 丢弃 n 个字符或直到遇到 delim
cin.putback(ch) 将字符 ch 放回缓冲区
cin.clear() 清除错误状态(如 failbit)