如何修改C++代码以实现正确的向量匹配与行号输出?
修复C++向量匹配行号错误的方案
问题场景
你的输入文件内容大致是这样的(展示关键行):
{4 <1,-1,-1> <1,1,-1> <-1,1,-1> <-1,-1,-1>} //第一行 {4 <1,3,-1> <1,1,-1> <1,1,0.5> <1,3,0.5>} ... {4 <1,-1,-1> <3,-1,-1> <3,1,-1> <1,1,-1>} //第十行
你想要实现的是:读取每个向量(比如1,-1,-1),在文件中找到所有包含该向量的行并输出正确行号,但现有代码不仅遗漏部分匹配,行号还少了1(比如本该匹配9、10行,却输出8、9行)。
现有代码的核心问题
先看你写的代码,主要有几个逻辑bug:
- 文件指针被一次性读完:外层
while(getline(iss, line))读第一行后,内层的while(getline(iss, line))直接把文件读到末尾,后续外层循环再也读不到其他行,自然会遗漏大量匹配。 - 行号计数错误:
curLine初始为0,内层循环第一次读取后就自增,导致行号比实际少1;而且只有内层循环计数,外层循环读取的第一行没被计数。 - 重复遍历导致效率低且遗漏:每个向量都会从头遍历剩余文件,而不是对所有行统一检查所有向量,逻辑混乱。
修复后的代码
我重新调整了逻辑,先把文件内容全部读入内存,再统一处理匹配,这样既避免了文件读取的问题,也能保证行号准确:
#include <iostream> #include <vector> #include <string> #include <fstream> using namespace std; using vecstr = vector<string>; vecstr splitOut(const string &line) { size_t pos = 0; vecstr result; while ((pos = line.find('<', pos)) != string::npos) { size_t endpos = line.find('>', pos); if (endpos != string::npos) { string token = line.substr(pos + 1, endpos - pos - 1); result.push_back(token); } pos = endpos; // 即使endpos是npos,赋值后下一次循环会自动退出 } return result; } int main() { // 第一步:先把整个文件的内容和每行的向量都读进内存 vector<string> allFileLines; vector<vecstr> allLineVectors; ifstream inputFile("a.txt"); string currentLine; unsigned int totalLines = 0; while (getline(inputFile, currentLine)) { totalLines++; allFileLines.push_back(currentLine); allLineVectors.push_back(splitOut(currentLine)); } inputFile.close(); // 文件读完就关闭,避免资源占用 // 第二步:收集所有需要查找的唯一向量(避免重复查找同一个向量) vecstr targetVectors; for (const auto &vecGroup : allLineVectors) { for (const auto &vec : vecGroup) { // 检查向量是否已经在目标列表里,避免重复 bool isDuplicate = false; for (const auto &existingVec : targetVectors) { if (existingVec == vec) { isDuplicate = true; break; } } if (!isDuplicate) { targetVectors.push_back(vec); } } } // 第三步:逐个向量查找所有匹配的行,输出正确行号 for (const auto &target : targetVectors) { for (unsigned int i = 0; i < allLineVectors.size(); ++i) { const vecstr ¤tLineVecs = allLineVectors[i]; // 遍历当前行的所有向量,检查是否匹配 for (const auto &vec : currentLineVecs) { if (vec == target) { cout << "found: " << target << " line: " << (i + 1) << endl; break; // 同一行只要找到一次就停止,避免重复输出 } } } } return 0; }
关键修改点说明
- 预读取全部内容:先把文件所有行和每行拆分后的向量都存在内存里,这样后续匹配不需要反复操作文件指针,逻辑更清晰。
- 行号准确对应:因为文件第一行对应行号1,所以用
i+1来输出行号(i是从0开始的索引),彻底解决行号少1的问题。 - 去重处理:先收集所有唯一的向量,避免重复查找同一个向量,提升效率。如果需要输出同一向量在同一行的多次出现,可以去掉去重逻辑,直接遍历所有向量查找。
- 精确匹配:不再用字符串查找(可能出现部分匹配的错误,比如
1,-1,-1和11,-1,-1会误判),而是直接对比拆分后的向量字符串,匹配更准确。
如果不需要去重,想要输出所有向量的所有出现情况(包括同一行多次出现同一向量),可以把第二步和第三步替换成下面的代码:
// 替代第二步和第三步:不做去重,输出所有匹配 for (unsigned int i = 0; i < allLineVectors.size(); ++i) { const vecstr &sourceVecs = allLineVectors[i]; for (const auto &vec : sourceVecs) { // 遍历所有行查找该向量 for (unsigned int j = 0; j < allLineVectors.size(); ++j) { const vecstr &searchVecs = allLineVectors[j]; for (const auto &matchVec : searchVecs) { if (matchVec == vec) { cout << "found: " << vec << " line: " << (j + 1) << endl; break; } } } } }
内容的提问来源于stack exchange,提问作者user12034867
相关产品推荐
相关产品推荐

