使用std::quoted读取末尾引号串时failbit置位的问题解决
解决
std::quoted分词时末尾引号串触发failbit的问题 问题原因
你的代码用while (!iss.eof())作为循环条件,会导致读完最后一个有效token后,仍会执行一次iss >> std::quoted(token)尝试读取。此时流已到达EOF,提取操作失败触发failbit,进而抛出异常。但实际上,以闭合引号串结尾的输入是合法的,这个引号串应该被正常读取,之后循环应终止而非触发错误。
修正后的代码
#include <cstring> #include <cwchar> #include <iomanip> #include <sstream> #include <stdexcept> #include <string> #include <vector> // Tokenize a string using std::quoted template <typename CharType> std::vector<std::basic_string<CharType>> tokenizeQuoted(const std::basic_string<CharType> &input) { std::basic_istringstream<CharType> iss(input); std::vector<std::basic_string<CharType>> tokens; std::basic_string<CharType> token; // 将读取操作直接作为循环条件,仅在读取成功时进入循环 while (iss >> std::quoted(token)) { tokens.push_back(token); } // 仅在真正的错误场景下抛出异常 if (iss.bad() || (iss.fail() && !iss.eof())) { throw std::runtime_error("failed to tokenize string: '" + input + "'; bad bit = " + (iss.bad() ? "true" : "false")); } return tokens; } int main() { const std::string inputMars = "\"hello mars\"!"; // 末尾带'!' const std::string inputEarth = "\"hello earth\""; // 以引号串结尾 const auto mars = tokenizeQuoted(inputMars); // 返回2个token:"hello mars"、"!" const auto earth = tokenizeQuoted(inputEarth); // 返回1个token:"hello earth" return mars.size() + earth.size(); // 返回3 }
关键说明
- 调整循环逻辑:把
iss >> std::quoted(token)作为循环条件,只有读取成功时才执行循环体,读取失败(包括到达EOF)直接退出循环,避免无效的读取尝试。 - 精准错误判断:退出循环后,仅在两种场景下判定为错误并抛出异常:
iss.bad():流发生严重底层错误(如缓冲区损坏),属于不可恢复的错误。iss.fail() && !iss.eof():提取失败且不是因为到达EOF,比如输入未闭合的引号(如"hello world),属于非法输入场景。
这样修改后,既能正确处理以引号串结尾的合法输入,又能可靠检测真正的分词错误。
内容的提问来源于stack exchange,提问作者user5534993
相关产品推荐
相关产品推荐

