使用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;
}

相关推荐

最近更新

  1. TCP协议是安全的吗?

    2024-03-18 08:20:02       18 阅读
  2. 阿里云服务器执行yum,一直下载docker-ce-stable失败

    2024-03-18 08:20:02       19 阅读
  3. 【Python教程】压缩PDF文件大小

    2024-03-18 08:20:02       19 阅读
  4. 通过文章id递归查询所有评论(xml)

    2024-03-18 08:20:02       20 阅读

热门阅读

  1. Solr完结版

    2024-03-18 08:20:02       20 阅读
  2. Kafka(十)安全

    2024-03-18 08:20:02       17 阅读
  3. Mysql数据库的多实例部署

    2024-03-18 08:20:02       21 阅读
  4. widget一些控件的使用

    2024-03-18 08:20:02       19 阅读
  5. C++ L2【入门】求和

    2024-03-18 08:20:02       20 阅读
  6. ubuntu(22.04版本之前)安装docker

    2024-03-18 08:20:02       20 阅读
  7. MySQL运维实战之备份和恢复(8.8)恢复单表

    2024-03-18 08:20:02       18 阅读
  8. 【C/C++】Linux系统周期回调函数(互斥锁双回调)

    2024-03-18 08:20:02       19 阅读
  9. Mysql设计规范

    2024-03-18 08:20:02       20 阅读
  10. HTB WifineticTwo

    2024-03-18 08:20:02       33 阅读