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

C++实现单词去重排序统计功能,不使用内置数据结构问题咨询

C++单词词频统计程序优化指导

核心需求

  • 将输入文本中的单词统一转为小写,按字母顺序对去重后的唯一单词排序
  • 实现词频统计,唯一单词和对应出现次数全部存储在动态数组中
  • 最终将唯一单词索引列表(concordance list)和词频写入用户指定的输出文件,禁止使用vector、list等标准库现成数据结构

开发约束

  1. 程序需主动提示用户输入待读取的文本文件名,文件打开失败时输出错误信息;读取单词时忽略所有标点符号,所有字母转为小写消除大小写差异
  2. 单词排序、去重、词频统计结果全部存储在动态数组中
  3. 索引列表和词频写入用户指定的输出文件,写入完成后在控制台打印成功提示,同时输出完整的索引列表和词频

开发注意事项

  • 采用模块化设计,拆分多个可复用函数:包括字符串小写转换、标点清理、单词搜索、数组排序、索引写入文件、从输入文件读取下一个单词等
  • 所有非字母字符都视为单词分隔符
  • 唯一单词总数编译期未知,需在运行时通过动态内存分配调整数组大小
  • 静态数组维度必须使用符号常量定义,声明数组时直接使用该常量
  • 一维数组传参时需同时传递维度,二维数组传参时传递行维度,列维度用符号常量定义
  • 禁止使用标准库提供的list等现成数据结构,索引列表需实现为string类型动态数组或动态二维字符数组

现有代码问题梳理

  1. 逻辑冗余:main函数硬编码读取readText.txt,后续findUnique又让用户输入文件名重复读取,且main中静态数组大小仅为100,单词数超过就会触发数组越界
  2. 大小写处理缺失:未实现单词转小写逻辑,大小写不同的同一个单词会被识别为不同单词
  3. 标点处理不完整:仅清理了单词末尾的标点,单词开头、中间的标点未处理
  4. 排序功能未实现:去重后的单词没有按字母顺序排序
  5. 输出逻辑错误:循环内重复打开输出文件,默认覆盖模式会导致最终文件仅保留最后一行数据,且输出文件名硬编码,未让用户自定义
  6. 内存泄漏:动态申请的数组没有手动释放
  7. 模块化程度不足:所有逻辑耦合在findUnique函数中,不符合可复用要求
  8. 读取逻辑错误:main中混用>>和getline读取内容会导致数据丢失,eof()判断逻辑存在缺陷,会多读空行

优化后完整代码

#include <iostream>
#include <fstream>
#include <string>
#include <cctype>
#include <iomanip>

#define MAX_WORD_LEN 100 // 符号常量定义单词最大长度,符合静态数组维度要求

using namespace std;

// 工具函数:将字符串全部转为小写
void toLowerString(string &str) {
    for (int i = 0; i < str.size(); i++) {
        str[i] = tolower(str[i]);
    }
}

// 工具函数:移除字符串中所有非字母字符
void removeNoneAlpha(string &str) {
    string res;
    for (int i = 0; i < str.size(); i++) {
        if (isalpha(str[i])) {
            res += str[i];
        }
    }
    str = res;
}

// 工具函数:在单词数组中搜索目标单词,返回下标,不存在返回-1
int findWord(const string wordArr[], int arrLen, const string &target) {
    for (int i = 0; i < arrLen; i++) {
        if (wordArr[i] == target) {
            return i;
        }
    }
    return -1;
}

// 工具函数:按字母顺序排序单词数组和对应词频数组(冒泡排序实现)
void sortConcordance(string wordArr[], int freqArr[], int arrLen) {
    for (int i = 0; i < arrLen - 1; i++) {
        for (int j = 0; j < arrLen - i - 1; j++) {
            if (wordArr[j] > wordArr[j + 1]) {
                // 交换单词
                string tempWord = wordArr[j];
                wordArr[j] = wordArr[j + 1];
                wordArr[j + 1] = tempWord;
                // 交换对应词频
                int tempFreq = freqArr[j];
                freqArr[j] = freqArr[j + 1];
                freqArr[j + 1] = tempFreq;
            }
        }
    }
}

// 工具函数:将索引列表写入指定输出文件
void writeConcordanceToFile(const string wordArr[], const int freqArr[], int arrLen, const string &fileName) {
    ofstream outFile(fileName);
    if (!outFile.is_open()) {
        cerr << "输出文件打开失败" << endl;
        return;
    }
    outFile << left << setw(20) << "单词" << "出现次数" << endl;
    for (int i = 0; i < arrLen; i++) {
        outFile << left << setw(20) << wordArr[i] << freqArr[i] << endl;
    }
    outFile.close();
    cout << "索引列表已成功写入文件:" << fileName << endl;
}

int main() {
    string inputFileName;
    // 提示用户输入输入文件名
    cout << "请输入待读取的文本文件名:" << endl;
    cin >> inputFileName;

    ifstream inFile(inputFileName);
    if (inFile.fail()) {
        cerr << "输入文件打开失败,请检查文件名是否正确" << endl;
        exit(-1);
    }

    // 第一遍读取统计总单词数,用于初始化动态数组
    int totalWordCount = 0;
    string tempStr;
    while (inFile >> tempStr) {
        removeNoneAlpha(tempStr);
        if (tempStr.size() > 0) { // 过滤掉全是符号的空字符串
            totalWordCount++;
        }
    }
    inFile.close();

    // 重新打开文件读取单词内容
    inFile.open(inputFileName);
    // 初始化动态数组,最大大小为总单词数(最坏情况所有单词都不重复)
    string *uniqueWords = new string[totalWordCount];
    int *freq = new int[totalWordCount];
    int uniqueCount = 0;

    while (inFile >> tempStr) {
        // 清理标点、转小写
        removeNoneAlpha(tempStr);
        if (tempStr.size() == 0) continue;
        toLowerString(tempStr);

        // 查找单词是否已存在
        int existIndex = findWord(uniqueWords, uniqueCount, tempStr);
        if (existIndex != -1) {
            freq[existIndex]++;
        } else {
            uniqueWords[uniqueCount] = tempStr;
            freq[uniqueCount] = 1;
            uniqueCount++;
        }
    }
    inFile.close();

    // 对唯一单词排序
    sortConcordance(uniqueWords, freq, uniqueCount);

    // 控制台输出结果
    cout << endl << left << setw(20) << "单词" << "出现次数" << endl;
    cout << "-----------------------------------" << endl;
    for (int i = 0; i < uniqueCount; i++) {
        cout << left << setw(20) << uniqueWords[i] << freq[i] << endl;
    }

    // 提示用户输入输出文件名
    string outputFileName;
    cout << endl << "请输入要保存的输出文件名:" << endl;
    cin >> outputFileName;
    writeConcordanceToFile(uniqueWords, freq, uniqueCount, outputFileName);

    // 释放动态数组内存,避免泄漏
    delete[] uniqueWords;
    delete[] freq;

    return 0;
}

内容的提问来源于stack exchange,提问作者Bee

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.26 00:54:05