C++统计vector字符串出现次数:越界与最后元素未统计问题
问题描述
自学C++一周,编写了统计vector<string>容器words中各字符串出现次数的代码。当前代码可正常输出「Six」「Three」「Two」的出现次数,但无法输出「One」的统计结果,且程序会因访问vector越界报错。需要解决:在不越界的前提下判断当前元素与下一个元素是否相等,同时确保最后一个元素被正确统计。
原代码如下:
int main() { vector<string> words; words.push_back("Six"); words.push_back("Six"); words.push_back("Six"); words.push_back("Six"); words.push_back("Six"); words.push_back("Six"); words.push_back("Three"); words.push_back("Three"); words.push_back("Three"); words.push_back("Two"); words.push_back("Two"); words.push_back("One"); vector<int> values; // vector to tracks the # of times a string //appears in the vecotor words //create elements in values equal to number of //elements in words //note: this creates too many elements //I am aware but am a begginner and don't know how //to solve this issue for (int i = 0; i <= words.size() - 1; i++) { values.push_back(0); } int invariant = 0; // tracks number of times loops string current; // used make sure duplicate strings aren't recounted while (invariant <= words.size() - 1) { //compare each element of words to each other element //one at a time and increment the appropriate //element of values if they match for (int i = 0; i <= words.size() - 1; i++) { if (words[invariant] == words[i]) { values[invariant] = values[invariant] + 1; } } //used to check for duplicate strings current.clear(); current = words[invariant]; if (invariant + 1 > words.size()) //avoids going outside range of words { return 0; //Errors outside range after this return } else{ if (words[invariant+1] == current) // if the next word is the same { ++invariant; } else //if the next word is different output the number of times the current word appears { cout << current << " appears " << values[invariant] << " times.\n"; ++invariant; } } } return 0; }
注:习惯在循环中使用invariant <= value的写法,若不设置invariant == value - 1程序就会出现越界错误。
问题分析与解决方案
核心问题
- 越界判断逻辑错误:原代码中
invariant + 1 > words.size()的判断无效,当invariant指向最后一个元素(索引为words.size()-1)时,invariant+1等于words.size(),此时访问words[invariant+1]会直接触发越界。 - 最后一个元素未输出:处理到最后一个元素时,代码直接
return 0,导致「One」的统计结果无法输出。 - 冗余的
values容器:创建了与words等长的values容器,实际上只需记录当前字符串的出现次数即可。
修正后的代码
#include <iostream> #include <vector> #include <string> using namespace std; int main() { vector<string> words; words.push_back("Six"); words.push_back("Six"); words.push_back("Six"); words.push_back("Six"); words.push_back("Six"); words.push_back("Six"); words.push_back("Three"); words.push_back("Three"); words.push_back("Three"); words.push_back("Two"); words.push_back("Two"); words.push_back("One"); vector<int> values; for (int i = 0; i <= words.size() - 1; i++) { values.push_back(0); } int invariant = 0; string current; while (invariant <= words.size() - 1) { // 统计当前字符串出现次数 for (int i = 0; i <= words.size() - 1; i++) { if (words[invariant] == words[i]) { values[invariant]++; } } current = words[invariant]; // 优先判断是否为最后一个元素,避免越界 if (invariant == words.size() - 1) { cout << current << " appears " << values[invariant] << " times.\n"; ++invariant; } else { if (words[invariant+1] == current) { ++invariant; } else { cout << current << " appears " << values[invariant] << " times.\n"; ++invariant; } } } return 0; }
关键修改点
- 修正越界问题:新增
invariant == words.size() - 1的判断,直接处理最后一个元素的输出,彻底避免访问words[invariant+1]导致的越界。 - 保留你的循环习惯:依然使用
invariant <= words.size() - 1的循环条件,符合你的编程习惯。 - 确保最后一个元素输出:当
invariant指向最后一个元素时,直接输出统计结果,不再提前return。
进阶优化(可选)
如果想简化代码,无需手动处理重复和越界问题,可以用std::map自动统计次数,代码更简洁高效:
#include <iostream> #include <vector> #include <string> #include <map> using namespace std; int main() { vector<string> words = {"Six", "Six", "Six", "Six", "Six", "Six", "Three", "Three", "Three", "Two", "Two", "One"}; map<string, int> countMap; for (const string& word : words) { countMap[word]++; } for (const auto& pair : countMap) { cout << pair.first << " appears " << pair.second << " times.\n"; } return 0; }
内容的提问来源于stack exchange,提问作者MetalGooseSolid
相关产品推荐
相关产品推荐

