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
错误分析与修复方案
核心错误点
- 引用绑定错误:
lastGrp = totalInfo.back();引用一旦绑定对象后无法更改绑定目标,这行实际是把新分组的值赋给了原本的哨兵节点,导致哨兵节点被污染,同时后续处理指向错误分组。 - 数据类型不匹配:
dataTy被定义为std::tuple<int, char>,但样本数据是两个char类型,隐式转换可能引发未定义行为。 - 哨兵节点被意外修改:由于引用赋值错误,哨兵节点的标签被改为有效数据标签,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; }
关键改动说明
- 修正
dataTy为std::tuple<char, char>,匹配样本数据类型,避免隐式转换问题。 - 在
emplace_back后重新获取最新分组的引用,替换错误的引用赋值逻辑,确保后续操作指向正确的分组。 - 改用
std::pair的成员访问(range.first/range.second)替代std::get,代码更直观。 - 优化计数逻辑:直接对现有节点的计数累加,无需
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
相关产品推荐
相关产品推荐

