C++ std::getline() 函数详解:用法、示例与常见问题
这是文章《如何在C++中使用std::getline()
函数?》的第1部分(共4部分)。
在本文中,我们将深入探讨在C++中使用std::getline()
函数。如果您需要从输入流中读取字符或整行内容,这是一个非常方便且强大的函数。
让我们通过一些具体的例子,详细了解如何正确地使用它。
C++中std::getline()
函数的基本语法
std::getline()
函数用于从输入流中读取字符,并将它们存储到一个字符串中。
为了使用std::getline()
,我们需要引入<string>
头文件,因为getline()
是该头文件的一部分。此外,如果涉及文件操作,还需要引入<fstream>
。
尽管std::getline()
的模板可以接受不同类型的参数,但我们主要关注其最常用的形式,即用于字符串输入(字符)的情况,因为其输出总是写入到字符串中。
istream& getline(istream& input_stream, string& output, char delim);
这个函数签名表明,getline()
函数接受一个输入流(input_stream
),并将读取到的内容写入到指定的输出字符串(output
)中。可选的delim
参数用于指定一个分隔符,当遇到该分隔符时,读取操作将停止。
getline()
函数还会返回一个指向相同输入流的引用,但在大多数情况下,我们并不需要直接使用这个返回值。
使用std::getline()
从输入流中读取内容
既然我们已经了解了基本的语法,让我们从标准输入流 std::cin
中获取字符串输入。
#include <iostream>
#include <string>
int main() {
// 定义一个字符串变量用于存储姓名
std::string name;
std::cout << "请输入您的姓名: ";
// 从std::cin获取输入并存储到name中
std::getline(std::cin, name);
std::cout << "你好," << name << "!\n";
return 0;
}
输出:
请输入您的姓名: JournalDev
你好,JournalDev!
确实,我们能够毫无问题地从std::cin
中获取输入!
现在让我们看另一个例子。假设我们有一个名为input.txt
的文件,其中包含以下内容:
$ cat input.txt
Hello from JournalDev
Second Line of file
Last line
现在,让我们一行一行地读取这个文件,并将每一行存储到一个字符串向量中!
核心逻辑是持续使用std::getline(file, temp)
读取,直到输入流达到文件末尾(EOF)。
我们可以轻松地用以下格式来实现:
std::ifstream infile("input.txt");
// 临时缓冲区
std::string temp;
// 从输入文件中获取内容,直到文件末尾
while (std::getline(infile, temp)) {
// 添加到输出字符串列表中
outputs.push_back(temp);
}
以下是完整的代码:
#include <iostream>
#include <string>
#include <vector> // 用于 std::vector
#include <fstream> // 用于 std::ifstream 和 std::ofstream
int main() {
// 将文件内容存储到字符串向量中
std::vector<std::string> outputs;
std::cout << "正在从 input.txt 读取...\n";
// 创建文件输入流对象
std::ifstream infile("input.txt");
// 临时缓冲区
std::string temp;
// 从输入文件中获取内容,直到文件末尾
while (std::getline(infile, temp)) {
// 添加到输出字符串列表中
outputs.push_back(temp);
}
// 使用基于范围的for循环遍历输出向量
for (const auto& i : outputs)
std::cout << i << std::endl;
return 0;
}
输出:
正在从 input.txt 读取....
Hello from JournalDev
Second Line of file
Last line
在C++中使用std::getline()
函数以分隔符拆分输入
除了默认的换行符 \n
,我们还可以利用 std::getline()
函数的第三个参数——分隔符(delim
),来指定自定义的输入分割字符。
默认情况下,std::getline()
将换行符(\n
)作为输入流的默认分隔符。然而,我们可以轻松修改此设置,使其根据其他字符进行输入分割。
现在,让我们将上述示例中的分隔符更改为空格字符 ' '
,并观察其效果!
#include <iostream>
#include <string>
#include <vector> // 用于 std::vector
#include <fstream> // 用于 std::ifstream 和 std::ofstream
int main() {
// 将内容存储到字符串向量中
std::vector<std::string> outputs;
std::cout << "正在从 input.txt 读取数据....\n";
// 创建文件对象(输入)
std::ifstream infile("input.txt");
// 临时缓冲区
std::string temp;
// 从输入文件中获取数据,直到文件结束(EOF)
while (std::getline(infile, temp, ' ')) {
// 添加到输出字符串列表中
outputs.push_back(temp);
}
// 使用基于范围的 for 循环遍历输出向量
for (const auto& i : outputs)
std::cout << i << std::endl;
return 0;
}
输出
正在从 input.txt 读取数据....
Hello
from
JournalDev
Second
Line
of
file
Last
line
正如所料,我们现在成功地获得了以空格分隔的字符串!
使用 std::getline()
可能存在的问题
这是文章《如何在C++中使用std::getline()函数?》的第3部分(共4部分)。
尽管`std::getline()`是一个非常有用的函数,但当与某些输入流(如`std::cin`)一起使用时,可能会遇到一些问题。
- `std::getline()`不会忽略任何开头的空白字符或换行符。
因此,如果在调用`getline()`之前调用`std::cin >> var;`,在读取输入变量后,输入流中仍会残留一个换行符。
如果你在`cin`之后立即调用`getline()`,你会得到一个换行符,因为它是输入流中的第一个字符!
为了避免这种情况,只需添加一个“虚拟”的`std::getline()`调用来消耗这个换行符!
以下程序展示了在使用`getline()`之前使用`cin`时存在的问题。
#include <iostream>
#include <string>
int main() {
// 定义一个字符串变量用于存储姓名
std::string name;
int id;
std::cout << "请输入ID: ";
std::cin >> id;
std::cout << "请输入姓名: ";
// 注意:上一个输入操作是std::cin!
std::getline(std::cin, name);
std::cout << "ID: " << id << std::endl;
std::cout << "姓名: " << name << "\n";
return 0;
}
产出:
请输入ID: 10
请输入姓名: ID: 10
姓名:
注意到我根本无法输入姓名!由于输入流中存在一个尾随的换行符,`getline()`只是读取了该字符,并且因为它是一个分隔符,所以停止了继续读取!
现在让我们在实际的`std::getline()`调用之前添加一个“虚拟”的`std::getline()`调用。
#include <iostream>
#include <string>
int main() {
// 定义一个字符串变量用于存储姓名
std::string name;
int id;
std::cout << "请输入ID: ";
std::cin >> id;
std::cout << "请输入姓名: ";
// 添加一个虚拟的getline()调用来消耗换行符
std::getline(std::cin, name);
// 注意:上一个输入操作是std::cin!
std::getline(std::cin, name);
std::cout << "ID: " << id << std::endl;
std::cout << "姓名: " << name << "\n";
return 0;
}
产出:
请输入ID: 10
请输入姓名: JournalDev
ID: 10
姓名: JournalDev
我们终于修复了我们的错误!希望这会让你在盲目使用`std::getline()`之前多加思考。
很遗憾,C++中没有特别优雅的方法来获取输入,所以我们必须利用现有方法来解决问题!
结论
在本文中,我们学习了如何在C++中使用std::getline()
函数。我们还通过一些示例,展示了这个函数的强大功能和潜在的陷阱。