C++primer练习12.27-12.32

练习12.27

TextQuery和QueryResult类只使用了我们已经介绍过的语言和标准库特性。

main.cpp

#include<iostream> 
#include <string>
#include <vector>
#include <fstream>
#include "QueryResult.h"
#include "TextQuery.h"

using std::ostream;
using std::cout;
using std::endl;

using std::cin;
ostream &print(ostream & os, const QueryResult &qr)
{
    // if the word was found, print the count and all occurrences
    os << qr.sword << " occurs " << qr.lines->size() << " "
       << make_plural(qr.lines->size(), "time", "s") << endl;

    // print each line in which the word appeared
    // for every element in the set 
    for (set<TextQuery::line_no>::const_iterator num = qr.lines->begin();
                num != qr.lines->end(); ++num) 
        // don't confound the user with text lines starting at 0
        os << "\t(line " << *num + 1 << ") " 
           << *(qr.paragraph->begin() + *num) << endl;
    return os;
}


void runQueries(std::ifstream&infile)
{
    TextQuery tq(infile);
    while(true)
    {
        cout<<"enter word to look for ,or to quit: ";
        string s;
        if(!(cin>>s)||s=="q")break;
        print(cout,tq.query(s));
    }
}

int main()
{
    ifstream in("number.txt");
    runQueries(in);
    
}

TextQuery.h

#ifndef TEXTQUERY
#define TEXTQUERY

#include <memory>
#include <string>
#include <vector>
#include <iostream>
#include <map>
#include <fstream>
#include <sstream>
#include "QueryResult.h"
#include <set>

using std::string;
using std::vector;
using std::map;
using std::ifstream;
using std::set;
using std::shared_ptr;



class TextQuery{
    public :
        typedef vector<string>::size_type line_no;
        typedef shared_ptr<set<line_no>> linetype;
        friend class QueryResult;
        shared_ptr<vector<string>> text;
        map<string,shared_ptr<set<line_no>>> record;
        TextQuery(ifstream &f);
        QueryResult query(const string& s);
        string cleanup_str(const string &word);
    private :    
        
};

string TextQuery::cleanup_str(const string &word)
{
    string ret;
    for (string::const_iterator it = word.begin(); 
                it != word.end(); ++it) {
        if (!ispunct(*it))
            ret += tolower(*it);
    }
    return ret;
}


using std::stringstream;
TextQuery::TextQuery(ifstream &f):text(new vector<string>)
{
    string s;
    while(getline(f,s))
    {
    text->push_back(s);
    int n = text->size() - 1;
    string word;
    std::istringstream eword(s);
    
    while(eword>>word)
    {
    word=cleanup_str(word);
    linetype &lines = record[word];
     if (!lines)
      lines.reset(new set<line_no>);
      lines->insert(n);
    
    
    }}
}

QueryResult TextQuery::query(const string &s)
{
    static linetype nodata;
    map<string,shared_ptr<set<line_no>>>::const_iterator pos=record.find(s);
        if (pos == record.end()) 
        return QueryResult(s, nodata, text);  // not found
    else 
        return QueryResult(s, pos->second, text);


}

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

#endif

QueryResult.h

#ifndef QUERYRESULT
#define QUERYRESULT

#include <string>
#include <vector>
#include <stdlib.h> 
#include <map>
#include <set>
#include <memory>

using std::string;
using std::vector;
using std::map;
using std::set;
using std::shared_ptr;
class TextQuery;

class QueryResult{
    public:
        typedef vector<string>::size_type line_no;
        friend class TextQuery;
        QueryResult(string s,shared_ptr<set<line_no>> p,shared_ptr<vector<string>> text):sword(s),lines(p),paragraph(text){}
        
        string sword;
        shared_ptr<set<line_no>> lines;
        shared_ptr<vector<string>> paragraph;
                    
    private:
    
    
    
};



#endif

print函数和TextQuery的构造抄了书上的,但原来自己码的没问题,只是在打开file的txt码成text,搞得程序一直崩,我就直接抄了,后来还是崩,一行行看才发现哭死

练习12.28

编写程序实现文本查询,不使用类,用标准库容器

#include <sstream>
#include <fstream>
#include <iostream>
#include <vector>
#include <string>
#include <map>
#include <set>
#include <ctype.h>
#include <memory>

using std::map;
using std::set;
using std::string;
using std::vector;
using std::ifstream;
using std::ostream;
using std::shared_ptr;
using std::cout;
using std::endl;
using line_no=vector<string>::size_type;

