std::istringstream
最常用于接受单行文本并进行处理的用户输入。这样可以避免当输入不符合预期或不能预测时可能出现的问题。
下面是一个简单的示例,它从 STDIN 逐行读取数据,并将其处理为一个命令,后跟一个字符串向量作为参数。
for(std::string line; std::getline(std::cin, line); )
{
std::istringstream iss(line);
std::string command;
if (iss >> command)
{
std::vector<std::string> args;
for (std::string arg; iss >> arg; )
{
args.push_back(arg);
}
std::cout << "Received '" << command << "' with " << args.size() << " arguments\n";
}
else
{
std::cerr << "Invalid input" << std::endl;
}
}
当然,您不需要阅读字符串或将内容存储在向量中。这仅仅是为了说明目的。
基本点是要避免人们遇到的陷阱,其中最常见的是期望先前的流操作成功。当这个假设是错误的时候,天真的程序员会发现自己试图解析应该在前一行交付的东西。
破碎的例子:
#include <iostream>
int main() {
std::string command;
while (std::cin >> command)
{
std::cout << "Got command: " << command << std::endl;
if (command == "foo")
{
int arg1, arg2;
std::cin >> arg1 >> arg2;
std::cout << command << ": " << arg1 << ", " << arg2 << std::endl;
}
else if (command == "bar")
{
float arg1;
std::cin >> arg1;
std::cout << command << ": " << arg1 << std::endl;
}
}
return 0;
}
在上述例子中,假设用户因为困惑而使用一个浮点数参数“调用”了“foo”命令,那么下一个命令就是有效的“bar”命令。
foo 42.0
bar 3.14
这里发生了以下情况:
foo处理程序将arg1读为42,然后未能读取下一个参数。现在流处于错误状态。
在该处理程序期间没有对输入进行任何错误检查,因此输出arg2
的值时会出现未定义行为。
尝试读取下一个命令时,流已经处于错误状态,因此循环终止。
因此,该程序的输出可能如下所示:
Got command: foo
foo: 42, -149017896
没有使用
istringstream
修复此问题是可能的,但很麻烦。流可能进入错误状态的原因有很多,只为了解决这个问题而清除特定错误状态的错误标志会导致丑陋且可能容易出错的代码。你不仅需要清除错误标志,还需要告诉流忽略行中剩余的任何字符。而且你可能已经在不知情的情况下开始读取下一行了。
更健壮的示例:
#include <iostream>
#include <sstream>
int main() {
std::string command;
for (std::string line; std::getline(std::cin, line); )
{
std::istringstream iss(line);
if (!(iss >> command))
continue;
std::cout << "Got command: " << command << std::endl;
if (command == "foo")
{
int arg1, arg2;
if (iss >> arg1 >> arg2)
{
std::cout << command << ": " << arg1 << ", " << arg2 << std::endl;
}
}
else if (command == "bar")
{
float arg1;
if (iss >> arg1)
{
std::cout << command << ": " << arg1 << std::endl;
}
}
}
return 0;
}
现在,与之前示例中相同的输入会产生以下输出:
Got command: foo
Got command: bar
bar: 3.14
区别如下:
使用istringstream
,任何处理输入时的错误都不会影响源流,因此前一行的失败不会引起问题。
在读取参数时正确检查字符串流,允许可选的错误处理。
如果在某些解析失败后,您决定尝试以不同方式处理输入行,则可以使用另一个字符串流轻松实现。
istringstream
,为什么不删除所有多线程内容并编辑你的问题以包含一个[mcve]? - Sid S