getline 函数在 C++ 里面有两套主流版本,一套是标准库 string 版本,属于头文件 string 里面的全局函数,作用是从输入流读取一整行文本,读到换行符停止,并且不会把换行符存入字符串,另一套是 C 语言风格的 istream 成员函数版本,还有 C 库的 getline,也就是 POSIX 标准的 getline,主要用来读取整行,自动处理缓冲区扩容,这也是初学者最容易混淆的地方,很多人会把 cin 和 getline 混用,出现读取空行的经典 bug,核心原因就是 cin 读取数字之后,输入缓冲区还残留换行符,下一次调用 getline 的时候直接识别换行就结束读取,学习的时候必须掌握函数原型 参数含义 返回值,还有输入缓冲区残留这个核心坑点,它和 cin 读取单词不一样,cin 默认遇到空格就截断,getline 可以完整保留一行里面所有空格,适合读取带空格的整行内容。
两套版本对照表
| 版本 | 所属环境 | 头文件 | 函数原型 | 核心特点 |
|---|---|---|---|---|
| C++ string 版 getline | C++ 标准库 | string | getline(istream &is, string &str, char delim) | 读取整行,默认分隔符是换行,存入 string 对象,自动管理内存 |
| POSIX C 版 getline | C 语言 POSIX | stdio.h | ssize_t getline(char **lineptr, size_t *n, FILE *stream) | 动态分配缓冲区,读取一行,缓冲区不够会自动扩容,返回读取字符总数 |
C++ string 版 getline 详细讲解
函数原型完整写法
std::getline (std::cin, str);
第三个参数是可选分隔符,写出来就是 std::getline (std::cin, str, '');
参数说明
第一个参数 is 输入流对象,一般就是 cin,也可以是文件流 ifstream
第二个参数 str 是 string 类型变量,读取到的一行内容会存进这个变量
第三个参数 delim 可选,自定义终止字符,读到这个字符就停止读取,默认终止符是换行符 \n
读取规则
读到终止字符之后,终止字符会从输入流里面取出,但是不会保存到 str 字符串里面,读取完成之后字符串末尾自动补结束标记
返回值 这个版本返回 istream 流对象,读取失败或者到达文件末尾的时候,流状态变成 false,可以用来做 while 循环判断
POSIX C 版 getline 详细讲解
参数说明
lineptr 二级指针,指向缓冲区,如果传入是空指针,函数会自动 malloc 分配缓冲区
n 指针,用来保存缓冲区总大小
stream 文件流,一般是 stdin 代表标准输入
返回值 ssize_t 类型,成功返回读取字符数量,包含换行符,失败返回 - 1
特点 当一行内容长度超过现有缓冲区,函数会自动调用 realloc 扩大缓冲区,不需要程序员手动预估行长度,适合读取长度不确定的长行,注意这个函数是 POSIX 标准,Windows 部分编译器原生不支持,跨平台项目要留意兼容性
使用操作步骤
第一 C++ 基础读取一行示例
引入头文件 iostream 和 string
代码逻辑
include
include
using namespace std;
int main ()
{
string line;
getline (cin, line);
cout << line << endl;
return 0;
}
第二 自定义分隔符用法
getline (cin, line, ',');
含义就是读到逗号就停止读取,逗号后面内容仍然留在输入缓冲区
第三 文件读取场景
ifstream fin ("test.txt");
string line;
while (getline (fin, line))
{
cout << line << endl;
}
这个循环会逐行读取文件,读到文件末尾自动退出循环
第四 解决 cin 和 getline 混用空行 bug
如果前面执行 cin >> num,输入回车之后,换行符留在缓冲区,下一行 getline 立刻读到换行,直接得到空字符串
解决办法 调用 cin.ignore (); 忽略掉缓冲区残留换行,也可以写 cin.ignore (numeric_limits
第五 POSIX C 版本示例
char buf = NULL;
size_t len = 0;
ssize_t readLen = getline (&buf, &len, stdin);
读取完成之后记得 free (buf); 释放动态内存,防止内存泄漏
常见注意事项
1 getline 读取的一行可以包含空格,这点和 cin >> 不一样,cin >> 遇到空格就停止
2 如果一行是空行,也就是直接回车,读取之后 string 变量内容是空字符串
3 C++ string 版本 getline 属于 std 命名空间,不加 using namespace std 的时候,必须写 std::getline
4 POSIX 版本 getline 分配的内存必须手动释放,不释放会内存泄漏
5 读取超长行的时候,C++ string 版本自动扩容,不需要担心溢出,POSIX 版本也会自动扩容,但是要手动释放内存
核心总结
getline 函数核心作用就是读取一整行文本,C++ 最常用的是 std::getline,搭配 string 对象,读取直到换行,保留行内空格,重点记住 cin 和 getline 混用时要 ignore 清除残留换行,POSIX C 版本 getline 是动态缓冲区版本,读取之后必须释放内存,根据项目是 C++ 还是 C 语言,选择对应的 getline 版本。
【常见问题】
问题 1 getline 函数为什么和 cin 一起用会读到空行
回答 1 getline 函数和 cin 混用出现空行,是因为 cin 读取数值之后,回车产生的换行符还留在输入缓冲区,getline 函数读到这个换行符就立刻结束读取,解决方式是使用 cin.ignore 清除残留换行。
问题 2 getline 函数能不能读取一行里面的空格
回答 2 getline 函数可以完整读取一行内部所有空格,和 cin 按空格截断的特性不一样,getline 函数默认只把换行作为终止标记,行内空格会全部保存到字符串里面。
问题 3 getline 函数有两个版本要怎么区分
回答 3 getline 函数分为 C++ 标准库 string 版本和 POSIX C 语言版本,C++ 版本搭配 string 对象,返回流对象,POSIX 版本使用 char 二级指针缓冲区,返回读取字符数量,使用的时候根据语言环境选择对应的 getline 函数。
【免责申明】
本内容基于 C++ 标准与 POSIX 规范编写,不同编译器版本对 getline 函数支持存在差异,部分老旧编译器或者 Windows 原生环境对 POSIX 版 getline 函数支持不完善,正式项目开发请参考对应编译器官方文档。