map<string,set<line_no>> lines;
vector<string> file;


string cleanup_str(string s)
{
    string ret;
    for(string::const_iterator it=s.begin();it!=s.end();++it)
    {
        if(!ispunct(*it))
        ret+=tolower(*it);
    }
    return ret;
}

void storage(ifstream& f)
{
    string line;
    while(getline(f,line))
    {
        file.push_back(line);
        int n=file.size();
        std::istringstream eword(line);
        string word;
        while(eword>>word)
        {
            word=cleanup_str(word);
            
             lines[word].insert(n);
        }
    }
    
}

void search(const string&s)
{
    cout<<s<<" occurs ";
    if(&lines[s]){
    cout<<lines[s].size()<<" times "<<endl;
    for(auto d:lines[s])
    cout<<"\t(line : "<<d<<"  "<<file[d-1]<<endl;

}
    else 
    cout<<" 0 "<<" time "<<endl;
    
}


int main()
{
    ifstream in("number.txt");
    storage(in);
    while(true)
    {
        cout<<"enter word to look for ,or q to quit : "<<endl;
        string s;
        if(!(std::cin>>s)||s=="q")break;
        search(s);
    }
    return 0;
}

练习12.29

我们曾经用do while循环来编写管理用户交互的循环。用do while重写本节程序。解释你倾向哪个版本

#include <sstream>
#include <fstream>
#include <iostream>
#include <vector>
#include <string>
#include <map>
#include <set>
#include <ctype.h>
#include <memory>

using std::map;
using std::set;
using std::string;
using std::vector;
using std::ifstream;
using std::ostream;
using std::shared_ptr;
using std::cout;
using std::endl;
using line_no=vector<string>::size_type;

map<string,set<line_no>> lines;
vector<string> file;


string cleanup_str(string s)
{
    string ret;
    for(string::const_iterator it=s.begin();it!=s.end();++it)
    {
        if(!ispunct(*it))
        ret+=tolower(*it);
    }
    return ret;
}

void storage(ifstream& f)
{
    string line;
    while(getline(f,line))
    {
        file.push_back(line);
        int n=file.size();
        std::istringstream eword(line);
        string word;
        while(eword>>word)
        {
            word=cleanup_str(word);
            
             lines[word].insert(n);
        }
    }
    
}

void search(const string&s)
{
    cout<<s<<" occurs ";
    if(&lines[s]){
    cout<<lines[s].size()<<" times "<<endl;
    for(auto d:lines[s])
    cout<<"\t(line : "<<d<<"  "<<file[d-1]<<endl;

}
    else 
    cout<<" 0 "<<" time "<<endl;
    
}


int main()
{
    ifstream in("number.txt");
    storage(in);
    do
    {
        cout<<"enter word to look for ,or q to quit : "<<endl;
        string s;
        if(!(std::cin>>s)||s=="q")break;
        search(s);
    }while(true);
    return 0;
}

用类更方便在大型程序里处理数据,也便于后续改善,用vector等容器,逻辑偏过程,不易于开发大程序,不过写短片代码倒挺上手,受了c的影响,还是得习惯用用类

练习12.30

定义你自己版本的TextQuery和QueryResult类

::如12.27

练习12.31

如果用vector代替set保存行号,会有什么差别?哪种方法更好?为什么?

::set防止重复,避免同一行出现而重复记录

练习12.32

重写TextQuery和QueryResult类,用StrBlob代替vector<string>保存输入文件

class QueryResult{
    public:
        typedef vector<string>::size_type line_no;
        friend class TextQuery;
        QueryResult(string s,shared_ptr<set<line_no>> p,shared_ptr<vector<string>> text):sword(s),lines(p),paragraph(text){}
        
        string sword;
        shared_ptr<set<line_no>> lines;
        shared_ptr<StrBlob> paragraph;
                    
    private:
    
    
    
};
class TextQuery{
    public :
        typedef vector<string>::size_type line_no;
        typedef shared_ptr<set<line_no>> linetype;
        friend class QueryResult;
        friend class StrBlob;
        shared_ptr<StrBlob> text;
        map<string,shared_ptr<set<line_no>>> record;
        TextQuery(ifstream &f);
        QueryResult query(const string& s);
        string cleanup_str(const string &word);
    private :    
        
};    

 

posted @ 2022-08-11 16:17  yddl  阅读(27)  评论(0编辑  收藏  举报