默认参数只能从右到左一个一个指定 对于派生类,可以用一个基类的引用来引用这个实现多态 函数重载,要看能不能区别函数,但是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) |