C++ 输入函数大乱斗:cin.get、cin.getline、getline 的区别与记忆技巧
前言
学习 C++ 输入输出时,cin.get()、cin.getline() 和 getline() 这三个函数常常让人混淆。它们都能读取输入,但行为却各不相同。本文通过对比分析和实用示例,帮你彻底理清它们的区别,并提供简单的记忆方法。
三个函数的快速对比
| 函数 | 所属 | 语法 | 读取内容 | 处理换行符 |
|---|
cin.get() | istream 成员 | cin.get(buf, size) | 包含换行符 | 留在缓冲区 |
cin.getline() | istream 成员 | cin.getline(buf, size) | 不包含换行符 | 读取并丢弃 |
getline() | 全局函数 | getline(cin, str) | 不包含换行符 | 读取并丢弃 |
cin >> | 运算符重载 | cin >> var | 遇到空白停止 | 留在缓冲区 |
函数详解
1. cin.get()
语法
1 2 3 4 5 6 7 8
| char ch = cin.get();
cin.get(char* buf, int size);
cin.get(char* buf, int size, char delim);
|
特点
- 读取
size - 1 个字符或遇到换行符停止 - 换行符留在输入缓冲区
- 读取的内容包含换行符(如果用单字符版本)
示例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| #include <iostream> using namespace std;
int main() { char buf[20];
cout << "输入:Hello World\n"; cin.get(buf, 20);
cout << "读取内容:[" << buf << "]" << endl;
char next = cin.get(); cout << "下一个字符是换行符:" << (next == '\n' ? "YES" : "NO") << endl;
return 0; }
|
输出:
1 2 3
| 输入:Hello World 读取内容:[Hello World] 下一个字符是换行符:YES
|
2. cin.getline()
语法
1 2 3 4 5
| cin.getline(char* buf, int size);
cin.getline(char* buf, int size, char delim);
|
特点
- 读取
size - 1 个字符或遇到换行符停止 - 换行符被读取并丢弃(不在缓冲区,也不在 buf 中)
- 只能用于字符数组(C 风格字符串)
示例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| #include <iostream> using namespace std;
int main() { char buf[20];
cout << "输入:Hello World\n"; cin.getline(buf, 20);
cout << "读取内容:[" << buf << "]" << endl;
cout << "准备读取下一个输入..." << endl;
return 0; }
|
3. getline() - 全局函数
语法
1 2 3 4 5
| getline(istream& is, string& str);
getline(istream& is, string& str, char delim);
|
特点
- 读取整行,自动扩展 string 大小
- 换行符被读取并丢弃
- 只能用于std::string 类型
- 是全局函数,不是成员函数
示例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| #include <iostream> #include <string> using namespace std;
int main() { string str;
cout << "输入:Hello World from string!\n"; getline(cin, str);
cout << "读取内容:[" << str << "]" << endl; cout << "长度:" << str.length() << endl;
return 0; }
|
核心区别对比实验
实验 1:换行符去哪了?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33
| #include <iostream> #include <string> using namespace std;
int main() { char buf[50]; string str;
cout << "=== 测试 cin.get() ===" << endl; cout << "请输入一行:"; cin.get(buf, 50); cout << "buf: [" << buf << "]" << endl; cout << "下一个字符 ASCII: " << (int)cin.get() << endl;
cout << "\n=== 测试 cin.getline() ===" << endl; cin.ignore(); cout << "请输入一行:"; cin.getline(buf, 50); cout << "buf: [" << buf << "]" << endl; cout << "下一个字符 (按任意键): "; char ch = cin.get(); cout << "你按了: " << ch << endl;
cout << "\n=== 测试 getline() ===" << endl; cout << "请输入一行:"; getline(cin, str); cout << "str: [" << str << "]" << endl; cout << "下一个字符 (按任意键): "; ch = cin.get(); cout << "你按了: " << ch << endl;
return 0; }
|
实验 2:混合使用 cin >> 后的问题
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| #include <iostream> #include <string> using namespace std;
int main() { int age; char buf[50]; string str;
cout << "输入年龄:"; cin >> age;
cout << "cin.get() 读取:"; cin.get(buf, 50); cout << "[" << buf << "]" << endl;
cout << "再次用 getline(cin) 读取:"; getline(cin, str); cout << "[" << str << "]" << endl;
return 0; }
|
问题原因:cin >> 只读取数字,换行符留在缓冲区,后续的 get 类函数立即读到换行符就结束了。
解决方案:
1 2 3 4
| cin >> age; cin.ignore();
cin.ignore(1000, '\n');
|
一图总结
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| ┌─────────────────────────────────────────────────────────────┐ │ 输入:"ABC\n" │ └─────────────────────────────────────────────────────────────┘ │ ┌─────────────────────┼─────────────────────┐ ▼ ▼ ▼ cin.get() cin.getline() getline(cin) char buf[] char buf[] string str │ │ │ ▼ ▼ ▼ ┌────────┐ ┌────────┐ ┌────────┐ │ "ABC\n"│ │ "ABC" │ │ "ABC" │ └────────┘ └────────┘ └────────┘ │ │ │ 换行符在 buf 中 换行符被丢弃 换行符被丢弃 │ │ │ ▼ ▼ ▼ 缓冲区:空 缓冲区:空 缓冲区:空
|
记忆技巧
技巧 1:看函数名
1 2 3
| cin.get() → get = 获取 → 来者不拒,换行符也要 cin.getline() → getline 但用 cin. → 字符数组版,丢弃换行 getline() → 全局函数 → string 专用,丢弃换行
|
技巧 2:看参数类型
1 2 3
| cin.get(buf, size) cin.getline(buf, size) getline(cin, str)
|
记忆口诀: > 有 cin 点的是小弟(留换行) > 没 cin 点的是大哥(丢换行) > string 只能用全局 getline
技巧 3:场景联想
| 场景 | 选择 |
|---|
| 读取单个字符 | cin.get() |
| C 风格字符串,需要换行符 | cin.get() |
| C 风格字符串,不要换行符 | cin.getline() |
| C++ string,读一行 | getline(cin, str) |
| 读取数字后读字符串 | cin >> x; cin.ignore(); getline(cin, str); |
常见陷阱与解决方案
陷阱 1:cin >> 后直接 getline
1 2 3 4 5 6 7 8 9 10 11 12
| int n; string s; cin >> n; getline(cin, s);
int n; string s; cin >> n; cin.ignore(); getline(cin, s);
|
陷阱 2:连续使用 cin.get()
1 2 3 4 5 6 7 8 9 10
| char buf1[50], buf2[50]; cin.get(buf1, 50); cin.get(buf2, 50);
char buf1[50], buf2[50]; cin.get(buf1, 50); cin.ignore(); cin.get(buf2, 50);
|
陷阱 3:混淆返回值
1 2 3 4 5 6 7 8
| cin.get(buf, 50).get(ch);
getline(cin, str1).getline(cin, str2);
getline(cin, str1); getline(cin, str2);
|
完整示例程序
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62
| #include <iostream> #include <string> #include <cstring> using namespace std;
void test_cin_get() { cout << "\n=== cin.get() 测试 ===" << endl; char buf[100];
cout << "请输入一行文字:"; cin.get(buf, 100);
cout << "读取内容:[" << buf << "]" << endl; cout << "长度:" << strlen(buf) << endl;
int len = strlen(buf); if (len > 0 && buf[len-1] == '\n') { cout << "提示:内容包含换行符" << endl; } }
void test_cin_getline() { cout << "\n=== cin.getline() 测试 ===" << endl; char buf[100];
cin.ignore(1000, '\n'); cout << "请输入一行文字:"; cin.getline(buf, 100);
cout << "读取内容:[" << buf << "]" << endl; cout << "长度:" << strlen(buf) << endl; cout << "提示:换行符已被丢弃" << endl; }
void test_std_getline() { cout << "\n=== getline(cin, str) 测试 ===" << endl; string str;
cout << "请输入一行文字:"; getline(cin, str);
cout << "读取内容:[" << str << "]" << endl; cout << "长度:" << str.length() << endl; cout << "提示:换行符已被丢弃" << endl; }
int main() { cout << "========================================" << endl; cout << " C++ 输入函数对比测试程序" << endl; cout << "========================================" << endl;
test_cin_get(); test_cin_getline(); test_std_getline();
cout << "\n========================================" << endl; cout << " 测试完成!" << endl; cout << "========================================" << endl;
return 0; }
|
总结表格
| 特性 | cin.get() | cin.getline() | getline() |
|---|
| 类型 | 成员函数 | 成员函数 | 全局函数 |
| 目标类型 | char/char[] | char[] | string |
| 换行符处理 | 留在缓冲区 | 读取并丢弃 | 读取并丢弃 |
| 是否包含换行 | 是 | 否 | 否 |
| 自动扩容 | 否 | 否 | 是 |
| 指定分隔符 | 支持 | 支持 | 支持 |
| 推荐场景 | 字符/保留换行 | C 风格字符串 | C++ string |
终极记忆口诀
1 2 3 4 5 6
| ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ cin 后面有个点,换行留在缓冲区 直接调用 getline,换行自动被丢弃 string 只能用全局,char 数组用成员 cin >> 后要 ignore,否则 getline 会出错 ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
记住这个口诀,这三个函数再也难不倒你!
参考资源: - C++ Reference - istream::get - C++ Reference - istream::getline - C++ Reference - std::getline