使用map和set实现简单的词频统计

一、运行效果图

在这里插入图片描述

二、代码示例

#include <iostream>
#include <fstream>
#include <sstream>
#include <string>
#include <map>
#include <set>
#include <vector>
#include <algorithm>
using namespace std;

class TextQuery {
public:
    void readFile(const string &filename);
    void query(const string &word);
private:
    vector<string> _lines; // 用于保存每一行的内容
    map<string, set<int>> _wordsNumbers; // 用于保存每个词所在的行号
    map<string, int> _dict; // 用于保存每个词的词频
};

void TextQuery::readFile(const string &filename) {
    // 打开文件流
    ifstream ifs(filename);
    if (!ifs.good()) {
        ifs.close();
        cerr << "open " << filename << " is fail" << endl;
        return;
    } 
    // 操作数据
    string line;
    size_t lineNumber = 0; // 行号
    while (getline(ifs, line)) {
        ++lineNumber;
        _lines.push_back(line); // 记录每一行
        istringstream iss(line);
        string word;
        // 一行一行地处理
        while (getline(iss, word, ' ')) {
            word.erase(remove_if(word.begin(), word.end(), [](const char c) {
                return !isalpha(c); // 处理掉非字母部分
            }),word.end());
            if (word.size() == 0) { // 跳过空字符
                continue;
            }
            ++_dict[word]; // 词频+1
            // 存入word的行号
            auto it = _wordsNumbers.find(word);
            if (it == _wordsNumbers.end()) { // 还没有word对应的key
                set<int> numbers;
                numbers.insert(lineNumber);
                _wordsNumbers[word] = numbers;
            } else { // 有对应key,直接插入
                it->second.insert(lineNumber);
            }
        }
    }
    // 关闭文件流
    ifs.close();
}

void TextQuery::query(const string &word) {
    // 先判断是否存在
    auto dictIt = _dict.find(word);
    if (dictIt == _dict.end()) {
        cout << "\"" << word << "\"" << " never appears!" << endl;
        return;
    }
    // 查找数据
    cout << "\"" << word << "\"" << " occurs " << dictIt->second << ((dictIt->second > 1) ? " times" : " time") << endl;
    auto wordsNumbersIt = _wordsNumbers.find(word); // 不用再校验
    for (const auto &lineNumber : wordsNumbersIt->second) {
        cout << lineNumber << ": ";
        // 标亮显示行内容
        istringstream iss(_lines[lineNumber - 1]);
        string tempWord;
        while (getline(iss, tempWord, ' ')) {
            if (word == tempWord) {
                cout << "\033[31m" << tempWord << "\033[0m" << " ";                
            } else {
                cout << tempWord << " ";
            }
        }
        cout << endl;
    }
}

void test0() {
    TextQuery tq;
    tq.readFile("./test.txt");
    string word;
    while (cout << "请输入要查询的关键字:", getline(cin, word)) {
        tq.query(word);
    } 
    cout << endl;
}

int main(void) {
    test0();
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值