我有一个文本文件,其中包含一系列两个字符串,每行以冒号分隔。
我使用 getline 来抓取整行,然后使用字符串流来拆分两个字符串并将它们放到一个向量上。该代码在第一遍时运行良好,它完美地抓取了字符串。然后在 while 循环的第二遍之后,依此类推,它不会获取新的输入。由于某种原因,字符串流似乎保留了原始的第一个值。
if (infile.is_open()) {
std::stringstream ss;
std::string current_line;
std::string tempProxy;
std::string tempPort;
while (std::getline(infile, current_line)) {
ss << current_line;
std::getline(ss, tempProxy, ':');
std::getline(ss, tempPort);
std::cout << tempProxy << " and " << tempPort << std::endl;
}
Run Code Online (Sandbox Code Playgroud)
知道为什么它不想在第一次迭代之外的任何传递中从 current_line 中获取字符串吗?
您正在重用ss但未正确重置它。当您从第一行中提取第二个单词时,流将耗尽并处于“EOF”状态。当流处于此或任何其他“错误”状态时,它们不会执行任何操作。您必须先清除错误,然后才能继续使用它们。
如果你要检查通过返回的错误operator<<和getline(或如果你要引起循环ss扔在错误异常*),你会发现他们表示他们都没有成功过一次迭代。始终检查错误是一个很好的一般做法,尤其是在调试时。
您可以通过更改循环来清除错误:
while (std::getline(infile, current_line)) {
ss.clear(); // clears the error, not the contents
ss << current_line;
Run Code Online (Sandbox Code Playgroud)
然而,这样做意味着ss将在其内部缓冲区中累积所有行。除非文件很大并且内存不足或类似的东西,否则代码将产生您预期的输出。
您可以使用以下内容查看累积的内部缓冲区:
while (std::getline(infile, current_line)) {
ss.clear();
ss << current_line;
std::cout << "ss internal buffer: " << ss.str();
Run Code Online (Sandbox Code Playgroud)
而不是使用格式化输入来添加ss您可能最好使用.str()成员来设置它,这将替换以前的数据而不是添加到它。
while (std::getline(infile, current_line)) {
ss.clear();
ss.str(current_line);
Run Code Online (Sandbox Code Playgroud)
或者,您可以stringstream在循环的每次迭代中构造一个新的。这确实确保没有错误状态或数据从先前的迭代中被遗留下来。它也可能更慢,但你必须自己分析。
while (std::getline(infile, current_line)) {
std::stringstream ss(current_line);
Run Code Online (Sandbox Code Playgroud)
* 异常很好,因为你不需要记住检查它们......除非在默认情况下它们没有启用的情况。此外,我还注意到一些 C++ 实现在其 iostreams 异常代码中存在错误,因为人们很少使用它。