You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用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
}

关键说明

  1. 调整循环逻辑:把iss >> std::quoted(token)作为循环条件,只有读取成功时才执行循环体,读取失败(包括到达EOF)直接退出循环,避免无效的读取尝试。
  2. 精准错误判断:退出循环后,仅在两种场景下判定为错误并抛出异常:
    • iss.bad():流发生严重底层错误(如缓冲区损坏),属于不可恢复的错误。
    • iss.fail() && !iss.eof():提取失败且不是因为到达EOF,比如输入未闭合的引号(如"hello world),属于非法输入场景。

这样修改后,既能正确处理以引号串结尾的合法输入,又能可靠检测真正的分词错误。

内容的提问来源于stack exchange,提问作者user5534993

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.05 02:55:24