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

C++文本文件词频统计代码问题:计数不更新+菜单无效输入循环

问题修复:词频统计失效与菜单输入异常

问题背景

学校项目中遇到两个核心问题:

  • 词频统计失效:文件可正常打开,但所有物品的出现次数始终显示为0;参考Stack Overflow建议修改后编译无错误,但统计列表仍为空,计数未更新。
  • 菜单输入异常:输入无效选项时,程序进入无限循环重复打印菜单。

原问题附带的错误表现:

  • 读取文件时持续抛出“无效条目”错误
  • 显示统计列表时所有物品数量为0

原错误代码

#include <iostream>
#include <fstream>
#include <map>
#include <string>
#include <stdexcept>

using namespace std;

class ItemCounter {
private:
    map <string, int> itemFrequency;
    string inputFile = "CS210_Project_Three_Input_File.txt";
    string outputFile = "itemTracker.dat";
public:
    void loadInputFile() {
        ifstream file(inputFile);
        // OPEN conditions
        if (file.is_open()) {
            string itemName;
            while (getline(file, itemName)) {
                int itemQuantity = 0;
                // Update item count
                itemFrequency[itemName] += itemQuantity;

                // Exception check for string conversion
                try {
                    itemQuantity = stoi(itemName);
                }
                catch (const invalid_argument& e) {
                    cout << "Error: Invalid Entry Found in Input File." << endl;
                    continue;
                }
            }
            // Close open file
            file.close();
        }
        // Else statement if file won't open
        else {
            cout << "Error: Could Not Open Input File" << endl;
            cout << endl;
        }
    }
    // Function to save new data to external file
    void saveOutputFile() {
        ofstream file(outputFile);
        if (file.is_open()) {
            for (auto& item : itemFrequency) {
                file << item.first << " " << item.second << endl;
            }
            file.close();
        }
        else {
            cout << "Error: Could Not Open Output File - Data Not Saved" << endl;
            cout << endl;
        }
    }

    // Function to display item occurrences
    void displayItemCount(string itemName) {
        int count = itemFrequency[itemName];
        cout << "Total Item Occurances for " << itemName << ": " << count << endl;

    }

    //Function to count and display total item counts of whole list
    void displayTotals () {
        for (auto& item : itemFrequency) {
            cout << item.first << " " << item.second << endl;
        }
    }

    // Function to count items in the list and print as histogram
    void displayItemsHistogram() {
        for (auto& item : itemFrequency) {
            cout << item.first << " ";
            for (int i = 0; i < item.second; i++) {
                cout << "*";
            }
            cout << endl;
        }
    }
};
    // 重复定义的函数,语法错误
    void saveOutputFile() {
        ofstream file(outputFile);
        if (file.is_open()) {
            for (auto& item : itemFrequency) {
                file << item.first << " " << item.second << endl;
            }
            file.close();
        }
        else {
            cout << "Error: Could Not Open Output File - Data Not Saved" << endl;
            cout << endl;
        }
    }
};

int main() { 
    ItemCounter itemCounter;
    itemCounter.loadInputFile();
    itemCounter.saveOutputFile();
    int menuChoice = 0;

    while (menuChoice != 4) {
        cout << "Main Menu" << endl;
        cout << endl;
        cout << "1. Stuff" << endl;
        cout << "2. Stuff" << endl;
        cout << "3. Stuff" << endl;
        cout << "4. Exit" << endl;
        cout << "Please make a selection: ";
        cin >> menuChoice;
        cout << endl;

        if (menuChoice == 1) {
            string itemName;
            cout << "Enter search term: ";
            cin >> itemName;
            cout << "FIX ME:" << endl;
        }

        else if (menuChoice == 2) {
            cout << "FIX ME" << endl;
        }

        else if (menuChoice == 3) {
            cout << "FIX ME" << endl;
        }
            
        else if (menuChoice == 4) {
            cout << "Program Terminated" << endl;
        }
        else {
            cout << "Invalid Selection, try again." << endl;
        }
    }
    return 0;
}

