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

解析文件Token存入vector后访问抛出std::out_of_range错误求助

问题分析与解决

核心错误:switch语句缺少break导致Token分类完全失效

你的代码里有两处致命的switch逻辑错误,直接导致Token解析和排序完全偏离预期,最终触发std::out_of_range异常:

1. Token::parse函数的switch无break

解析Token类型时,无论匹配到哪个case,代码都会继续执行后续所有case的赋值操作,最终所有Token的level都会被覆盖为最后一个case的值(FOUR_CHILD)。比如:

  • 输入行@use 1;的lev为'1',代码先执行case '1'设置tpe=ONE_CHILD,但因为没有break,会继续执行case '2'、case '3'、case '4',最终tpe被强制改为FOUR_CHILD。
  • 所有Token的level最终都变成5,排序时全部被归入st.fourth和st.unspec,st.first、st.second等容器完全为空——这就是调用st.first.at(0)抛出异常的根本原因。

修复代码:给每个case添加break,同时初始化tpe避免未定义行为:

static Token parse(string line) {
  string temp;
  istringstream iss(line);
  char lev;
  u8 tpe = Token::UNSPEC; // 初始化默认值
  iss >> temp >> lev;
  switch (lev) {
  case 'c':
    tpe = Token::UNSPEC;
    break;
  case '0':
    tpe = Token::NO_CHILD;
    break;
  case '1':
    tpe = Token::ONE_CHILD;
    break;
  case '2':
    tpe = Token::TWO_CHILD;
    break;
  case '3':
    tpe = Token::THREE_CHILD;
    break;
  case '4':
    tpe = Token::FOUR_CHILD;
    break;
  default:
    cerr << "警告:无效的Token级别 '" << lev << "',行内容:" << line << endl;
    break;
  }
  return Token(tpe, temp);
}

2. TokenScraper::sort函数的switch无break

排序时的switch同样缺少break,会导致一个Token被同时加入多个分类容器(比如NO_CHILD类型的Token会被加入none、first、second等所有后续容器),不符合分类需求。

修复代码:给每个case添加break,同时用size_t代替int作为循环变量(匹配vector::size()的无符号类型):

struct SortedTokens TokenScraper::sort() {
  SortedTokens st;
  for (size_t i = 0; i < tokens.size(); i++) {
    switch (tokens.at(i).level) {
    case Token::NO_CHILD:
      st.none.push_back(tokens.at(i));
      break;
    case Token::ONE_CHILD:
      st.first.push_back(tokens.at(i));
      break;
    case Token::TWO_CHILD:
      st.second.push_back(tokens.at(i));
      break;
    case Token::THREE_CHILD:
      st.third.push_back(tokens.at(i));
      break;
    case Token::FOUR_CHILD:
      st.fourth.push_back(tokens.at(i));
      break;
    case Token::UNSPEC:
      st.unspec.push_back(tokens.at(i));
      break;
    default:
      break;
    }
  }
  return st;
}

其他次要问题修复

1. IOError构造函数逻辑错误

当前构造函数中,message.append(to_string(line))操作的是参数副本,而非类成员变量,导致错误信息拼接失败。修改为:

struct IOError {
  string message;
  IOError(string msg, int line) : message(msg + to_string(line)) {}
};

2. 异常抛出方式错误

构造函数中抛出new IOError是抛出指针,C++通常抛出异常对象而非指针,避免内存泄漏:

TokenScraper::TokenScraper(string filename) {
  file.open(filename);
  if (!file.is_open() || file.peek() == file.eof()) {
    throw IOError("无法打开文件,行号:", __LINE__);
  }
}

throw之后的代码不会执行,因此可以删除file.close()和return。

验证效果

修复上述问题后,st.first会包含所有子节点数为1的Token(@use、@start、@include、import),st.second会包含子节点数为2的Token(@eval、@def、@alias),此时访问st.first.at(0)和st.second.at(0)将不再抛出std::out_of_range异常。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.08 19:04:59