《C++ Primer》第19章 19.5节习题答案

在这个编程习题中,你被要求将QueryResult类嵌套在TextQuery类中,并应用到第12.3.2节的示例中,用于处理文本查询。你需要创建并实现QueryResult类的相关功能,如结果集操作和打印输出。
摘要由CSDN通过智能技术生成

《C++ Primer》第19章 特殊工具与技术

19.5节 嵌套类 习题答案

练习19.20:将你的QueryResult类嵌套在TextQuery中,然后重新运行12.3.2节(第435页)中使用了TextQuery的程序。

【出题思路】嵌套类的定义与使用练习。

【解答】

class TextQuery
{
public:
    class QueryResult;
    //其他成员的定义
};


class TextQuery::QueryResult
{
    friend std::ostream& print(std::ostream&, const QueryResult&);
public:
    typedef std::vector<std::string>::size_type line_no;
    typedef std::set<line_no>::const_iterator line_it;
    QueryResult(std::string s, std::shared_ptr<std::set<line_no>> p, std::shared_ptr<std::vector<std::string>> f);
    //其他成员的定义

};

TextQuery::QueryResult::QueryResult(std::string s, std::shared_ptr<std::set<line_no>> p, std::shared_ptr<std::vector<std::string>> f)
:sought(s), lines(p), file(f)
{

}

完整的示例:

#include <cstddef>
using std::size_t;

#include <string>
using std::string;

#include <iostream>
using std::cout;
using std::endl;

#ifndef MAKE_PLURAL_H
#define MAKE_PLURAL_H

// return the plural version of word if ctr is greater than 1
inline
string make_plural(size_t ctr, const string &word,
                               const string &ending)
{
    return (ctr > 1) ? word + ending : word;
}

#endif // MAKE_PLURAL_H
#ifndef PROGRAM19_20_H
#define PROGRAM19_20_H

#include <memory>
#include <string>
#include <map>
#include <set>
#include <fstream>
#include <vector>
#include <iostream>

class TextQuery
{
public:
    class QueryResult;
    using line_no = std::vector<std::string>::size_type;
    TextQuery(std::ifstream&);
    QueryResult query(const std::string&) const;
    void display_map();

private:
    std::shared_ptr<std::vector<std::string>> file;//输入文件

    std::map<std::string, std::shared_ptr<std::set<line_no>>> wm;

    static std::string cleanup_str(const std::string&);
};


class TextQuery::QueryResult
{
    friend std::ostream& print(std::ostream&, const QueryResult&);
public:
    typedef std::vector<std::string>::size_type line_no;
    typedef std::set<line_no>::const_iterator line_it;
    QueryResult(std::string s, std::shared_ptr<std::set<line_no>> p,
                std::shared_ptr<std::vector<std::string>> f);

    line_it begin() const { return lines->cbegin(); }
    line_it end() const { return lines->cend(); }
    std::shared_ptr<std::vector<std::string>> get_file() { return file; }

private:
    std::string sought;//word this query represents
    std::shared_ptr<std::set<line_no>> lines;//lines it's on
    std::shared_ptr<std::vector<std::string>> file;//input file
};


std::ostream &print(std::ostream&, const TextQuery::QueryResult&);

TextQuery::QueryResult::QueryResult(std::string s, std::shared_ptr<std::set<line_no>> p, std::shared_ptr<std::vector<std::string>> f)
:sought(s), lines(p), file(f)
{

}

#endif // PROGRAM19_20_H
#include <sstream>  //istringstream
#include "program19_20.h"
#include "make_plural.h"
#include <cstdlib> //for EXIT_FAILURE


using std::size_t;
using std::shared_ptr;
using std::istringstream;
using std::string;
using std::getline;
using std::vector;
using std::map;
using std::set;
using std::cerr;
using std::cout;
using std::cin;
using std::ostream;
using std::endl;
using std::ifstream;
using std::strlen;
using std::pair;