错误分析

  • 词频统计逻辑完全错误

    • loadInputFile中,初始化itemQuantity = 0后执行itemFrequency[itemName] += 0,相当于没有任何计数增长。
    • 错误地尝试将物品名称(字符串)转换为整数,导致每次读取都会触发invalid_argument异常,执行continue跳过后续逻辑,根本没有完成统计。
    • 类外部重复定义了saveOutputFile函数,属于语法错误(编译时会报错)。
  • 菜单输入异常

    • 当输入非整数内容时,cin >> menuChoice会进入失败状态,后续所有cin操作都会直接失败,导致menuChoice始终为初始值0,触发无限循环打印菜单。

修复后的代码

#include <iostream>
#include <fstream>
#include <map>
#include <string>
#include <stdexcept>
#include <limits>

using namespace std;

class ItemCounter {
private:
    map<string, int> itemFrequency;
    string inputFile = "CS210_Project_Three_Input_File.txt";
    string outputFile = "itemTracker.dat";
public:
    void loadInputFile() {
        ifstream file(inputFile);
        if (file.is_open()) {
            string itemName;
            // 直接读取每行物品名称,计数自增
            while (getline(file, itemName)) {
                // 跳过空行避免无效统计
                if (itemName.empty()) continue;
                itemFrequency[itemName]++;
            }
            file.close();
        } else {
            cout << "错误:无法打开输入文件" << endl << endl;
        }
    }

    void saveOutputFile() {
        ofstream file(outputFile);
        if (file.is_open()) {
            for (auto& item : itemFrequency) {
                file << item.first << " " << item.second << endl;
            }
            file.close();
        } else {
            cout << "错误:无法打开输出文件 - 数据未保存" << endl << endl;
        }
    }

    void displayItemCount(const string& itemName) {
        // 使用find避免自动插入不存在的键
        auto it = itemFrequency.find(itemName);
        int count = it != itemFrequency.end() ? it->second : 0;
        cout << itemName << " 的总出现次数:" << count << endl;
    }

    void displayTotals() {
        cout << "所有物品统计:" << endl;
        for (auto& item : itemFrequency) {
            cout << item.first << " " << item.second << endl;
        }
        cout << endl;
    }

    void displayItemsHistogram() {
        cout << "统计直方图:" << endl;
        for (auto& item : itemFrequency) {
            cout << item.first << " ";
            for (int i = 0; i < item.second; i++) {
                cout << "*";
            }
            cout << endl;
        }
        cout << endl;
    }
};

int main() { 
    ItemCounter itemCounter;
    itemCounter.loadInputFile();
    itemCounter.saveOutputFile();
    int menuChoice = 0;

    while (menuChoice != 4) {
        cout << "主菜单" << endl << endl;
        cout << "1. 查询单个物品出现次数" << endl;
        cout << "2. 显示所有物品统计" << endl;
        cout << "3. 显示统计直方图" << endl;
        cout << "4. 退出" << endl;
        cout << "请输入选择: ";

        // 处理输入错误
        if (!(cin >> menuChoice)) {
            cout << endl << "输入无效,请输入数字选项!" << endl << endl;
            // 清除错误状态
            cin.clear();
            // 清空输入缓冲区
            cin.ignore(numeric_limits<streamsize>::max(), '\n');
            continue;
        }
        cout << endl;

        switch(menuChoice) {
            case 1: {
                string itemName;
                cout << "输入查询物品: ";
                cin >> itemName;
                itemCounter.displayItemCount(itemName);
                cout << endl;
                break;
            }
            case 2:
                itemCounter.displayTotals();
                break;
            case 3:
                itemCounter.displayItemsHistogram();
                break;
            case 4:
                cout << "程序已终止" << endl;
                break;
            default:
                cout << "无效选择,请重试。" << endl << endl;
        }
    }
    return 0;
}

修复要点

  • 词频统计修复:移除错误的整数转换逻辑,直接对读取到的物品名称执行itemFrequency[itemName]++完成计数;跳过空行避免无效统计。
  • 输入错误处理:在读取菜单选项时检查cin状态,若输入失败则清除错误状态并清空缓冲区,避免无限循环。
  • 完善功能调用:替换菜单中的FIX ME,调用ItemCounter类的对应方法实现功能。
  • 修复语法错误:删除类外部重复定义的saveOutputFile函数。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.18 11:44:58