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

使用结构体数组统计词频时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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.15 08:30:51