【C++ Primer】【学习笔记】【第十章】关联容器之:文本查询程序

textquery.h:

#include <string>
#include <vector>
#include <map>
#include <set>

class TextQuery
{
public:
    typedef std::vector<std::string>::size_type line_no;

    void read_file(std::ifstream &is)
    {
        store_file(is);
        build_map();
    }

    std::set<line_no> run_query(const std::string &) const;

    std::string text_line(line_no) const;

private:
    void store_file(std::ifstream &);

    void build_map();

    std::vector<std::string> lines_of_text;

    std::map<std::string, std::set<line_no> > word_map;
};


textquery.cpp:
#include <iostream>
#include <fstream>
#include <sstream>
#include <string>
#include <vector>
#include <map>
#include <set>
#include <utility>
#include <stdexcept>
#include "textquery.h"

void TextQuery::store_file(std::ifstream &is)
{
    std::string textline;
    while (getline(is, textline))
    {
        lines_of_text.push_back(textline);
    }
}


void TextQuery::build_map()
{
    for (line_no line_num = 0; line_num != lines_of_text.size(); ++line_num)
    {
        std::istringstream line(lines_of_text[line_num]);
        std::string word;
        while (line >> word)
        {
            word_map[word].insert(line_num);
        }
    }
}

std::set<TextQuery::line_no> TextQuery::run_query(const std::string &query_word) const
{
    std::map<std::string, std::set<line_no> >::const_iterator loc = word_map.find(query_word);
   
    if (loc == word_map.end())
    {
        return std::set<line_no>();
    }
    else
    {
        return loc->second;
    }
}

std::string TextQuery::text_line(line_no line) const
{
    if (line < lines_of_text.size())
    {
        return lines_of_text[line];
    }
    else
    {
        throw std::out_of_range("line number out of range");
    }
}

main.cpp:

#include <iostream>
#include <fstream>
#include <sstream>
#include <string>
#include <vector>
#include <map>
#include <set>
#include <utility>
#include <stdexcept>
#include "textquery.h"

using namespace std;

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

ifstream & open_file(ifstream &in, const string &file)
{
    in.close();
    in.clear();
    in.open(file.c_str());
    return in;
}

void print_results(const set<TextQuery::line_no> &locs, const string &s, const TextQuery &file)
{
    typedef set<TextQuery::line_no> line_nums;
    line_nums::size_type size = locs.size();
    cout << "\n" << s << " 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(int argc, char* argv[])
{
    ifstream infile;
    if ((argc < 2) || !open_file(infile, argv[1]))
    {
        cerr << "No input file!" << endl;
        cout << "Usage: mmgrep <filename>" << endl;
        return -1;
    }

    TextQuery tq;
    tq.read_file(infile);

    while (true)
    {
        cout << "Enter word to look for, or q to quit: ";
        string s;
        cin >> s;
        if (!cin || s == "q")
        {
            break;
        }

        set<TextQuery::line_no> locs = tq.run_query(s);
        print_results(locs, s, tq);
    }

    return 0;
}

makefile:

mmgrep: *.cpp
        g++ -g *.cpp -o mmgrep

clean:
        rm -f mmgrep
        rm -f *.o

运行效果:

[textquery]$ ./mmgrep vimtutor 
Enter word to look for, or q to quit: move
move occurs 31times 
        (line 22)      the   j   key enough times to move the cursor so that Lesson 1.1
        (line 28)    ** To move the cursor, press the h,j,k,l keys as indicated. **
        (line 37)      Now you know how to move to the next lesson.
        (line 39)   3. Using the down key, move to Lesson 1.2.
        (line 45)       move around much faster, once you get used to it.  Really!
        (line 78)   2. To fix the errors, move the cursor until it is on top of the
        (line 101)   2. To make the first line the same as the second, move the cursor on top
        (line 112)   5. When you are comfortable inserting text move to lesson 1.5.
        (line 137)   5. When you are comfortable appending text move to lesson 1.6.
        (line 157)   5. If you have quit vimtutor in step 1 restart the vimtutor and move down to
        (line 252)        move the cursor as specified.
        (line 262)   2. Type  2w  to move the cursor two words forward.
        (line 264)   3. Type  3e  to move the cursor to the end of the third word forward.
        (line 266)   4. Type  0  (zero) to move to the start of the line.
        (line 270) ---> This is just a line with words you can move around in.
        (line 311)   3. Now move to the fourth line.
        (line 341)   8. These are very useful commands.  Now move on to the Lesson 2 Summary.
        (line 363)   6. To move to the start of the line use a zero:  0
        (line 409)   5. Now move on to Lesson 3.3.
        (line 427)   4. Press <ESC> and move to the next character that needs to be changed.
        (line 488)      Type  G  to move to a line in the file. **
        (line 499)   2. Press  G  to move you to the bottom of the file.
        (line 500)      Type  gg  to move you to the start of the file.
        (line 540)   3. The cursor will move to the matching parenthesis or bracket.
        (line 542)   4. Type  %  to move the cursor to the other matching bracket.
        (line 653)   2. Press  v  and move the cursor to the fifth item below.  Notice that the
        (line 664) NOTE:  Pressing  v  starts Visual selection.  You can move the cursor around
        (line 676) NOTE:  After executing Step 2 you will see text from Lesson 5.3.  Then move
        (line 752)   5. Use  e  to move to the next incomplete word and repeat steps 3 and 4.
        (line 791)   2. Start Visual mode with  v  and move the cursor to just before "first".
        (line 799)   6. Use Visual mode to select " item.", yank it with  y , move to the end of
Enter word to look for, or q to quit: q
[textquery]$ 


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值