// read the input file and build the map of lines to line numbers
TextQuery::TextQuery(ifstream &is): file(new vector<string>)
{
    string text;
    while(getline(is, text)) // for each line in the file
    {
        file->push_back(text);// remember this line of text
        unsigned long n = file->size() - 1;// the current line number
        istringstream line(text); // separate the line into words
        string word;
        while(line >> word)
        {
            word = cleanup_str(word);
            //if word isn't already in wm, subscripting adds a new entry
            auto &lines = wm[word];//lines is a shared_ptr
            if(!lines)//that pointer is null the first time we see word
            {
                lines.reset(new set<line_no>);// allocate a new set
            }
            lines->insert(n);// insert this line number
        }
    }
}


// not covered in the book -- cleanup_str removes
// punctuation and converts all text to lowercase so that
// the queries operate in a case insensitive manner
string TextQuery::cleanup_str(const string &word)
{
    string ret;
    for(auto it = word.begin(); it != word.end(); ++it)
    {
        if(!ispunct(*it))
        {
            ret += tolower(*it);
        }
    }
    return ret;
}


TextQuery::QueryResult TextQuery::query(const string &sought) const
{
    // we'll return a pointer to this set if we don't find sought
    static shared_ptr<set<line_no>> nodata(new set<line_no>);
    //use find and not a subscript to avoid adding words to wm!
    auto loc = wm.find(cleanup_str(sought));
    if(loc == wm.end())
    {
        return TextQuery::QueryResult(sought, nodata, file);
    }
    else
    {
        return TextQuery::QueryResult(sought, loc->second, file);
    }
}


ostream &print(ostream &os, const TextQuery::QueryResult &qr)
{
    //if the word was found, print the count and all occurrences
    os << qr.sought << " occurs " << qr.lines->size() << " " << make_plural(qr.lines->size(), "time", "s") << endl;
    // print each line in which the word appeared
    for(auto num: *qr.lines)
    {
        // don't confound the user with text lines starting at 0
        os << "\t(line " << num + 1 << ") " << *(qr.file->begin() + num) << endl;
    }
    return os;
}


// debugging routine, not covered in the book
void TextQuery::display_map()
{
    auto iter = wm.cbegin(), iter_end = wm.cend();
    //for each word in the map
    for(; iter != iter_end; ++iter)
    {
        cout << "word: " << iter->first << " {";
        // fetch location vector as a const reference to avoid copying it
        auto text_locs = iter->second;
        auto loc_iter = text_locs->cbegin(), loc_iter_end = text_locs->cend();
        // print all line numbers for this word
        while(loc_iter != loc_iter_end)
        {
            cout << *loc_iter;
            if(++loc_iter != loc_iter_end)
                cout << ", ";
        }
        cout << "}\n";// end list of output this word
    }
    cout << endl; // finished printing entire map
}


void runQueries(ifstream &infile)
{
    //infile is an ifstream that is the file we want to query
    TextQuery tq(infile); // store the file and build the query map
    // iterate with the user: prompt for a word to find and print results
    while(true)
    {
        cout << "enter word to look for, or q to quit:" << endl;
        string s;
        // stop if we hit end-of-file on the input or if a 'q' is entered
        if(!(cin >> s) || s == "q")
            break;
        // run the query and print the results
        print(cout, tq.query(s)) << endl;
    }
}


int main(int argc, const char * argv[])
{
    // open the file from which user will query words
    ifstream infile;
    // open returns void, so we use the comma operator XREF(commaOp)
    // to check the state of infile after the open
    if (argc < 2 || !(infile.open(argv[1]), infile)) {
        cerr << "No input file!" << endl;
        return EXIT_FAILURE;
    }
    runQueries(infile);

    cout << "hello world===program exit " << endl;
    return 0;
}

data19_20.txt文件内容如下:

Alice Emma has long flowing red hair. 
Her Daddy says when the wind blows 
through her hair, it looks almost alive, 
like a fiery bird in flight. 
A beautiful fiery bird, he tells her, 
magical but untamed. 
"Daddy, shush, there is no such thing," 
she tells him, at the same time wanting 
him to tell her more.
Shyly, she asks, "I mean, Daddy, is there?"

设置命令行参数

运行:

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值