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

C++11嵌套列表哨兵节点未正常工作,求代码修复方案

C++11嵌套列表分组统计问题修复

问题说明

用C++11开发,需要实现嵌套列表结构:

  • 外层std::list存储多个内层列表,连续相同标签的内层列表需分组
  • 内层列表统计连续相同标签数据的总数,相同则累加计数,否则创建新条目

为避免每次判断容器是否为空,初始化时插入了一个不会出现在数据中的哨兵节点,但方案未按预期工作,出现重复分组且计数错误。

原代码

#include <list>
#include <tuple>
#include <iostream>

using profileLoc = std::pair<char, size_t>;
using profileGrp = std::pair<char, std::list<profileLoc>>;

std::list<profileGrp> totalInfo;

void dump(bool isFinal=false){
  static int dumpCount = 0;
  if(isFinal) std::cout<<"Final ";
  std::cout<<"dump "<< ++dumpCount<<"\n";
  for(auto grp:totalInfo){
    if(grp.first==-1) continue;
    std::cout<<"grp label: "<<grp.first<<"\n";
    for(auto range: grp.second){
      if(std::get<0>(range)==0) continue;
      std::cout<<"\ttype label: "<<std::get<0>(range)<<" count: "<<std::get<1>(range)<<"\n";
    }
  }
}

int main(){

  profileGrp dummyGrp{-1,{{0,0}}};
  totalInfo.push_back(dummyGrp);
  

  using dataTy = std::tuple<int, char>;
  std::list<dataTy> sampleData{
    {'X', 'a'},
    {'X', 'a'},
    {'X', 'a'},
    {'X', 'b'},
    {'X', 'b'},
    {'X', 'b'},
    //{'Y', 'c'},
    //{'Y', 'c'},
    //{'Y', 'b'},
    //{'Y', 'b'},
    //{'Y', 'b'},
  };
  
  for(auto data:sampleData){
    char grpNo;
    char typeNo;
    std::tie(grpNo, typeNo) = data;
    std::cout<<"receiving data "<<grpNo<<" "<<typeNo<<"\n";
    
    profileGrp& lastGrp = totalInfo.back();
    if(lastGrp.first != grpNo){
      std::list<profileLoc> dummyList{{0, 0}};
      totalInfo.emplace_back(grpNo, dummyList);
      lastGrp = totalInfo.back();
    }
    
    std::list<profileLoc>& locList = lastGrp.second;
    if(std::get<0>(locList.back())!=typeNo){
      locList.emplace_back(typeNo, 1);
    } else {
      size_t lastCount = std::get<1>(locList.back());
      locList.pop_back();
      locList.emplace_back(typeNo, lastCount+1);
    }
    
    //dump();
  }

  dump(true);
  return 0;
}

当前错误结果

receiving data X a
receiving data X a
receiving data X a
receiving data X b
receiving data X b
receiving data X b
Final dump 1
grp label: X
    type label: a count: 1
grp label: X
    type label: a count: 2
    type label: b count: 3

期望正确结果

receiving data X a
receiving data X a
receiving data X a
receiving data X b
receiving data X b
receiving data X b
Final dump 1
grp label: X
    type label: a count: 3
    type label: b count: 3

错误分析与修复方案

核心错误点

  1. 引用绑定错误:lastGrp = totalInfo.back(); 引用一旦绑定对象后无法更改绑定目标,这行实际是把新分组的值赋给了原本的哨兵节点,导致哨兵节点被污染,同时后续处理指向错误分组。
  2. 数据类型不匹配:dataTy被定义为std::tuple<int, char>,但样本数据是两个char类型,隐式转换可能引发未定义行为。
  3. 哨兵节点被意外修改:由于引用赋值错误,哨兵节点的标签被改为有效数据标签,dump时被当作有效分组输出。

修复后的代码

#include <list>
#include <tuple>
#include <iostream>

using profileLoc = std::pair<char, size_t>;
using profileGrp = std::pair<char, std::list<profileLoc>>;

std::list<profileGrp> totalInfo;

void dump(bool isFinal=false){
  static int dumpCount = 0;
  if(isFinal) std::cout<<"Final ";
  std::cout<<"dump "<< ++dumpCount<<"\n";
  for(auto grp:totalInfo){
    if(grp.first==-1) continue;
    std::cout<<"grp label: "<<grp.first<<"\n";
    for(auto range: grp.second){
      if(range.first==0) continue;
      std::cout<<"\ttype label: "<<range.first<<" count: "<<range.second<<"\n";
    }
  }
}

int main(){

  profileGrp dummyGrp{-1,{{0,0}}};
  totalInfo.push_back(dummyGrp);
  
  // 修正数据类型为tuple<char, char>,匹配样本数据
  using dataTy = std::tuple<char, char>;
  std::list<dataTy> sampleData{
    {'X', 'a'},
    {'X', 'a'},
    {'X', 'a'},
    {'X', 'b'},
    {'X', 'b'},
    {'X', 'b'},
    //{'Y', 'c'},
    //{'Y', 'c'},
    //{'Y', 'b'},
    //{'Y', 'b'},
    //{'Y', 'b'},
  };
  
  for(auto data:sampleData){
    char grpNo;
    char typeNo;
    std::tie(grpNo, typeNo) = data;
    std::cout<<"receiving data "<<grpNo<<" "<<typeNo<<"\n";
    
    profileGrp& lastGrp = totalInfo.back();
    if(lastGrp.first != grpNo){
      std::list<profileLoc> dummyList{{0, 0}};
      totalInfo.emplace_back(grpNo, dummyList);
      // 重新获取最新的lastGrp引用
      auto& updatedLastGrp = totalInfo.back();
      lastGrp = updatedLastGrp;
    }
    
    std::list<profileLoc>& locList = lastGrp.second;
    if(locList.back().first != typeNo){
      locList.emplace_back(typeNo, 1);
    } else {
      // 直接累加计数,无需反复删除插入
      locList.back().second += 1;
    }
    
    //dump();
  }

  dump(true);
  return 0;
}

关键改动说明

  1. 修正dataTy为std::tuple<char, char>,匹配样本数据类型,避免隐式转换问题。
  2. 在emplace_back后重新获取最新分组的引用,替换错误的引用赋值逻辑,确保后续操作指向正确的分组。
  3. 改用std::pair的成员访问(range.first/range.second)替代std::get,代码更直观。
  4. 优化计数逻辑:直接对现有节点的计数累加,无需pop_back再emplace_back,提升效率。

修复后运行结果

运行修复后的代码,会输出期望的正确结果:

receiving data X a
receiving data X a
receiving data X a
receiving data X b
receiving data X b
receiving data X b
Final dump 1
grp label: X
    type label: a count: 3
    type label: b count: 3

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.14 23:35:22