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

C++二叉树输入流处理需求:忽略数字、符号作分隔符

二叉树单词流处理:正确的字符分隔与过滤实现

初始实现及问题

最初的input方法尝试读取输入流中的字符串,处理后加入二叉树,但存在两个明显问题:

void WordTree::input(std::istream& in) {
   std::string str;
   
   while (in >> str) {
      // 转换为小写
      std::transform(str.begin(), str.end(), str.begin(), ::tolower);
      // 删除数字和标点
      str.erase(std::remove_if(str.begin(), str.end(), ::isdigit), str.end());
      str.erase(std::remove_if(str.begin(), str.end(), ::ispunct), str.end());
      // 添加到树中
      if (str != " ")
         add(str);
   }
}

测试结果问题

测试输入:

std::string str_input = " 100 2/3 alakazam qwerty up-time level up up up up bastion how are you 23 ALAKAZAM"

输出暴露两个问题:

  • 出现空单词计数(显示 occurrences: 3):非空判断逻辑错误,应该检查字符串是否为空!str.empty(),而非判断是否等于空格字符串" "。
  • "up-time"被合并为"uptime":原实现先把up-time当作一个完整token读取,再删除标点,不符合“将符号作为分隔符拆分单词”的需求。

错误的逐字符尝试

改用逐字符读取的实现后,所有单词被拼接成长串,完全不符合预期:

void WordTree::input(std::istream& in) {

   char c;
   std::string str;

   
   while (in >> c) {
      if (std::isalpha(c)) {
         str = str + c;
      }
      else if (str != "") {
         std::transform(str.begin(), str.end(), str.begin(), ::tolower);
         add(str);
         str = "";
      }
   }
}

问题根源:while (in >> c)会自动跳过所有空白字符,导致空格无法触发单词分隔,所有字母被连续拼接。

正确的实现方案

采用逐字符读取所有字符(包括空白)的方式,将所有非字母字符(数字、标点、空格)视为单词分隔符,逻辑如下:

  • 遍历每个字符,仅保留字母字符,直接转换为小写并加入当前单词。
  • 遇到非字母字符时,若当前单词非空,则将其加入二叉树并清空。
  • 循环结束后,处理最后一个未完成的单词。
void WordTree::input(std::istream& in) {
    char c;
    std::string current_word;

    // 读取所有字符,包括空白、标点、数字
    while (in.get(c)) {
        // 转换为unsigned char避免std::isalpha的未定义行为
        unsigned char uc = static_cast<unsigned char>(c);
        if (std::isalpha(uc)) {
            // 直接转小写并加入当前单词
            current_word += static_cast<char>(std::tolower(uc));
        } else {
            // 非字母字符触发单词结束
            if (!current_word.empty()) {
                add(current_word);
                current_word.clear();
            }
            // 非字母字符直接忽略
        }
    }

    // 处理循环结束后剩余的单词
    if (!current_word.empty()) {
        add(current_word);
    }
}

实现说明

  1. in.get(c):读取输入流中的每一个字符,包括空白、标点和数字,不会自动跳过,确保所有分隔符都能被捕获。
  2. std::isalpha的安全调用:将char转换为unsigned char,避免处理负数值字符时的未定义行为。
  3. 实时转小写:遇到字母时直接转换为小写,无需事后对整个字符串调用std::transform,提升效率。
  4. 收尾处理:循环结束后检查剩余单词,避免遗漏最后一个未被分隔符终止的单词。

测试验证

使用原测试输入,处理后将得到正确结果:

  • alakazam:2次
  • qwerty:1次
  • up:5次(up-time拆分出的up + 后续4个up)
  • time:1次
  • level:1次
  • bastion:1次
  • how:1次
  • are:1次
  • you:1次
    无空单词计数,完全符合需求。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.09 14:10:39