如何测试stringstream operator >>是否解析了错误类型并跳过它

Fan*_*Fox 30 c++ stringstream

我有兴趣讨论用于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作为循环条件被认为是错误的.它答案很好,如何在遇到意外/无效值时打破输入循环.但是那里没有解释如何跳过/忽略无效的输入字段(并且没有被要求).


Ton*_*roy 5

与 \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}\n
Run Code Online (Sandbox Code Playgroud)\n\n

输出:

\n\n
2.832\n1.3067\n1.678\n-100\n0.05\n
Run Code Online (Sandbox Code Playgroud)\n\n

(看到它在这里运行运行)

\n