C++自学笔记_文本查询程序_《C++ Primer》

《C++ Primer》 第10章结束,用一个文本查询程序结束本章 :)

 

程序将读取用户指定的任意文本文件,然后允许用户从该文件中查找单词。查询的结果是该单词出现的次数,并列出每次出现所在的行。如果某单词在同一行

中多次出现,程序将只显示该行一次。行号按照升序显示。

 

程序支持以下任务:

  · 它必须允许用户指明要处理的文件的名字。程序将存储该文件的内容,以便输出每个单词所在的原始行。

  · 它必须将每一行分解为各个单词,并记录每个单词所在的行。在输出行号时,应保证以升序输出,并且不重复。

  · 对特定单词的查询将返回出现该单词的所有行的行号。

  · 输出某单词所在的行文本时,程序必须能够根据给定的行号从输入文件中获取相应的行。

 

假定要查询的文件路径为  F:\C++ Primer_TXT\TextQuery.txt

TextQuery.txt:

 

Code:
#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;
    map<string,set<line_no> >word_map;
};

/*存储输入文件*/
void TextQuery::store_file(ifstream &is){
    string textline;
    while(getline(is,textline)){
        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);
        }
    }
}

/*支持查询*/
set<TextQuery::line_no> TextQuery::run_query(const string &query_word) const{
    map<string,set<line_no> >::const_iterator loc=word_map.find(query_word);
    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(line "<<(*it)+1<<") "<<file.text_line(*it)<<endl;
    }
}

int main()
{
    ifstream infile;
    cout<<"enter a file path to query: ";
    string fileName;
    getline(cin,fileName);
    infile.open(fileName.c_str());
    TextQuery tq;
    tq.read_file(infile);
    while(true){
        cout<<endl<<"enter a word to look for,or q to quit: ";
        string str;
        cin>>str;
        if(!cin||str=="q")
            break;
        set<TextQuery::line_no> locs=tq.run_query(str);
        print_results(locs,str,tq);
    }
    return 0;
}

 

posted @ 2014-12-15 15:15  tinylcy  阅读(540)  评论(0编辑  收藏  举报