《c++ primer》文本查询程序和邮件处理程序
Posted I_myours
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了《c++ primer》文本查询程序和邮件处理程序相关的知识,希望对你有一定的参考价值。
记录一下,这两个例子很棒。
文本查询程序
#ifndef _TEXTQUERY_H_
#define _TEXTQUERY_H_
#include <iostream>
#include <fstream>
#include <sstream>
#include <memory>
#include <string>
#include <vector>
#include <map>
#include <set>
using line_no = std::vector<std::string>::size_type;
class TextQuery;
class QueryResult;
class QueryResult
friend class TextQuery;
friend std::ostream& print(std::ostream &os, const QueryResult &qr);
public:
QueryResult(std::string s,
std::shared_ptr<std::set<line_no>>l,
std::shared_ptr<std::vector<std::string>> f):
s_word(s),lines(l),file(f)
private:
std::string s_word;
std::shared_ptr<std::set<line_no>>lines;
std::shared_ptr<std::vector<std::string>>file;
;
class TextQuery
friend class QueryResult;
public:
TextQuery() = default;
TextQuery(std::ifstream &infile);
QueryResult query(const std::string&)const;
private:
std::shared_ptr<std::vector<std::string>>m_file;
std::map<std::string, std::shared_ptr<std::set<line_no>>>m_word_line;
;
#endif
#include "TextQuery.h"
TextQuery::TextQuery(std::ifstream &infile):m_file(new std::vector<std::string>)//make_shared<vector<string>>()
std::string line;
std::string word;
static int i = 0;
//t_file = make_shared<vector<string>>;
while(std::getline(infile,line))
i++;
m_file->push_back(line);//按行保存文本.
std::istringstream i_line(line);
while(!i_line.eof())
i_line >> word;
auto &li = m_word_line[word];
if(!li) //为了避免拷贝set行号动态分配
li.reset(new std::set<line_no>);
li->insert(i);
QueryResult TextQuery::query(const std::string& sought)const
<span style="color:#FF0000;">static std::shared_ptr<std::set<line_no>>nodata(new std::set<line_no>); </span>
auto loc = m_word_line.find(sought);
if(loc == m_word_line.end())
return QueryResult(sought, nodata, m_file);
else
return QueryResult(sought, loc->second, m_file);
std::ostream& print(std::ostream &os, const QueryResult &qr)
os << "element occurs " << qr.lines->size() << " times" << std::endl;
for(line_no i : *qr.lines)
os << " " << "(line " << i+1 << ") ";
os << *(qr.file->begin()+i)<< std::endl;
return os;
#include "TextQuery.h"
int main(int argc, char *argv[])
std::ifstream is(argv[1]);
TextQuery essay(is);
std::string word;
std::cout << "input search word('q' is quit):";
while(std::cin >> word && word != "q")
std::cout << std::endl;
print(std::cout, essay.query(word));
std::cout << "input search word('q' is quit):";
注意!:
1.对于可能置于头文件的中的代码,在使用标准库名字时要加上std::
头文件不应该使用using声明,
位于头文件代码一般来说不应该使用using声明,因为头文件的内容会拷贝到每个引用它的文件中去,如果某个头文件有using 声明,那么引用它的每个
头文件都会有using声明,对于某些程序来说,由于不经意间包含了某些名字,可能会出现名字冲突
2.查询时千万不能用map的[ ]操作符,若不存在的话会生成,那么查询就没意义了,所以应该query定义成const成员函数,不允许添加,避免[ ]。可以使用find
3.代码中的static shared_ptr<set<string>>nodata(new set<string>), static成员无论调用多少次,只在第一次时执行初始化,很好的方法。
如果new的话每次用都会new。
邮件处理程序
/*
* Message类:
* 消息类,可以存储或删除
* 一个Message可以属于多个Floder
*/
#ifndef _MESSAGE_H_
#define _MESSAGE_H_
#include <iostream>
#include <set>
#include <memory>
#include <string>
#include "Folder.h"
class Message;
class Folder;
class Message
friend void swap(Message &lhs, Message &rhs);
friend std::istream& read(std::istream &in, Message &msg);
friend std::ostream& print(std::ostream &os, Message &msg);
friend class Folder;
public:
//隐式初始化为空,且避免隐式转换
explicit Message(const std::string &s = " "):
contents(s)
Message(const Message &msg); //赋值形参,add
Message(Message &&msg); //移动拷贝
Message& operator=(const Message &msg);//删除左值message,赋值右值add 三个拷贝控制成员都有交叉操作,所以定义private
Message& operator=(Message &&msg); //移动赋值
~Message(); //删除message 工具函数来处理,避免代码重复。提高效率
//两个成员函数,从floders保存和删除message
void save(Folder &f);
void remove(Folder &f);
private:
std::string contents; //message text
std::set<Folder*>folders; //message from floders 每个message包含多个指向floders的指针,指明它属于哪些floders
void add_to_Folders(const Message &msg);
void remove_from_Folders();
;
#endif
#include "Message.h"
void Message::save(Folder &f)
folders.insert(&f); //message保存到flod,message的floder添加f
f.addMsg(this); //floder里面要add message
void Message::remove(Folder &f)
folders.erase(&f);
f.rmMsg(this);
//添加信息message,要对于每个包含message的添加message
void Message::add_to_Folders(const Message &msg)
for(auto &f : msg.folders)
f->addMsg(this);
void Message::remove_from_Folders()
//自己保存的每个floder删除自己
for(auto &f : folders)
f->rmMsg(this);
//拷贝构造函数
Message::Message(const Message &msg):contents(msg.contents),folders(msg.folders)
add_to_Folders(msg);
//赋值操作符
Message& Message::operator=(const Message &msg)
remove_from_Folders();
contents = msg.contents;
folders = msg.folders;
add_to_Folders(msg);
return *this;
Message::~Message()
remove_from_Folders();
std::istream& read(std::istream &in, Message &msg)
in >> msg.contents;
return in;
std::ostream& print(std::ostream &os, Message &msg)
os << "Message:" << msg.contents << "\\n";
os << "Folders:";
for(auto f : msg.folders)
os << f->fold_name << " ";
os << "\\n";
return os;
void swap(Message &lhs, Message &rhs)
using std::swap;
for(auto f : lhs.folders)
f->rmMsg(&lhs);
for(auto f : rhs.folders)
f->rmMsg(&rhs);
swap(lhs.folders, rhs.folders);
swap(lhs.contents, rhs.contents);
for(auto f : lhs.folders)
f->addMsg(&lhs);
for(auto f : rhs.folders)
f->addMsg(&rhs);
Message::Message(Message &&msg) //这两个函数可以有很多共有操作,可以换成一个私密函数来简化
contents = std::move(msg.contents);
folders = std::move(msg.folders);
for(auto f : folders)
f->rmMsg(&msg);
f->addMsg(this);
msg.folders.clear();
Message& Message::operator=(Message &&msg)
if(this != &msg)
remove_from_Folders();
contents = std::move(msg.contents);
folders = std::move(msg.folders);
for(auto f : folders)
f->rmMsg(&msg);
f->addMsg(this);
msg.folders.clear();
return *this;
Folder
#ifndef _FOLDER_H_
#define _FOLDER_H_
#include <iostream>
#include <set>
#include <string>
class Folder;
class Message;
class Folder
friend std::istream& read(std::istream &in, Message &msg);
friend std::ostream& print(std::ostream &os, Message &msg);
friend class Message;
public:
Folder(const std::string &s = " "):
fold_name(s)
~Folder()
void addMsg(Message *msg); //删除message
void rmMsg(Message *msg); //添加message
private:
std::set<Message*>_fold; //保存message的flod
std::string fold_name;
;
#endif
#ifndef _FOLDER_H_
#define _FOLDER_H_
#include <iostream>
#include <set>
#include <string>
class Folder;
class Message;
class Folder
friend std::istream& read(std::istream &in, Message &msg);
friend std::ostream& print(std::ostream &os, Message &msg);
friend class Message;
public:
Folder(const std::string &s = " "):
fold_name(s)
~Folder()
void addMsg(Message *msg); //删除message
void rmMsg(Message *msg); //添加message
private:
std::set<Message*>_fold; //保存message的flod
std::string fold_name;
;
#endif
main函数
#include "Folder.h"
#include "Message.h"
int main()
Folder file1("mail1");
Folder file2("mail2");
Message m1;
Message m2;
read(std::cin, m1);
m1.save(file1);
m1.save(file2);
read(std::cin, m2);
m2.save(file1);
m2.save(file2);
print(std::cout, m1);
print(std::cout, m2);
swap(m1,m2);
print(std::cout, m1);
print(std::cout, m2);
!注意:
在类内如果有多个函数重复几个操作,我们可以把这些操作定义在private,作为工具函数来调用。
如果要避免隐式转换,我们应该显示的写出关键字explicit
函数名字和变量名字起的要符合实际作用
析构函数如果使用默认记得加上=defalut,自己定义要加
思路清晰在开始写代码,尽量避免代码重复。
新添加的移动操作没有在末尾添加noexcept,因为在移动操作内部部分操作可能会抛出异常。
以上是关于《c++ primer》文本查询程序和邮件处理程序的主要内容,如果未能解决你的问题,请参考以下文章
《C++ Primer》 chapter 15 TextQuery