我有兴趣讨论用于stringstream解析具有多种类型的行的方法.我将从查看以下行开始:
"2.832 1.3067 nana 1.678"
Run Code Online (Sandbox Code Playgroud)
现在让我们假设我有一个有多个strings和的长行doubles.解决这个问题的显而易见的方法是将字符串标记化,然后检查转换每个字符串.我有兴趣跳过第二步,stringstream直接使用只找到数字.
我认为解决这个问题的好方法是读取字符串并检查是否failbit已设置,如果我尝试将字符串解析为double,它将会是这样.
说我有以下代码:
string a("2.832 1.3067 nana 1.678");
stringstream parser;
parser.str(a);
for (int i = 0; i < 4; ++i)
{
double b;
parser >> b;
if (parser.fail())
{
std::cout << "Failed!" << std::endl;
parser.clear();
}
std::cout << b << std::endl;
}
Run Code Online (Sandbox Code Playgroud)
它将打印出以下内容:
2.832
1.3067
Failed!
0
Failed!
0
Run Code Online (Sandbox Code Playgroud)
我没有惊讶它没有解析一个字符串,但内部发生了什么,以至于它无法清除它failbit并解析下一个数字?
πάν*_*ῥεῖ 22
下面的代码工作很好地跳过坏词,收集有效double值
istringstream iss("2.832 1.3067 nana 1.678");
double num = 0;
while(iss >> num || !iss.eof()) {
if(iss.fail()) {
iss.clear();
string dummy;
iss >> dummy;
continue;
}
cout << num << endl;
}
Run Code Online (Sandbox Code Playgroud)
这是一个完整的样本.
您的示例几乎正确,在检测到格式错误后,从流中消耗无效输入字段只是丢失了
if (parser.fail()) {
std::cout << "Failed!" << std::endl;
parser.clear();
string dummy;
parser >> dummy;
}
Run Code Online (Sandbox Code Playgroud)
在您的情况下,提取将尝试再次从"nana"最后一次迭代读取,因此输出中的最后两行.
还要注意我的第一个样本中的狡猾iostream::fail()以及如何实际测试iostream::eof().有一个众所周知的问答,为什么简单测试EOF作为循环条件被认为是错误的.它答案很好,如何在遇到意外/无效值时打破输入循环.但是那里没有解释如何跳过/忽略无效的输入字段(并且没有被要求).
与 \xcf\x80\xce\xac\xce\xbd\xcf\x84\xce\xb1 \xe1\xbf\xa5\xce\xb5\xe1\xbf\x96\ 的答案有一些细微的差别 - 使其也可以处理例如负数表示等,以及 - 恕我直言 - 更容易阅读。
\n\n#include <iostream>\n#include <sstream>\n#include <string>\n\nint main()\n{\n std::istringstream iss("2.832 1.3067 nana1.678 x-1E2 xxx.05 meh.ugh");\n double num = 0;\n for (; iss; )\n if (iss >> num)\n std::cout << num << \'\\n\';\n else if (!iss.eof())\n {\n iss.clear();\n iss.ignore(1);\n }\n}\nRun Code Online (Sandbox Code Playgroud)\n\n输出:
\n\n2.832\n1.3067\n1.678\n-100\n0.05\nRun Code Online (Sandbox Code Playgroud)\n\n(看到它在这里运行运行)
\n