使用结构体数组统计词频时strcmp无限循环且仅读首个词的问题
问题分析与修复方案
嘿,我来帮你拆解代码里的问题——你遇到的strcmp无限循环、只能读取第一个词的情况,主要是几个核心逻辑和初始化的问题导致的,咱们逐个来解决:
1. 结构体数组未初始化,触发野指针灾难
你定义了cuvinte multime[100];但完全没初始化,数组里每个元素的cuvant都是野指针(指向随机内存地址),numar也是随机值。这时候调用strcmp(cuvant, multime[i].cuvant),本质是在和垃圾内存对比,直接导致未定义行为——要么崩溃,要么陷入异常循环,结果完全不可控。
修复方法:在使用数组前先初始化每个元素:
// 初始化结构体数组,避免野指针和随机值 for (int i = 0; i < 100; i++) { multime[i].cuvant = nullptr; multime[i].numar = 0; }
2. strtok分隔符不一致,导致后续词汇无法解析
第一次调用strtok你用的是" ,/_",但第二次调用却改成了" ",这会导致分隔规则不统一——比如文本里用逗号分隔的词,strtok会直接停止解析,自然只能拿到第一个词。
修复方法:两次strtok调用用相同的分隔符:
cuvant = strtok(NULL, " ,/_");
3. 内层循环逻辑混乱,触发无意义遍历与重复插入
你的嵌套循环逻辑完全拧巴了:
- 遍历
i从0到9时,每一次不匹配就去遍历所有空位插入,会把同一个词重复塞进所有numar==0的位置,而且没有终止条件,很容易触发逻辑死循环。 - 正确逻辑应该是:先遍历数组找是否已有匹配词汇,找到就计数+1;如果遍历完都没找到,再找第一个空位插入。
修复方法:重构内层判断逻辑:
bool found = false; // 先找已有词汇,匹配就计数加1 for (int i = 0; i < 100; i++) { if (multime[i].cuvant != nullptr && strcmp(cuvant, multime[i].cuvant) == 0) { multime[i].numar++; found = true; break; // 找到就立刻退出循环,不用继续遍历 } } // 没找到的话,找第一个空位插入新词汇 if (!found) { for (int i = 0; i < 100; i++) { if (multime[i].numar == 0) { // 注意:必须复制字符串内容,不能直接赋值指针(否则会指向临时内存) multime[i].cuvant = new char[strlen(cuvant) + 1]; strcpy(multime[i].cuvant, cuvant); multime[i].numar = 1; break; // 插入第一个空位就退出,避免重复插入 } } }
4. 内存管理的隐藏坑(次要但必须解决)
你用new创建了abc和cuvant但从未释放,会造成内存泄漏;而且直接把cuvant(指向abc的临时内存)赋值给结构体指针是错误的——abc是每行循环的临时变量,后续会被覆盖,结构体里的指针会变成野指针。所以必须手动复制字符串内容到新分配的内存里。
完整修复后的代码
#include <iostream> #include <fstream> #include <string> #include <cstring> #include <algorithm> using namespace std; struct cuvinte { char *cuvant; int numar; }; int main() { cuvinte multime[100]; // 初始化结构体数组 for (int i = 0; i < 100; i++) { multime[i].cuvant = nullptr; multime[i].numar = 0; } ifstream f("input.txt"); if (!f.is_open()) { // 新增:检查文件是否成功打开,避免崩溃 cerr << "无法打开输入文件!" << endl; return 1; } string str; while (getline(f, str)) { char *abc = new char[str.size() + 1]; copy(str.begin(), str.end(), abc); abc[str.size()] = '\0'; // 手动添加字符串结束符,避免strtok出错 char *cuvant = strtok(abc, " ,/_"); while (cuvant != NULL) { bool found = false; // 查找已有词汇 for (int i = 0; i < 100; i++) { if (multime[i].cuvant != nullptr && strcmp(cuvant, multime[i].cuvant) == 0) { multime[i].numar++; found = true; break; } } // 插入新词汇到第一个空位 if (!found) { for (int i = 0; i < 100; i++) { if (multime[i].numar == 0) { multime[i].cuvant = new char[strlen(cuvant) + 1]; strcpy(multime[i].cuvant, cuvant); multime[i].numar = 1; break; } } } cuvant = strtok(NULL, " ,/_"); } delete[] abc; // 释放每行的临时内存 } // 测试输出统计结果 cout << "词汇统计结果:" << endl; for (int i = 0; i < 100; i++) { if (multime[i].cuvant != nullptr) { cout << multime[i].cuvant << ": " << multime[i].numar << endl; delete[] multime[i].cuvant; // 释放结构体中的字符串内存 } } f.close(); return 0; }
额外补充
我还加了文件打开失败的检查,避免程序在文件不存在时直接崩溃;同时在程序结束时释放了所有动态分配的内存,彻底解决内存泄漏问题。
内容的提问来源于stack exchange,提问作者Ionnier
相关产品推荐
相关产品推荐

