C++ Primer(第5版) 练习 12.30
练习 12.30 定义你自己版本的TextQuery和QueryResult类,并执行12.3.1节(第431页)中的runQueries函数。
环境:Linux Ubuntu(云服务器)
工具:vim
代码块
/*************************************************************************
> File Name: ex12.30.cpp
> Author:
> Mail:
> Created Time: Mon 22 Apr 2024 08:21:38 AM CST
************************************************************************/
#include<iostream>
#include<fstream>
#include<sstream>
#include<vector>
#include<map>
#include<set>
#include<memory>
using namespace std;
string make_plural(size_t ctr, string &word, const string &ending = "s"){
int size = word.size();
if(ctr <= 1){
return word;
}
else{
if(word[size-1] == 's' || word[size-1] == 'x' || (word[size-1] == 'h' && word[size-2] == 's') || (word[size-1] == 'h' && word[size-2] == 'c')){
return word + "e" + ending;
}
else if(word[size-1] == 'y' && (word[size-2] != 'a' && word[size-2] != 'e' && word[size-2] != 'i' && word[size-2] != 'o' && word[size-2] != 'u')){
word[size-1] = 'i';
return word + "e" + ending;
}
else if((word[size-3] != 'a' && word[size-3] != 'e' && word[size-3] != 'i' && word[size-3] != 'o' && word[size-3] != 'u') && (word[size-2] != 'a' && word[size-2] != 'e' && word[size-2] != 'i' && word[size-2] != 'o' && word[size-2] != 'u')){
if(word[size-1] == 'f'){
word[size-1] = 'v';
return word + ending;
}
else if(word[size-2] == 'f' && word[size-1] == 'e'){
word[size-2] = 'v';
return word + "e" + ending;
}
}
else{
return word + ending;
}
}
return word;
}
class QueryResult;
class TextQuery{
public:
using line_no = vector<string>::size_type;
TextQuery(ifstream &is);
QueryResult query(const string &s) const;
private:
shared_ptr<vector<string>> file;
map<string, shared_ptr<set<line_no>>> wm;
};
TextQuery::TextQuery(ifstream &is): file(new vector<string>){
string text;
while(getline(is, text)){
file->push_back(text);
int n = file->size() - 1;
istringstream line(text);
string word;
while(line>>word){
auto &lines = wm[word];
if(!lines){
lines.reset(new set<line_no>);
lines->insert(n);
}
}
}
}
class QueryResult{
friend ostream &print(ostream &, const QueryResult &);
public:
QueryResult(string s, shared_ptr<set<TextQuery::line_no>> p, shared_ptr<vector<string>> f): sought(s), lines(p), file(f) {}
private:
string sought;
shared_ptr<set<TextQuery::line_no>> lines;
shared_ptr<vector<string>> file;
};
QueryResult TextQuery::query(const string &sought) const{
static shared_ptr<set<line_no>> nodata(new set<line_no>);
auto loc = wm.find(sought);
if(loc == wm.end()){
return QueryResult(sought, nodata, file);
}
else{
return QueryResult(sought, loc->second, file);
}
}
ostream &print(ostream &os, const QueryResult &qr){
string na = "time";
os<<qr.sought<<" occurs "<<qr.lines->size()<<" "<<make_plural(qr.lines->size(), na)<<endl;
for(auto num : *qr.lines){
os<<"\t(line "<<num + 1<<") "<<*(qr.file->begin() + num)<<endl;
}
return os;
}
void runQueries(ifstream &infile){
TextQuery tq(infile);
while(true){
cout<<"enter word to look for, or q to quit: ";
string s;
if(!(cin>>s) || s == "q"){
break;
}
print(cout, tq.query(s))<<endl;
}
}
int main(){
ifstream file("12.27.txt");
runQueries(file);
return 0;
}