《C++ Primer》小玩具: 文本查询程序代码

一、文本查询程序实现

书中题目:
我们将实现一个简单的文本查询程序,我们的程序允许用户在一个给定文件中查询单词。查询结果是单词在文件中出现的次数及其所在行的列表。如果一个单词在一行中出现多次,此行只列出一次。行会按照升序输出。我们可以直接使用vector 、set和map来直接编写文本查询程序,但我们在这里定义一个抽象的解决方案会更有效。


程序支持以下任务:
1.它必须允许用户指明要处理的文件的名字。程序将存储该文件的内容,以便输出每个单词所在的原始行。
2.它必须将每一行分解为各个单词,并记录每个单词所在的行。在输出行号时,应保证以升序输出,并且不重复。
3.对特定单词的查询将返回出现该单词的所有行的行号。
4.输出某单词所在的行文本时,程序必须能够根据给定的行号从输入文件中获取相应的行。

假定要查询的文件路径为:C:\Users\t\source\repos\vector\ConsoleApplication2\text.txt
text.txt:


wo ai wo de zhong guo
wo ai wo de xiao shu lan 
Sunday's coming I wanna drive my car
这周日我想开着我的爱车
To your apartment with the present like a star
像明星一样带着的礼物去你的公寓
Forecaster said the weathers may be rainy hard
天气预报说天气糟透了
But I know the sun will shine for us
但是太阳会为我们闪耀
Oh lazy seagull fly me from the dark
喔~慵懒的海鸥引领我走向光明
I dress my jeans and feed my monkey banana
穿上我的牛仔,塞满钞票
Then I think my age how old,skyline how far
我想到,我有多大,地平线有多远
Or we need each other in California
喔~在加州我们需要彼此

二、代码:

#include <iostream>
#include <vector>
#include <map>
#include <set>
#include <fstream>
#include <sstream>
#include <stdexcept>

using namespace std;

class TextQuery {
public:
    typedef vector<string>::size_type line_no;
    void read_file(ifstream& is) {
        store_file(is);
        build_map();
    }
    set<line_no> run_query(const string&) const;
    string text_line(line_no) const;
private:
    void store_file(ifstream&);
    void build_map();
    vector<string> lines_of_text;//存放着txt文件
    map<string, set<line_no> >word_map;//存放行号和内容
};

/*存储输入文件*/
void TextQuery::store_file(ifstream& is) {
    string textline;
    while (getline(is, textline)) {//其中 is 是正在读取的输入流,而 textline 是接收输入字符串的 string 变量的名称。
        lines_of_text.push_back(textline);
    }
}

/*建立map容器*/
void TextQuery::build_map() {
    for (line_no line_num = 0; line_num != lines_of_text.size(); ++line_num) {//逐行
        istringstream line(lines_of_text[line_num]);//把读入的每行分解为单词
        string word;
        while (line >> word) {                //对每个单词
            word_map[word].insert(line_num);  // 插入map中
        }
    }
}

/*支持查询*/
set<TextQuery::line_no> TextQuery::run_query(const string& query_word) const {//查询str
    map<string, set<line_no> >::const_iterator loc = word_map.find(query_word);//用find查找不会把单词添加到wordmap中
    if (loc == word_map.end())
        return set<line_no>();//没找到
    else
        return loc->second;//找到了,返回次数
}

/*run_query返回值的使用*/
string TextQuery::text_line(line_no line) const {
    if (line < lines_of_text.size())
        return lines_of_text[line];
    else
        throw out_of_range("line number out of range");
}

string make_plural(TextQuery::line_no ctr, const string& word, const string& ending) {
    return (ctr == 1) ? word : word + ending;
}

void print_results(const set<TextQuery::line_no>& locs, const string& sought, const TextQuery& file) {
    typedef set<TextQuery::line_no> line_nums;
    line_nums::size_type size = locs.size();
    cout << "\n" << sought << " occurs " << size << make_plural(size, " time", "s") << endl;
    line_nums::const_iterator it = locs.begin();
    for (; it != locs.end(); ++it) {
        cout << "\t(in line " << (*it) + 1 << ") " << file.text_line(*it) << endl;//输出行号和内容
    }
}

int main()
{
    ifstream infile; //infile指向我们要处理的文件
    cout << "输入查询文件放在哪里: ";
    string fileName;
    getline(cin, fileName);//获取输入的路径
    infile.open(fileName.c_str());//以输入的方式打开文件
    TextQuery tq;        //实例化对象
    tq.read_file(infile);//读取txt文件、建立map;
    while (true) {
        cout << endl << "输入要找的单词,或者输入 q 退出 : ";
        string str;
        cin >> str;//获取输入的单词
        if (!cin || str == "q")//控制主函数循环:到了文件尾或 者输入q ;退出
            break;
        set<TextQuery::line_no> locs = tq.run_query(str);
        print_results(locs, str, tq);//次数、cin字符、实例化对象tq;
    }
    return 0;
}

在这里插入图片描述
怕什么真理无穷,进一步有进一步的欢喜!

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

甜橙の学习笔记

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值