当时刚学C++的时候买了这本书,一开始前面看的一知半解,索性就先缓缓,等学完学校的C++课程(中途自己也写了不少c++的代码),一段时间之后又拿起这本书去看,感觉还是挺有滋味的,这本书对我印象中的C++做了很大的扩展,个人认为这本书不太适合刚学C++就去看,而是写了一定的代码,对C++有一个大体的了解之后再去看会很有味道。在看书的过程中自己也写了上面的课后练习题,现在整理一下,也跟大家分享一下,下面是9~12 15~16章的课后题编程题的答案
(第八章之前的都没保存/(ㄒoㄒ)/~~):
当时保存的时候是按节保存的,比如 练习9.3、练习9.4 练习9.5、练习9.6 是在9.2.1节练习里面的题
9.2.1节练习:
<span style="font-size:18px;">#include <iostream> #include <vector> std::vector<int>::iterator fun(std::vector<int>::iterator isb,std::vector<int>::iterator ise,int y){ while(isb<ise) if(*(isb)==y) return isb; else isb++; return ise; } int main() { std::vector<int> s={1,2,3}; std::vector<int>::iterator is=s.begin(); //if(fun(is,s.end(),2)) cout<<"OK"<<endl; is=fun(is,s.end(),2); std::cout<<*is<<std::endl; while(std::cout<<*is<<"#" && (is++)<s.end()); return 0; } </span>
9.3.1节练习:
#include <iostream> #include <vector> #include <list> #include <deque> int main() { std::string temp; std::deque<std::string>dq; for(int i=1;i<=3;++i){ std::cin>>temp; dq.push_front(temp); } auto x=dq.begin(); //std::deque<std::string>::iterator x; while(x < dq.end() && std::cout<<" "<<*(x++)); std::cout<<std::endl; std::list<std::string>l; for(int i=1;i<=3;++i){ std::cin>>temp; l.push_front(temp); } auto y=l.begin(); while(y!=l.end() && std::cout<<" "<<*(y++)); //list中无 > <操作 使用!=代替 std::cout<<std::endl; return 0; }
9.3.3节练习:
#include <iostream> #include <vector> #include <list> #include <deque> int main() { int ia[]={0,1,1,2,3,5,8,13,21,55,89}; std::vector<int > vec={0,1,1,2,3,5,8,13,21,55,89}; std::list<int > lis={0,1,1,2,3,5,8,13,21,55,89}; auto i=vec.begin(); while(i!=vec.end()) if(*i % 2)i=vec.erase(i); else i++; auto j=lis.begin(); while(j!=lis.end()) if(*j % 2==0)j=lis.erase(j); else j++; for(auto x:vec) std::cout<<" "<<x; std::cout<<std::endl; for(auto x:lis) std::cout<<" "<<x; std::cout<<std::endl; return 0; }
9.5.3节练习:
练习9.47:
#include <iostream> #include <algorithm> int main() { std::string temp("ab2c3d7R4"); std::string digit("0123456789"); std::string word; for(int i=0;i<24;++i){ word+=(char)('a'+i); word+=(char)('A'+i); } std::string::size_type pos=0; while((pos=temp.find_first_of(word,pos))!=std::string::npos) std::cout<<temp[pos++];std::cout<<std::endl; pos=0; while((pos=temp.find_first_of(digit,pos))!=std::string::npos) std::cout<<temp[pos++];std::cout<<std::endl; pos=0; while((pos=temp.find_first_not_of(digit,pos))!=std::string::npos) std::cout<<temp[pos++];std::cout<<std::endl; pos=0; while((pos=temp.find_first_not_of(word,pos))!=std::string::npos) std::cout<<temp[pos++];std::cout<<std::endl; return 0; }
练习9.49:
#include <iostream> int main() { std::string temp("bdfghijklpqty"); std::string s; while(std::cin>>s){ std::string::size_type pos=0; while((pos=s.find_first_not_of(temp,pos))!=std::string::npos)std::cout<<s[pos++]; std::cout<<std::endl; } return 0; }
练习9.50:
#include <iostream> #include <vector> int main() { std::vector<std::string > vec={"1","2","3","4","5"}; int sum1=0; for(auto x:vec) sum1+=stoi(x); //codeblock(12.11)报错,vs2012也报,本汪编译器不支持 std::cout<<sum1<<std::endl; double sum2=0.0; for(auto x:vec) sum2+=stod(x); std::cout<<sum2<<std::endl; return 0; }
练习9.51:
#include <iostream> class A{ public : A(const std::string s="10/12/1994"){ std::string sign=" ,/"; auto pos=s.find_first_of(sign); month=s.substr(0,pos); day=s.substr(pos+1,s.find_first_of(sign,pos+1)-pos-1); year=s.substr(s.find_last_of(sign)+1); } void print(){ std::cout<<month<<" "<<day<<" "<<year<<std::endl; } private: std::string year,day,month; }; int main() { A a; a.print(); A b("jan 1/1990"); b.print(); return 0; } /* #include <iostream> #include <vector> #include <list> #include <deque> #include <algorithm> #include <numeric> #include <cstring> using namespace std; int main() { int a1[]={1,2,3,4,5,6}; int a2[sizeof(a1)/sizeof(a1)]; auto ret=copy(begin(a1),end(a1),begin(a2)); return 0; } */
练习10.1:
#include <iostream> #include <vector> #include <list> #include <deque> #include <algorithm> using namespace std; int main() { std::vector<int > vec={1,2,3,4,5,6,7,12,3,4,6,7,3,6,9,2,6,3,3,3,3,3,3}; std::cout<<count(vec.begin(),vec.end(),3)<<std::endl; std::list<std::string > lis={"q","e","sdg","zvgs","123g","545","qwe","uyt","qwe"}; std::cout<<count(lis.begin(),lis.end(),"qwe")<<std::endl; return 0; }
10.2.1节练习:
/* #include <iostream> #include <vector> #include <list> #include <deque> #include <algorithm> using namespace std; class A{ public : A(const string s="1/1/1990"):month("jan"),day("1"),year("1994"){ string sign=" ,/"; auto pos=s.find_first_of(sign); month=s.substr(0,pos); day=s.substr(pos+1,s.find_first_of(sign,pos+1)-pos-1); year=s.substr(s.find_last_of(sign)+1); } void print(){ cout<<month<<" "<<day<<" "<<year<<endl; } private: string year,day,month; }; int main() { A a(); a.print(); // A b("1/1/1990"); // b.print(); return 0; } */ #include <iostream> #include <vector> #include <algorithm> #include <cstring> int main() { std::vector<int > vec={1,2,3,4,5,6,7,8,9}; std::cout<<accumulate(vec.cbegin(),vec.cend(),0)<<std::endl; std::vector<std::string > vec_str={"a","b","c","d"}; std::cout<<accumulate(vec_str.cbegin(),vec_str.cend(),std::string(""))<<std::endl; //accumulate(,,"");错误 const char* 没有定义+操作 //accumulate(,,"hello"); 最后结果是 helloxxxx char *s=(char *)malloc(10*sizeof(char)); char s1[]="heheda",s2[]="heheda"; std::cout<<std::equal(s1,s1+strlen(s1),s2)<<std::endl; return 0; }
10.2.2节练习:
#include <iostream> #include <vector> #include <list> #include <algorithm> #include <numeric> int main() { //10.6 int num[]={1,2,3,4,5,6}; std::fill_n(std::begin(num),std::end(num)-std::begin(num),0); for(auto x:num) std::cout<<x<<" "; std::cout<<std::endl; //10.7 a std::vector<int > vec; std::list<int >lst; int i; while(std::cin>>i) lst.push_back(i); std::copy(lst.cbegin(),lst.cend(),back_inserter(vec)); //vec未申请空间,所以使用插入迭代器 for(auto x:vec) std::cout<<x<<" "; std::cout<<std::endl; //10.7 b std::vector<int > vecc; vecc.reserve(10); //虽然分配了内存 但size()=0 vecc.begin()==vecc.end() capacity()=10 std::fill_n(vecc.begin(),10,0); for(auto x:vecc) std::cout<<x<<" "; std::cout<<std::endl; return 0; }
10.2.3节练习:
#include <iostream> #include <vector> #include <list> #include <algorithm> #include <numeric> void elimDups(std::vector<std::string > &vec){ std::sort(vec.begin(),vec.end()); auto uni=std::unique(vec.begin(),vec.end()); //把重复单词忘末尾放,返回指向不重复范围的后一个迭代器 vec.erase(uni,vec.end()); for(auto x:vec) std::cout<<x<<" "; std::cout<<std::endl; } int main() { std::vector<std::string> vec={"the","quick","red","fox","jumps","over","the","slow","red","turtle"}; elimDups(vec); return 0; } // the quick red fox jumps over the slow red turtle
10.3.1节练习:
#include <iostream> #include <vector> #include <list> #include <algorithm> #include <numeric> void elimDups(std::vector<std::string > &vec){ std::sort(vec.begin(),vec.end()); auto uni=std::unique(vec.begin(),vec.end()); //把重复单词忘末尾放,返回指向不重复范围的后一个迭代器 vec.erase(uni,vec.end()); for(auto x:vec) std::cout<<x<<" "; std::cout<<std::endl; } bool isShortter(std::string a,std::string b){ return a.size()<b.size(); } bool islessfive(const std::string &a){ return a.length()<5; } int main() { std::vector<std::string> vec={"the","quick","red","fox","jumps","over","the","slow","red","turtle"}; elimDups(vec); std::stable_sort(vec.begin(),vec.end(),isShortter); for(auto x:vec) std::cout<<x<<" "; std::cout<<std::endl; auto iter=partition(vec.begin(),vec.end(),islessfive); while(iter!=vec.end())std::cout<<*iter++<<" "; std::cout<<std::endl; return 0; } // the quick red fox jumps over the slow red turtle
10.3.2节练习:
练习10.16:
#include <iostream> #include <vector> #include <algorithm> void elimDups(std::vector<std::string > &vec){ std::sort(vec.begin(),vec.end()); auto uni=std::unique(vec.begin(),vec.end()); //把重复单词忘末尾放,返回指向不重复范围的后一个迭代器 vec.erase(uni,vec.end()); std::cout<<"after unique_sort and erase :"<<std::endl; for(auto x:vec) std::cout<<x<<" "; std::cout<<std::endl; } int main() { //10.15 int x,y; std::cin>>x>>y; auto fun2=[x](const int y){return x+y;}; std::cout<<fun2(y)<<std::endl; //10.16 std::vector<std::string> vec={"the","quick","red","fox","jumps","over","the","slow","red","turtle"}; elimDups(vec); std::stable_sort(vec.begin(),vec.end(),[](const std::string &a,const std::string &b){return a.size()<b.size();}); std::cout<<"after stable_sort:"<<std::endl; for(auto x:vec) std::cout<<x<<" "; std::cout<<std::endl; int n; std::cin>>n; auto iter=find_if(vec.begin(),vec.end(), [n](const std::string &s){ return s.size()>=n; }); auto count=vec.end()-iter; for_each(iter,vec.end(),[](const std::string &s){std::cout<<s<<" ";}); std::cout<<std::endl; return 0; }
练习10.18:
#include <iostream> #include <vector> #include <algorithm> void elimDups(std::vector<std::string > &vec){ std::sort(vec.begin(),vec.end()); auto uni=std::unique(vec.begin(),vec.end()); //把重复单词忘末尾放,返回指向不重复范围的后一个迭代器 vec.erase(uni,vec.end()); std::cout<<"after unique_sort and erase :"<<std::endl; for(auto x:vec) std::cout<<x<<" "; std::cout<<std::endl; } int main() { std::vector<std::string> vec={"the","quick","red","fox","jumps","over","the","slow","red","turtle"}; elimDups(vec); stable_sort(vec.begin(),vec.end(),[](const std::string &a,const std::string &b){return a.size()<b.size();}); std::cout<<"after stable_sort:"<<std::endl; for(auto x:vec) std::cout<<x<<" "; std::cout<<std::endl; int n; std::cin>>n; auto iter=partition(vec.begin(),vec.end(), [n](const std::string &s){ return s.size()<n; }); auto count=vec.end()-iter; for_each(iter,vec.end(),[](const std::string &s){std::cout<<s<<" ";}); std::cout<<std::endl; return 0; }
10.3.3节练习:
#include <iostream> #include <vector> #include <algorithm> int main() { std::vector<std::string> vec={"the","quick","red","fox","jumps","over","the","slow","red","turtle"}; auto x=count_if(vec.begin(),vec.end(),[](const std::string &s){ return s.size()>=6;}); std::cout<<x<<std::endl; int y=0; auto def=[=]()mutable{ if(y==0) return true; else{ --y; return false;} }; return 0; }
10.3.4节练习:
#include <iostream> #include <vector> #include <functional> #include <algorithm> using namespace std::placeholders; // bind_n操作 bool check_size(const int &x,std::string::size_type sz){return x>=sz;} int main() { std::vector<int > vec={1,3,6,8,0,3,5,12,4,2}; std::string s="woqu"; auto f=bind(check_size,_1,s.size()); for(auto x:vec) if(f(x)){ std::cout<<x<<std::endl; break; } return 0; }
10.4.1节练习:
#include <iostream> #include <list> #include <vector> #include <functional> #include <algorithm> int main() { //10.27 std::list<int > lst={1,2,2,2,2,2,2,2,6,8}; std::list<int > lst1; unique_copy(lst.begin(),lst.end(),back_inserter(lst1)); std::cout<<"old array:"; for_each(lst.begin(),lst.end(),[](const int &x){std::cout<<x<<" ";}); std::cout<<std::endl; std::cout<<"new array:"; for_each(lst1.begin(),lst1.end(),[](const int &x){std::cout<<x<<" ";}); std::cout<<std::endl; //10.28 //其中front_inserter报错 ?inserter 复制失败 std::vector <int > vec={1,2,3,4,5,6,7,8,9}; std::vector <int > front_vec,back_vec,rand_vec; auto iter=vec.begin(); //copy(vec.begin(),vec.end(),front_inserter(front_vec)); copy(vec.begin(),vec.end(),back_inserter(back_vec)); copy(vec.begin(),vec.end(),inserter(vec,iter)); // std::cout<<"front:"; //for_each(front_vec.begin(),front_vec.end(),[](const int &x){std::cout<<x<<" ";}); std::cout<<std::endl; std::cout<<"back:"; for_each(back_vec.begin(),back_vec.end(),[](const int &x){std::cout<<x<<" ";}); std::cout<<std::endl; std::cout<<"rand:"; for_each(rand_vec.begin(),rand_vec.end(),[](const int &x){std::cout<<x<<" ";}); std::cout<<std::endl; return 0; }
10.4.2节练习:
#include <iostream> #include <vector> #include <iterator> #include <fstream> #include <algorithm> //10.33 void fun(const std::string &inf_file,const std::string &outf1_file,const std::string &outf2_file){ std::ifstream inf; inf.open(inf_file); std::istream_iterator<int > inf_iter(inf),eof; std::ofstream outf1; outf1.open(outf1_file); std::ofstream outf2; outf2.open(outf2_file); std::ostream_iterator<int > outf1_iter(outf1),outf2_iter(outf2); while(inf_iter!=eof){ if((*inf_iter)%2) outf1<<*inf_iter; else outf2<<*inf_iter; inf_iter++; } std::cout<<"从文件\""<<inf_file<<"\"中读取数字,奇数已存入\""<<outf1_file<<"\"中,偶数已存入\""<<outf2_file<<"\"中"<<std::endl; inf.close(); outf1.close(); outf2.close(); } int main() { //10.29 std::ifstream inf; inf.open("test.txt"); std::istream_iterator<std::string > in_iter(inf); //in_ter 从文件流inf中读取类型为std::string的值 std::istream_iterator<std::string > eof; //文件结束位置 std::vector<std::string> vec(in_iter,eof); //把文件的字符串读入vec中 auto iter=vec.begin(); while(iter!=vec.end()) std::cout<<*iter++<<" "; std::cout<<std::endl; inf.close(); //10.30 std::istream_iterator<int > in(std::cin); //in从输入流cin中读取类型为int的值 std::istream_iterator<int > eof2; //输入流结束位置 std::vector<int > vec2(in,eof2); //输入的数据读入vec2 sort(vec2.begin(),vec2.end()); //排序 std::ostream_iterator<int > out(std::cout," "); //把类型为int的值写到输出流out中,每个值后加空格 copy(vec2.begin(),vec2.end(),out);//vec2的值读出到out中 std::cout<<std::endl; std::ostream_iterator<int > out2(std::cout," "); unique_copy(vec2.begin(),vec2.end(),out2); //不重复的复制 std::cout<<std::endl; //10.33 fun("num_in.txt","num_out1.txt","num_out2.txt"); return 0; }
10.4.3节练习:
#include <iostream> #include <vector> #include <iterator> #include <algorithm> #include <list> int main() { //10.34 10.35 std::vector <int > vec={1,2,3,4,5,6,7,8,9}; std::vector<int >::reverse_iterator reiter=vec.rbegin(); //反向迭代器 while(reiter!=vec.rend()) std::cout<<*reiter++<<" "; std::cout<<std::endl; std::vector<int >::iterator iter=vec.begin(); //普通迭代器 while(iter!=vec.end()) std::cout<<*iter++<<" "; std::cout<<std::endl; //10.36 std::list<int > lis={1,2,3,0,6,4,0,1,3,2}; //查找最后一个0,返回其迭代器 std::list<int >::reverse_iterator lis_reiter=find(lis.rbegin(),lis.rend(),0); std::cout<<*lis_reiter<<std::endl; //10.37 std::vector <int > vec2={1,2,3,4,5,6,7,8,9,10}; // 取其中 3~7 的位置复制给std::list std::list <int> lis2; auto vec2_iter=vec2.begin(); copy(vec2_iter+2,vec2_iter+7,back_inserter(lis2));//后插迭代器实现 for(auto x:lis2) std::cout<<x<<" "; std::cout<<std::endl; return 0; }
11.1.1节练习:
#include <iostream> #include <vector> #include <algorithm> #include <map> //algorithm提供的string转换字母大小写函数写法 std::string fun(std::string &s){ transform(s.begin(),s.end(),s.begin(), ::tolower); std::string s2; for(auto x:s) if(islower(x)) s2+=x; //去标点 return s2; } int main() { std::map<std::string ,size_t > m; std::string word; while(std::cin>>word && word!="end") m[fun(word)]++; for(const auto &x:m) std::cout<<x.first<<" : "<<x.second<<std::endl; return 0; }
11.2.1节练习:
#include <iostream> #include <vector> #include <algorithm> #include <map> int main() { std::map<std::string ,std::vector<std::string > > name; std::string first_name,last_name; while(std::cin>>first_name>>last_name && first_name!="end") (name[first_name]).push_back(last_name); for(auto x:name){ std::cout<<x.first<<": "<<std::endl; for(auto y:x.second) std::cout<<y<<" "; std::cout<<std::endl; } return 0; } /* 李 胜 李 冰冰 李 连杰 刘 韶 刘 氓 刘 星 刘 亦菲 张 三丰 张 天泽 张 晓红 end e */
11.2.3节练习~练习11.12、练习11.13:
#include <iostream> #include <vector> #include <algorithm> #include <utility> #include <map> int main() { //11.12 11.13 std::vector <std::pair<std::string ,int> > vec1,vec2,vec3; std::pair<std::string ,int> pa; while(std::cin>>pa.first>>pa.second){ vec1.push_back({pa.first,pa.second}); vec2.push_back(std::pair<std::string,int>(pa.first,pa.second)); vec3.push_back(pa); } for(auto x:vec1) std::cout<<x.first<<" "<<x.second<<std::endl; return 0; }
练习11.14:
#include <iostream> #include <vector> #include <algorithm> #include <utility> //pair #include <map> int main() { //11.14 std::map<std::string ,std::vector<std::pair<std::string,std::string> > > name; std::string first_name; std::pair<std::string,std::string> last_name; while(std::cin>>first_name>>last_name.first>>last_name.second && first_name!="end") (name[first_name]).push_back(last_name); for(auto x:name){ std::cout<<x.first<<": "<<std::endl; for(auto y:x.second) std::cout<<y.first<<" "<<y.second<<" "; std::cout<<std::endl; } return 0; }
11.3.2节练习:
#include <iostream> #include <algorithm> #include <map> int main() { //11.20 std::map<std::string ,size_t > word_count; std::string word; while(std::cin>>word && word!="end"){ std::pair< std::map<std::string ,size_t>::iterator,bool> ite=word_count.insert({word,1}); if(!ite.second) ite.first->second++; } for(auto x:word_count) std::cout<<x.first<<" : "<<x.second<<std::endl; //11.23 std::multimap<std::string ,std::string> name; std::string first_name,last_name; while(std::cin>>first_name>>last_name && first_name!="end") name.insert({first_name,last_name}); for(auto x:name) std::cout<<x.first<<": "<<x.second<<std::endl; return 0; }
11.3.5节练习:
#include <iostream> #include <algorithm> #include <vector> #include <map> #include <set> #include <utility> int main() { //11.31 std::multimap<std::string ,std::string > book={{"oyy","c++ prime"}, {"oyy","java plus"}, {"oyy","english"}, {"awei","math"}, {"awei","computer"}, {"baobao","taijiong"}, {"baobao","gangjiong"}, }; std::string find_name="baoba"; auto ite=book.find(find_name); while(ite!=book.end() && ite->first==find_name){ ite=book.erase(ite); } for(auto x:book) std::cout<<x.first<<" "<<x.second<<std::endl; return 0; }
11.3.6节练习:
#include <iostream> #include <map> #include <fstream> #include <sstream> int main() { //11.33 //读取转换规则 std::ifstream readfile("test1.txt"); std::map<std::string ,std::string> tran; std::string word_first,word_second,temp; while(readfile>>word_first && getline(readfile,word_second)) tran[word_first]=word_second.length()==0?word_first:word_second.substr(1); //读取要转的内容 std::ifstream readfile2("test2.txt"); std::string sentc,word; while(getline(readfile2,sentc)){ std::istringstream in(sentc); while(in>>word){ if(tran.find(word)!=tran.end()) std::cout<<tran[word]<<" "; else std::cout<<word<<" "; } std::cout<<std::endl; } return 0; } /* test1.txt brb be right back k okay? justkey y why r are u you pic picture thk thanks! l8r later test2.txt where r u y dont u send me a pic k thk l8r */
12.1.1节练习:
#include <iostream> #include <vector> #include <initializer_list> #include <memory> #include <stdexcept> //12.2 class StrBlob{ typedef std::vector<std::string> vstring; public: StrBlob():data(std::make_shared<vstring>()){} StrBlob(std::initializer_list<std::string > lis):data(std::make_shared<vstring>(lis)){} vstring::size_type size()const {return data->size();} void push_back(const std::string &s){data->push_back(s);} void pop_back(){ check(0,"pop on empty StrBlob"); data->pop_back(); } std::string &front(){ check(0,"front on empty StrBlob"); return data->front(); } std::string &back(){ check(0,"back on empty StrBlob"); return data->back(); } private: std::shared_ptr<vstring> data; // emory void check(vstring::size_type i,const std::string &s)const { if(data->size()<=i) throw std::out_of_range(s); // stdexcept } }; int main() { //12.1 StrBlob b1{}; { StrBlob b2={"a","an","the"}; b1=b2; b2.push_back("about"); } std::cout<<b1.back()<<std::endl; StrBlob b3{"wo","qu"}; std::cout<<b3.back()<<std::endl; return 0; }
12.1.2节练习:
#include <iostream> #include <vector> #include <memory> //12.6 std::vector<int > *new_vecint(){ return new std::vector<int>; } void read_data(std::istream &in,std::vector<int> *&pv){ //普通指针 引用指针 int x; in>>x; pv->push_back(x); } void print(std::vector<int> *&pv){ for(auto x:*pv) std::cout<<x<<" "; std::cout<<std::endl; delete(pv); pv=nullptr; } //12.7 std::shared_ptr <std::vector<int > > ptr_vecint(){ //智能指针 return std::make_shared<std::vector<int > > (); //return shared_ptr<vector<int >> (new vector<int>(p)); } void ptr_read_data(std::istream &in,std::shared_ptr<std::vector<int > > &spv){ int x; in>>x; spv->push_back(x); } void ptr_print(std::shared_ptr<std::vector<int > > spv){ for(auto x:*spv) std::cout<<x<<" "; std::cout<<std::endl; } int main() { //12.6 auto pv=new_vecint(); for(int i=1;i<=3;++i) read_data(std::cin,pv); print(pv); //12.7 auto spv=ptr_vecint(); for(int i=1;i<=3;++i) ptr_read_data(std::cin,spv); ptr_print(spv); return 0; }
12.1.6节练习:
#include <iostream> #include <vector> #include <initializer_list> #include <memory> #include <stdexcept> #include <fstream> #include <sstream> class StrBlob{ typedef std::vector<std::string> vstring; public: friend class StrBlobPtr; StrBlob():data(std::make_shared<vstring>()){} StrBlob(std::initializer_list<std::string > lis):data(std::make_shared<vstring>(lis)){} vstring::size_type size()const {return data->size();} void push_back(const std::string &s){data->push_back(s);} void pop_back(){ check(0,"pop on empty StrBlob"); data->pop_back(); } std::string &front(){ check(0,"front on empty StrBlob"); return data->front(); } std::string &back(){ check(0,"back on empty StrBlob"); return data->back(); } private: std::shared_ptr<vstring> data; // memory void check(vstring::size_type i,const std::string &s)const { if(data->size()<=i) throw std::out_of_range(s); //stdexcept } }; //12.19 12.20 class StrBlobPtr{ typedef std::vector<std::string> vstring; public : StrBlobPtr():curr(0){} StrBlobPtr(StrBlob &a,size_t sz=0):wptr(a.data),curr(sz){} std::string &deref() const { auto p=check(curr,"dereference past end"); return (*p)[curr]; } StrBlobPtr& incur(){ check(curr,"increment past end of StrBlobPtr"); ++curr; return *this; } bool empty(){ if(curr < wptr.lock()->size()) return false; return true; } private: std::shared_ptr<vstring> check(size_t i,const std::string &msg)const { auto ret=wptr.lock(); if(!ret) throw std::runtime_error("unbound StrBlobPtr"); if(ret->size() <= i) throw std::out_of_range(msg); return ret; } std::weak_ptr<vstring> wptr; size_t curr; }; int main() { //12.20 std::ifstream in("in.txt"); std::string word_s; StrBlob sb; while(getline(in,word_s)){ //从文件读入数据 std::stringstream sin(word_s); std::string word; while(sin>>word) sb.push_back(word); sb.push_back("\n"); } StrBlobPtr sbp(sb); //使用StrBlob 指针类型输出StrBlob while(!sbp.empty()){ std::cout<<sbp.deref()<<" "; sbp.incur(); } return 0; } /* in.txt i think we should do it if you don't mind. so what do you want to do? */
12.2.1节练习:
#include <iostream> #include <memory> #include <algorithm> #include <cstring> #include <iterator> int main() { //12.23 char sc1[]="woqu",sc2[]=" nimeide"; char *q=new char[strlen(sc1)+strlen(sc2)+1]; strcpy(q,sc1); strcat(q,sc2); std::cout<<q<<std::endl; std::string s1="woqu",s2=" nimeide"; std::cout<<s1+s2<<std::endl; delete [] q; // need to tell the size. 12.24 std::cout << "How long do you want the string? "; int size(0); std::cin >> size; char* input = new char[size + 1](); std::cin.ignore(); //读取多余回车 std::cout << "input the string: "; std::cin.get(input, size + 1); std::cout << input; delete[] input; return 0; }
12.2.2节练习:
#include <iostream> #include <memory> //12.26 int main() { int n; std::cout<<"please input size:"; std::cin>>n; std::cin.ignore(); std::allocator<std::string > t; //定义类型对象 auto const p = t.allocate(n); //申请内存 auto q=p; std::string word; while(q!=p+n && std::cin>>word) t.construct(q++,word); //调用构造函数 while(q!=p){ std::cout<<*--q<<std::endl; t.destroy(q); //调用析构函数,释放对象 } t.deallocate(p,n); //释放内存 return 0; }
12.3.1节练习:
#include <iostream> #include <map> #include <vector> #include <set> #include <memory> #include <sstream> #include <fstream> //12.28 typedef std::vector<std::string >::size_type line; int main() { std::vector<std::string > text; std::map<std::string ,std::set<line> > sign; std::string file_name; std::cout<<"enter file name : "<<std::endl; std::cin>>file_name; std::cin.ignore(); std::ifstream file_input(file_name); std::string senten,word; while(getline(file_input,senten)){ //读入文件内容 text.push_back(senten); std::stringstream word_in(senten); line len=text.size(); while(word_in>>word) sign[word].insert(len); } while(true){ //查询 std::cout<<"enter the query word and enter q to quit : "; std::cin>>word; std::cin.ignore(); if(word=="q") break; auto loc=sign.find(word); if(loc==sign.cend()) std::cout<<"not find "<<word<<std::endl; else { std::cout<<word<<" : "<<std::endl; for(auto x:loc->second) std::cout<<"(line "<<x<<") : "<<text[x-1]<<std::endl; } } return 0; }
12.3.2节练习:
练习12.30:
#include <iostream> #include <map> #include <vector> #include <set> #include <memory> #include <sstream> #include <fstream> //12.30 同12.27 class TextQuery; class QueryResult; using line=std::vector<std::string>::size_type; //文件查询类,存错整个文件内容 以及每个单词出现的行数 定义查询函数返回一个查询结果类 class TextQuery{ public : //构造函数 获取一个文件输入对象 构造 sign p_text TextQuery(std::ifstream& in):p_text(new std::vector<std::string >){ std::string senten; //读取每行的句子 while(getline(in,senten)){ p_text->push_back(senten); auto len=p_text->size(); std::stringstream word_in(senten); std::string word; while(word_in>>word){ auto isok=sign.find(word); //若该单词还为出现过,申请新的空间 if(isok==sign.cend()) sign[word].reset(new std::set<line>); sign[word]->insert(len); } } } //该函数的定义必须在QueryResult 完整定义后定义,这里只做声明 QueryResult query(const std::string &s)const ; private : std::shared_ptr<std::vector<std::string > > p_text; //存内容 std::map<std::string,std::shared_ptr<std::set<line> > > sign; //存每个单词所在行位置数 }; //查询结果类 包括查询的单词 以及该单词所在的所有行数 单词所在行的句子(即必须获取所有内容) class QueryResult{ private: std::string word; //查询的单词 std::shared_ptr<std::set<line> > p_line; //该单词的行号 std::shared_ptr<std::vector<std::string> >p_text; //存句子 public : //print要使用里面的成员 friend std::ostream& print(std::ostream& out,const QueryResult& qr); QueryResult(std::string s, std::shared_ptr<std::set<line> > pl, std::shared_ptr<std::vector<std::string> > pv): word(s),p_line(pl),p_text(pv){} }; QueryResult TextQuery::query(const std::string &s)const{ std::shared_ptr<std::set<line> > null_ptr(new std::set<line> ); auto isok=sign.find(s); //若未找到,返回第二个参数为新申请的初始化的空间 if(isok==sign.cend()) return QueryResult(s,null_ptr,p_text); else return QueryResult(s,isok->second,p_text); } std::ostream& print(std::ostream& out,const QueryResult &qr){ out<<qr.word<<" : "<<std::endl; for(auto x:*qr.p_line) out<<"(line "<<x<<" ): "<<qr.p_text->at(x-1)<<std::endl; return out; } void runQueries(std::ifstream &infile){ TextQuery tq(infile); while(true){ std::cout<<"enter word to look for, or q to quit: "; std::string s; if(!(std::cin>>s) || s=="q") break; print(std::cout,tq.query(s))<<std::endl; } } int main() { std::ifstream in("in.txt"); runQueries(in); return 0; }
练习12.32:
#include <iostream> #include <map> #include <vector> #include <set> #include <memory> #include <sstream> #include <fstream> #include <stdexcept> //12.32 class StrBlob{ typedef std::vector<std::string> vstring; public: StrBlob():data(std::make_shared<vstring>()){} StrBlob(std::initializer_list<std::string > lis):data(std::make_shared<vstring>(lis)){} vstring::size_type size()const {return data->size();} void push_back(const std::string &s){data->push_back(s);} void pop_back(){ check(0,"pop on empty StrBlob"); data->pop_back(); } std::string &front(){ check(0,"front on empty StrBlob"); return data->front(); } std::string &back(){ check(0,"back on empty StrBlob"); return data->back(); } std::string at(int x){ return data->at(x); } private: std::shared_ptr<vstring> data; // emory void check(vstring::size_type i,const std::string &s)const { if(data->size()<=i) throw std::out_of_range(s); // stdexcept } }; class TextQuery; class QueryResult; using line=std::vector<std::string>::size_type; //文件查询类,存错整个文件内容 以及每个单词出现的行数 定义查询函数返回一个查询结果类 class TextQuery{ public : //构造函数 获取一个文件输入对象 构造 sign p_text TextQuery(std::ifstream& in):p_text(new StrBlob){ std::string senten; //读取每行的句子 while(getline(in,senten)){ p_text->push_back(senten); auto len=p_text->size(); std::stringstream word_in(senten); std::string word; while(word_in>>word){ auto isok=sign.find(word); //若该单词还为出现过,申请新的空间 if(isok==sign.cend()) sign[word].reset(new std::set<line>); sign[word]->insert(len); } } } //该函数的定义必须在QueryResult 完整定义后定义,这里只做声明 QueryResult query(const std::string &s)const ; private : std::shared_ptr<StrBlob > p_text; //存内容 std::map<std::string,std::shared_ptr<std::set<line> > > sign; //存每个单词所在行位置数 }; //查询结果类 包括查询的单词 以及该单词所在的所有行数 单词所在行的句子(即必须获取所有内容) class QueryResult{ private: std::string word; //查询的单词 std::shared_ptr<std::set<line> > p_line; //该单词的行号 std::shared_ptr<StrBlob >p_text; //存句子 public : //print要使用里面的成员 friend std::ostream& print(std::ostream& out,const QueryResult& qr); QueryResult(std::string s, std::shared_ptr<std::set<line> > pl, std::shared_ptr<StrBlob > pv): word(s),p_line(pl),p_text(pv){} }; QueryResult TextQuery::query(const std::string &s)const{ std::shared_ptr<std::set<line> > null_ptr(new std::set<line> ); auto isok=sign.find(s); //若未找到,返回第二个参数为新申请的初始化的空间 if(isok==sign.cend()) return QueryResult(s,null_ptr,p_text); else return QueryResult(s,isok->second,p_text); } std::ostream& print(std::ostream& out,const QueryResult &qr){ out<<qr.word<<" : "<<std::endl; for(auto x:*qr.p_line) out<<"(line "<<x<<" ): "<<qr.p_text->at(x-1)<<std::endl; return out; } void runQueries(std::ifstream &infile){ TextQuery tq(infile); while(true){ std::cout<<"enter word to look for, or q to quit: "; std::string s; if(!(std::cin>>s) || s=="q") break; print(std::cout,tq.query(s))<<std::endl; } } int main() { std::ifstream in("in.txt"); runQueries(in); return 0; }
练习12.33:
#include <iostream> #include <map> #include <vector> #include <set> #include <memory> #include <sstream> #include <fstream> //12.30 同12.27 class TextQuery; class QueryResult; using line=std::vector<std::string>::size_type; //文件查询类,存错整个文件内容 以及每个单词出现的行数 定义查询函数返回一个查询结果类 class TextQuery{ public : //构造函数 获取一个文件输入对象 构造 sign p_text TextQuery(std::ifstream& in):p_text(new std::vector<std::string >){ std::string senten; //读取每行的句子 while(getline(in,senten)){ p_text->push_back(senten); auto len=p_text->size(); std::stringstream word_in(senten); std::string word; while(word_in>>word){ auto isok=sign.find(word); //若该单词还为出现过,申请新的空间 if(isok==sign.cend()) sign[word].reset(new std::set<line>); sign[word]->insert(len); } } } //该函数的定义必须在QueryResult 完整定义后定义,这里只做声明 QueryResult query(const std::string &s)const ; private : std::shared_ptr<std::vector<std::string > > p_text; //存内容 std::map<std::string,std::shared_ptr<std::set<line> > > sign; //存每个单词所在行位置数 }; //查询结果类 包括查询的单词 以及该单词所在的所有行数 单词所在行的句子(即必须获取所有内容) class QueryResult{ private: std::string word; //查询的单词 std::shared_ptr<std::set<line> > p_line; //该单词的行号 std::shared_ptr<std::vector<std::string> >p_text; //存句子 public : //print要使用里面的成员 friend std::ostream& print(std::ostream& out,const QueryResult& qr); QueryResult(std::string s, std::shared_ptr<std::set<line> > pl, std::shared_ptr<std::vector<std::string> > pv): word(s),p_line(pl),p_text(pv){} std::set<line >::iterator begin(){ //begin return p_line->begin(); } std::set<line >::iterator end(){ //end return p_line->end(); } std::shared_ptr<std::vector<std::string> > get_file(){ //get_file return p_text; } }; QueryResult TextQuery::query(const std::string &s)const{ std::shared_ptr<std::set<line> > null_ptr(new std::set<line> ); auto isok=sign.find(s); //若未找到,返回第二个参数为新申请的初始化的空间 if(isok==sign.cend()) return QueryResult(s,null_ptr,p_text); else return QueryResult(s,isok->second,p_text); } std::ostream& print(std::ostream& out,const QueryResult &qr){ out<<qr.word<<" : "<<std::endl; for(auto x:*qr.p_line) out<<"(line "<<x<<" ): "<<qr.p_text->at(x-1)<<std::endl; return out; } void runQueries(std::ifstream &infile){ TextQuery tq(infile); while(true){ std::cout<<"enter word to look for, or q to quit: "; std::string s; if(!(std::cin>>s) || s=="q") break; print(std::cout,tq.query(s))<<std::endl; } } int main() { return 0; }
15.2.1节练习:
#include <iostream> //15.3 class Quote{ public : Quote()=default; Quote(const std::string &book,double sales_price):bookNo(book),price(sales_price){} std::string isbn()const {return bookNo;} virtual double net_price(std::size_t n) const {return n*price;} friend double print_total(std::ostream&,const Quote&,size_t ); private: std::string bookNo; protected: double price=0.0; }; double print_total(std::ostream &os,const Quote &item,size_t n){ double ret=item.net_price(n); os<<"isbn: "<<item.isbn()<<" sold :"<<n<<" total due: "<<ret<<std::endl; return ret; } int main() { Quote q("c++ prime",150); print_total(std::cout,q,3); return 0; }
15.2.2节练习:
#include <iostream> #include <cstdio> //15.5 15.6 15.7 class Quote{ public : Quote()=default; Quote(const std::string &book,double sales_price):bookNo(book),price(sales_price){} std::string isbn()const {return bookNo;} virtual double net_price(std::size_t n) const {return n*price;} friend double print_total(std::ostream&,const Quote&,size_t ); private: std::string bookNo; protected: double price=0.0; }; class Bulk_quote:public Quote{ public : Bulk_quote()=default; Bulk_quote(const std::string &book,double sales_price,std::size_t num,double disc): Quote(book,sales_price),min_num(num),discount(disc){}; double net_price(std::size_t n) const{ if(n>=min_num) return n*price*discount; else return n*price; } private: std::size_t min_num; double discount; }; class huodong_quote:public Quote{ public : huodong_quote()=default; huodong_quote(const std::string book,double sales_price,std::size_t num,double disc): Quote(book,sales_price),max_num(num),discount(disc){} double net_price(std::size_t n)const { if(n<=max_num) return n*price*discount; else return net_price(max_num)+(n-max_num)*price; } private: double discount; size_t max_num; }; double print_total(std::ostream &os,const Quote &item,size_t n){ double ret=item.net_price(n); os<<"isbn: "<<item.isbn()<<" sold :"<<n<<" total due: "<<ret<<std::endl; return ret; } int main() { Bulk_quote b("math",20,5,0.5); print_total(std::cout,b,4); print_total(std::cout,b,5); huodong_quote h("高数",20,5,0.5); print_total(std::cout,h,5); print_total(std::cout,h,6); return 0; }
15.3节练习:
#include <iostream> #include <cstdio> //15.11 debug() class Quote{ public : Quote()=default; Quote(const std::string &book,double sales_price):bookNo(book),price(sales_price){} std::string isbn()const {return bookNo;} virtual double net_price(std::size_t n) const {return n*price;} friend double print_total(std::ostream&,const Quote&,size_t ); virtual void debug(){ std::cout<<"类成员及类型如下所示:"<<std::endl; std::cout<<"string : bookNo"<<std::endl; std::cout<<"double : price"<<std::endl; } private: std::string bookNo; protected: double price=0.0; }; class Bulk_quote:public Quote{ public : Bulk_quote()=default; Bulk_quote(const std::string &book,double sales_price,std::size_t num,double disc): Quote(book,sales_price),min_num(num),discount(disc){}; double net_price(std::size_t n) const{ if(n>=min_num) return n*price*discount; else return n*price; } void debug()override{ Quote::debug(); std::cout<<"size_t : min_num"<<std::endl; std::cout<<"double : discount"<<std::endl; } private: std::size_t min_num; double discount; }; class huodong_quote:public Quote{ public : huodong_quote()=default; huodong_quote(const std::string book,double sales_price,std::size_t num,double disc): Quote(book,sales_price),max_num(num),discount(disc){} double net_price(std::size_t n)const { if(n<=max_num) return n*price*discount; else return net_price(max_num)+(n-max_num)*price; } void debug()override{ Quote::debug(); std::cout<<"size_t : max_num"<<std::endl; std::cout<<"double : discount"<<std::endl; } private: double discount; size_t max_num; }; double print_total(std::ostream &os,const Quote &item,size_t n){ double ret=item.net_price(n); os<<"isbn: "<<item.isbn()<<" sold :"<<n<<" total due: "<<ret<<std::endl; return ret; } int main() { Bulk_quote b("math",20,5,0.5); huodong_quote h("数学",20,5,0.5); b.debug(); std::cout<<std::endl; h.debug(); return 0; }
15.4节练习:
#include <iostream> #include <cstdio> //15.15 15.16 class Quote{ public : Quote()=default; Quote(const std::string &book,double sales_price):bookNo(book),price(sales_price){} std::string isbn()const {return bookNo;} virtual double net_price(std::size_t n) const {return n*price;} friend double print_total(std::ostream&,const Quote&,size_t ); private: std::string bookNo; protected: double price=0.0; }; double print_total(std::ostream &os,const Quote &item,size_t n){ double ret=item.net_price(n); os<<"isbn: "<<item.isbn()<<" sold :"<<n<<" total due: "<<ret<<std::endl; return ret; } class Disc_quote:public Quote{ public : Disc_quote()=default; Disc_quote(const std::string &book,double sales_price,std::size_t n,double disc): Quote(book,sales_price),off_num(n),discount(disc){} double net_price(size_t)const =0; //´¿Ð麯Êý protected: size_t off_num; double discount; }; class Bulk_quote:public Disc_quote{ public : Bulk_quote()=default; Bulk_quote(const std::string &book,double sales_price,std::size_t num,double disc): Disc_quote(book,sales_price,num,disc){}; double net_price(std::size_t n) const override{ if(n>=off_num) return n*price*discount; else return n*price; } }; class huodong_quote:public Disc_quote{ public : huodong_quote()=default; huodong_quote(const std::string book,double sales_price,std::size_t num,double disc): Disc_quote(book,sales_price,num,disc){} double net_price(std::size_t n)const override{ if(n<=off_num) return n*price*discount; else return net_price(off_num)+(n-off_num)*price; } }; int main() { Bulk_quote b("高数",20,5,0.5); huodong_quote h("线代",20,5,0.5); print_total(std::cout,b,6); print_total(std::cout,h,6); return 0; }
15.5节练习:
#include <iostream> #include <cmath> //15.21 15.22 class Graph{ public : Graph()=default; Graph(double x):r(x){} virtual double get_area()=0; virtual double get_value()=0; protected: double r; const double Pi=3.1415926; }; class Grid:public Graph{ public : Grid()=default; Grid(double x):Graph(x){} double get_area(){return r*r;} double get_value(){return 0.0;} }; class Circle:public Graph{ public : Circle()=default; Circle(double x):Graph(x){} double get_area(){return Pi*r*r;} double get_value(){return 0.0;} }; class Ball:public Graph{ public : Ball()=default; Ball(double x):Graph(x){} double get_area(){return 4.0*Pi*r*r;} double get_value(){return 4.0*Pi*r*r*r/3.0;} }; class Cone:public Graph{ public : Cone()=default; Cone(double x,double y):Graph(x),height(y){} double get_area(){return Pi*r*r+Pi*r*sqrt(height*height+r*r);} double get_value(){return Pi*height*r*r/3.0;} protected: double height; }; int main() { Grid g(2.0); Circle ci(2.0); Ball b(2.0); Cone co(2.0,3.0); std::cout<<"Grid : "<<g.get_area()<<" m^2 "<<g.get_value()<<" m^3 "<<std::endl; std::cout<<"Cirle : "<<ci.get_area()<<" m^2 "<<ci.get_value()<<" m^3 "<<std::endl; std::cout<<"Ball : "<<b.get_area()<<" m^2 "<<b.get_value()<<" m^3 "<<std::endl; std::cout<<"Cone : "<<co.get_area()<<" m^2 "<<co.get_value()<<" m^3 "<<std::endl; return 0; }
15.7.3节练习:
#include <iostream> //15.26 class Quote{ public : Quote()=default; Quote(const std::string &book,double sales_price):bookNo(book),price(sales_price){ std::cout<<"Quote construct "<<std::endl; } Quote(const Quote &qu){ this->bookNo=qu.bookNo; this->price=qu.price; std::cout<<"Quote copy "<<std::endl; } std::string isbn()const {return bookNo;} virtual ~Quote(){ std::cout<<"Quote delete"<<std::endl; } private: std::string bookNo; protected: double price=0.0; }; class Bulk_quote:public Quote{ public : Bulk_quote()=default; Bulk_quote(const std::string &book,double sales_price,std::size_t num,double disc): Quote(book,sales_price),min_num(num),discount(disc){ std::cout<<"Bulk_quote construct "<<std::endl; }; Bulk_quote(const Bulk_quote &bkq):Quote(bkq){ this->min_num=bkq.min_num; this->discount=bkq.discount; std::cout<<"Bulk_quote copy "<<std::endl; } virtual ~Bulk_quote(){ std::cout<<"Bulk_quote delete "<<std::endl; } private: std::size_t min_num; double discount; }; int main() { Bulk_quote b("math",20,5,0.5); Bulk_quote bb(b); return 0; } /* 首位两行为b调用构造函数及析构函数, 中间四行为bb调用拷贝函数及析构函数 Quote construct Bulk_quote construct Quote copy Bulk_quote copy Bulk_quote delete Quote delete Bulk_quote delete Quote delete */
15.8节练习:
#include <iostream> #include <cstdio> #include <vector> #include <memory> //15.28 15.29 class Quote{ public : Quote()=default; Quote(const std::string &book,double sales_price):bookNo(book),price(sales_price){} std::string isbn()const {return bookNo;} virtual double net_price(std::size_t n) const {return n*price;} friend double print_total(std::ostream&,const Quote&,size_t ); private: std::string bookNo; protected: double price=0.0; }; class Bulk_quote:public Quote{ public : Bulk_quote()=default; Bulk_quote(const std::string &book,double sales_price,std::size_t num,double disc): Quote(book,sales_price),min_num(num),discount(disc){}; double net_price(std::size_t n) const{ if(n>=min_num) return n*price*discount; else return n*price; } private: std::size_t min_num; double discount; }; double print_total(std::ostream &os,const Quote &item,size_t n){ double ret=item.net_price(n); os<<"isbn: "<<item.isbn()<<" sold :"<<n<<" total due: "<<ret<<std::endl; return ret; } int main() { std::vector<Quote > vec1; vec1.push_back(Bulk_quote("高数",20,8,0.5));//只是把其中Quote的部分拷贝给vec1了 vec1.push_back(Bulk_quote("高数",20,5,0.5)); double sum1=0.0; for(auto x:vec1){ sum1+=print_total(std::cout,x,7); } std::cout<<"total_price:"<<sum1<<std::endl; std::vector<std::shared_ptr<Quote> > vec2; vec2.push_back(std::make_shared<Bulk_quote>("高数",20,8,0.5)); //指针动态绑定 vec2.push_back(std::make_shared<Bulk_quote>("高数",20,5,0.5)); double sum2=0.0; for(auto x:vec2){ sum2+=print_total(std::cout,*x,7); } std::cout<<"total_price:"<<sum2<<std::endl; return 0; }
15.8.1节练习:
#include <iostream> #include <memory> #include <set> //15.30 class Quote{ public : Quote()=default; Quote(const std::string &book,double sales_price):bookNo(book),price(sales_price){} std::string isbn()const {return bookNo;} virtual double net_price(std::size_t n) const {return n*price;} friend double print_total(std::ostream&,const Quote&,size_t ); // virtual Quote *clone()const &{return new Quote(*this);} 编译器不支持 private: std::string bookNo; protected: double price=0.0; }; class Bulk_quote:public Quote{ public : Bulk_quote()=default; Bulk_quote(const std::string &book,double sales_price,std::size_t num,double disc): Quote(book,sales_price),min_num(num),discount(disc){}; //Bulk_quote *clone()const &{return new Bulk_quote(*this);} double net_price(std::size_t n) const{ if(n>=min_num) return n*price*discount; else return n*price; } private: std::size_t min_num; double discount; }; double print_total(std::ostream &os,const Quote &item,size_t n){ double ret=item.net_price(n); os<<"isbn: "<<item.isbn()<<" sold :"<<n<<" total due: "<<ret<<std::endl; return ret; } class Basket{ public: //向vector中插入新元素 void add_item(std::shared_ptr<Quote> sale){ item.insert(sale); } //void add_item(const Quote &sale){ // item.insert(std::shared_ptr<Quote>(sale.clone())); //} //输出 double total_receipt(std::ostream& os)const{ double sum=0.0; //upper_bound(*iter) 指向下一个关键字 //item.count(*iter) 计算关键字为*iter的元素个数 for(auto iter=item.cbegin();iter!=item.cend();iter=item.upper_bound(*iter)){ sum+=print_total(os,**iter,item.count(*iter)); } os<<"Total Sale: "<<sum<<std::endl; return sum; } private: static bool cmp(const std::shared_ptr<Quote > &lhs,const std::shared_ptr<Quote > &rhs){ return lhs->isbn()<rhs->isbn(); } std::multiset<std::shared_ptr<Quote>,decltype(cmp)*> item{cmp}; }; int main() { Basket b; for(int i=1;i<=5;++i) b.add_item(std::make_shared<Bulk_quote>("高数",20,5,0.5)); for(int i=1;i<=7;++i) b.add_item(std::make_shared<Bulk_quote>("线代",30,5,0.5)); //for(int i=1;i<=5;++i) b.add_item(Bulk_quote("高数",20,5,0.5)); //for(int i=1;i<=7;++i) b.add_item(Bulk_quote("线代",30,5,0.5)); b.total_receipt(std::cout); return 0; }
15.92~15.93节练习:
#include <iostream> #include <map> #include <vector> #include <set> #include <memory> #include <sstream> #include <fstream> #include <algorithm> #include <iterator> class TextQuery; class QueryResult; using line=std::vector<std::string>::size_type; //文件查询类,存错整个文件内容 以及每个单词出现的行数 定义查询函数返回一个查询结果类 class TextQuery{ public : //构造函数 获取一个文件输入对象 构造 sign p_text TextQuery(std::ifstream& in):p_text(new std::vector<std::string >){ std::string senten; //读取每行的句子 while(getline(in,senten)){ p_text->push_back(senten); auto len=p_text->size(); //对应行号 即从1开始 std::stringstream word_in(senten); std::string word; while(word_in>>word){ auto isok=sign.find(word); //若该单词还为出现过,申请新的空间 if(isok==sign.cend()) sign[word].reset(new std::set<line>); sign[word]->insert(len); } } } //该函数的定义必须在QueryResult 完整定义后定义,这里只做声明 QueryResult query(const std::string &s)const ; private : std::shared_ptr<std::vector<std::string > > p_text; //存内容 std::map<std::string,std::shared_ptr<std::set<line> > > sign; //存每个单词所在行位置数 }; //查询结果类 包括查询的单词 以及该单词所在的所有行数 单词所在行的句子(即必须获取所有内容) class QueryResult{ private: std::string word; //查询的单词 std::shared_ptr<std::set<line> > p_line; //该单词的行号 std::shared_ptr<std::vector<std::string> >p_text; //存句子 public : //print要使用里面的成员 friend std::ostream& print(std::ostream& out,const QueryResult& qr); QueryResult(std::string s, std::shared_ptr<std::set<line> > pl, std::shared_ptr<std::vector<std::string> > pv): word(s),p_line(pl),p_text(pv){} std::set<line >::iterator begin(){ //begin return p_line->begin(); } std::set<line >::iterator end(){ //end return p_line->end(); } std::shared_ptr<std::vector<std::string> > get_file(){ //get_file return p_text; } }; QueryResult TextQuery::query(const std::string &s)const{ std::shared_ptr<std::set<line> > null_ptr(new std::set<line> ); auto isok=sign.find(s); //若未找到,返回第二个参数为新申请的初始化的空间 if(isok==sign.cend()) return QueryResult(s,null_ptr,p_text); else return QueryResult(s,isok->second,p_text); } std::ostream& print(std::ostream& out,const QueryResult &qr){ out<<qr.word<<" : "<<std::endl; for(auto x:*qr.p_line) out<<"(line "<<x<<" ): "<<qr.p_text->at(x-1)<<std::endl; return out; } class Query_base{ friend class Query; //Query使用eval() rep()函数 protected : virtual ~Query_base()=default; private: virtual QueryResult eval(const TextQuery&)const =0; //返回与之匹配的QueryResult virtual std::string rep()const =0; //返回要查询的string }; class Query{ friend Query operator~(const Query &); friend Query operator|(const Query&,const Query&); friend Query operator&(const Query&,const Query&); public : Query(const std::string&s=""); //当Query q时,自动赋值一个""给rep( 初始值默认初始化) QueryResult eval(const TextQuery &t)const {return q->eval(t);}//Query_base::eval() std::string rep()const {return q->rep();} //Query_base::rep() private: Query(std::shared_ptr<Query_base> query):q(query){} //构造函数,接受一个Query_base指针 std::shared_ptr<Query_base> q; //通过该指针实现多态 }; class WordQuery:public Query_base{ //直接调用TextQuery的query函数即可 friend class Query; WordQuery(const std::string &s):query_word(s){} QueryResult eval(const TextQuery &t)const {return t.query(query_word);} std::string rep()const {return query_word;} std::string query_word; // Query::Query(const std::string &s):q(new WordQuery(s)){} }; //Query的构造函数,接受一个string 把一个WordQuery(s)赋给Query:q inline Query::Query(const std::string &s):q(new WordQuery(s)){} class NotQuery:public Query_base{ friend Query operator~(const Query &); NotQuery(const Query &q):query(q){} //构造函数 获取一个Query参数 std::string rep()const {return "~("+query.rep()+")";} QueryResult eval(const TextQuery&) const ; Query query; }; //重载运算符,返回一个指向NotQuery类型的指针 绑定到Query inline Query operator~(const Query &operand){ return std::shared_ptr<Query_base>(new NotQuery(operand)); } class BinaryQuery:public Query_base{ protected: //构造函数获得左右操作对象 及操作方法 BinaryQuery(const Query &l,const Query &r,std::string s):lhs(l),rhs(r),opSym(s){} std::string rep()const{ return "("+lhs.rep()+" "+opSym+" "+rhs.rep()+")";} Query lhs,rhs; //两个运算对象 std::string opSym; //运算符 }; class AndQuery:public BinaryQuery{ friend Query operator&(const Query&,const Query); public : AndQuery(const Query &left,const Query &right):BinaryQuery(left,right,"&"){} QueryResult eval(const TextQuery&)const; }; //重载运算符返回一个指向 AndQuery类型的指针 绑定到Query inline Query operator&(const Query &lhs,const Query &rhs){ return std::shared_ptr<Query_base>(new AndQuery(lhs,rhs)); } class OrQuery:public BinaryQuery{ friend Query operator|(const Query &,const Query&); public : OrQuery(const Query &left,const Query &right):BinaryQuery(left,right,"|"){} QueryResult eval(const TextQuery&)const; }; //重载运算符返回一个指向 OrQuery类型的指针 绑定到Query inline Query operator|(const Query &lhs,const Query &rhs){ return std::shared_ptr<Query_base>(new OrQuery(lhs,rhs)); } //重载输出运算符,输出Query指向的rep(),可注释 std::ostream & operator<<(std::ostream &os,const Query &query){return os<<query.rep();} //把两个Query 的QueryResult合并,即两向一个set 插入两个对象的信息 QueryResult OrQuery::eval(const TextQuery& text)const { auto right=rhs.eval(text),left=lhs.eval(text); auto ret_lines=std::make_shared<std::set<line> >(left.begin(),left.end()); ret_lines->insert(right.begin(),right.end()); return QueryResult(rep(),ret_lines,left.get_file()); } //调用函数 set_intersection(beg1,end1,beg2,end2,dest)函数实现 QueryResult AndQuery::eval(const TextQuery& text)const{ auto left=lhs.eval(text),right=rhs.eval(text); auto ret_lines=std::make_shared<std::set<line> >(); set_intersection(left.begin(),left.end(),right.begin(),right.end(), inserter(*ret_lines,ret_lines->begin())); return QueryResult(rep(),ret_lines,left.get_file()); } QueryResult NotQuery::eval(const TextQuery&text)const { auto result=query.eval(text); //result相当于一个WordQuery的结果 auto ret_lines=std::make_shared<std::set<line> >(); //新建一个 *set auto beg=result.begin(),end=result.end(); auto sz=result.get_file()->size();//查询内容的总行数 //for(auto &x:result) std::cout<<x<<std::endl; //std::cout<<" sz :"<<sz<<std::endl; for(size_t n=1;n!=sz;++n){ //取内容中不在result,p_line中的行数放入新*set,注意从第一行开始 if(beg==end || *beg!=n) ret_lines->insert(n); else if(beg!=end)++beg; } return QueryResult(rep(),ret_lines,result.get_file()); } void runQueries(std::ifstream &infile){ TextQuery tq(infile); while(true){ std::cout<<"enter word to look for, or q to quit: "; std::string s; if(!(std::cin>>s) || s=="q") break; print(std::cout,tq.query(s))<<std::endl; } } int main() { std::ifstream infile("in.txt"); TextQuery tq(infile); Query q1("i"),q2,q3=q1|q2,q4=~q1; print(std::cout,q4.eval(tq)); return 0; } /* in.txt: i don't think so why i can't do it just for her ? i love her and i want stay with her forever can i success ? */
16.1.1节练习:
#include <iostream> #include <cstring> #include <vector> #include <list> #include <algorithm> //16.2 template <typename T> int compare(const T& a,const T& b){ if(a>b) return 1; else if(a<b) return -1; return 0; } void fun2(){ std::cout<<compare(123,12)<<std::endl; std::cout<<compare(12.12,12.13)<<std::endl; std::cout<<compare((std::string)"woqu",(std::string)"shabi")<<std::endl; std::vector<int > v1={1,2,3,4},v2={2,3,4}; std::cout<<compare(v1,v2)<<std::endl; } //16.4 template <typename T1,typename T2> T1 find1(T1 beg,T1 end,const T2& temp){ while(beg!=end) if(*beg==temp) return beg; else ++beg; return end; } void fun4(){ std::vector<int > a={1,3,4,5}; auto iter=find1(a.begin(),a.end(),3); std::cout<<*iter<<std::endl; std::list<std::string > ls={"wo","qu","dou","bi"}; auto iter2=find1(ls.begin(),ls.end(),"qu"); std::cout<<*iter2<<std::endl; } //16.5 这个很神奇 template <typename T,unsigned N> void print(const T (&p)[N]){ for(int i=0;i<N;++i) std::cout<<p[i]<<" "; std::cout<<std::endl; } void fun5(){ int a[]={1,3,4,5,7}; char s[]="woqunimeide"; print(a); print(s); } //16.6 template <typename T,unsigned N> T* begin(T (&p)[N]){ if(N>1) return p; else return NULL; } template <typename T,unsigned N> T* end(T (&p)[N]){ if(N>1)return p+N; else return NULL; } void fun6(){ int num[]={1,2,3,4,5}; char s[]="woqufule"; std::for_each(begin(num),end(num), [](const int &x){std::cout<<x<<" ";}); //相当于for(auto it=begin(num);it!=end(num);+it) std::cout<<*it<<" "; std::cout<<std::endl; std::for_each(begin(s),end(s), [](const char &x){std::cout<<x<<" ";}); std::cout<<std::endl; } //16.7 template <typename T,unsigned N> constexpr unsigned size_array(T (&p)[N]){ return N; } void fun7(){ int num[]={1,2,3,4}; std::cout<<size_array(num); } int main() { //fun2(); //16.2 //fun4(); //16.4 //fun5(); //16.5 //fun6(); //16.6 //fun7(); //16.7 return 0; }
16.1.2节练习:
#include <iostream> #include <vector> #include <initializer_list> #include <memory> #include <stdexcept> //16.12 template <typename T> class BlobPtr; template <typename T> class Blob{ friend BlobPtr<T> ; public: typedef typename std::vector<T>::size_type size_type; Blob():data(std::make_shared<std::vector<T> >()){} Blob(std::initializer_list<T> lis):data(std::make_shared<std::vector<T> >(lis)){} size_type size()const {return data->size();} void push_back(const T &s){data->push_back(s);} void pop_back(){ check(0,"pop on empty Blob"); data->pop_back(); } T &front(){ check(0,"front on empty Blob"); data->front(); } T &back(){ check(0,"back on empty Blob"); return data->back(); } T &operator[](size_type t); private: std::shared_ptr<std::vector<T> > data; // emory void check(size_type i,const std::string &s)const { if(data->size()<=i) throw std::out_of_range(s); // stdexcept } }; template <typename T> T &Blob<T>::operator[](size_type t){ check(t,"subscript out of range"); return (*data)[t]; } template <typename T> class BlobPtr{ public : BlobPtr():curr(0){} BlobPtr(Blob<T> &a,size_t sz=0):wptr(a.data),curr(sz){} T &operator*()const{ auto p=check(curr,"derefence past end"); return (*p)[curr]; } BlobPtr& operator++(){ BlobPtr ret=*this; curr++; // ++*this; return ret; } BlobPtr& operator--(){ BlobPtr ret=*this; curr--; // --*this; return ret; } private: std::shared_ptr<std::vector<T> > check(std::size_t t,const std::string &msg)const { auto ret=wptr.lock(); if(!ret) throw std::runtime_error("unbound BlobPtr"); else if(t>=ret->size())throw std::out_of_range(msg); return ret; } std::weak_ptr<std::vector<T> > wptr; std::size_t curr; }; int main() { //16.12 Blob<std::string> b1={"a","an","the"}; for(auto i=0;i<b1.size();++i) std::cout<<b1[i]<<" "; std::cout<<std::endl; BlobPtr<std::string> pb(b1); for(int i=0;i<b1.size();++i,++pb) std::cout<<*pb<<" "; return 0; }
16.1.2节练习:
#include <iostream> #include <stdexcept> //16.14 16.15 template <unsigned H,unsigned W> class Screen{ typedef std::string::size_type pos; public: Screen()=default; Screen(char c):contents(H*W,c){} char get()const { return contents[cursor];} //取当前焦点的值 Screen &move(pos r,pos c){ //移动焦点 if(r<1) throw std::out_of_range("out of screen"); cursor =(r-1)*width +c; return *this; } Screen &operator<<(const char &c){ //输出当前焦点的值 contents[cursor] =c; return *this; } Screen &operator>>(char &c){ //输入当前焦点的值 c=contents[cursor]; return *this; } friend std::ostream &operator<<(std::ostream &os,const Screen<H,W> &c ){ //输出屏幕 for(int i=0;i<c.height;++i) os<<c.contents.substr(i*W,W)<<std::endl; return os; } private: pos cursor=0; //焦点 pos height=H,width=W; //宽高 std::string contents; //一个string 存整个屏幕 }; int main() { Screen<10,10> src('x'); src.move(5,5); src<<'c'; std::cout<<src; return 0; }
16.1.3节练习:
#include <iostream> #include <vector> #include <list> #include <set> //16.19 template <typename T> void print(T& pack){ for(auto &x:pack) std::cout<<x<<" "; std::cout<<std::endl; } //16.20 template <typename T> void print2(T& pack){ for(auto it=pack.begin();it!=pack.end();++it) std::cout<<*it<<" "; std::cout<<std::endl; } int main() { std::vector<int > vec={1,2,3,4,5}; print(vec); print2(vec); std::list<char > li={'w','o','q','u'}; print(li); print2(li); std::set<int > st={6,7,8}; print(st); print2(st); return 0; }
16.1.4节练习:
#include <iostream> //16.21 class DebugDelete{ public : DebugDelete(std::ostream &s = std::cerr):os(s){} //构造函数 template <typename T> void operator()(T *p)const{ //重载()运算符 os<<"deleteing unique_ptr"<<std::endl; delete p; } private: std::ostream &os; }; int main() { DebugDelete del; int *p= new int(3); del(p); std::cout<<*p; return 0; }
16.1.4节练习:
#include <iostream> #include <vector> #include <memory> #include <stdexcept> template <typename T> class Blob{ public: typedef typename std::vector<T>::size_type size_type; Blob():data(std::make_shared<std::vector<T> >()){} Blob(std::initializer_list<T> lis):data(std::make_shared<std::vector<T> >(lis)){} size_type size()const {return data->size();} void push_back(const T &s){data->push_back(s);} void pop_back(){ check(0,"pop on empty Blob"); data->pop_back(); } T &front(){ check(0,"front on empty Blob"); data->front(); } T &back(){ check(0,"back on empty Blob"); return data->back(); } T &operator[](size_type t); //16.24 Blob(typename std::vector<T>::iterator b,typename std::vector<T>::iterator e){ data=std::make_shared<std::vector<T> >(b,e); } private: std::shared_ptr<std::vector<T> > data; // emory void check(size_type i,const std::string &s)const { if(data->size()<=i) throw std::out_of_range(s); // stdexcept } }; int main() { std::vector<int > v={1,2,3}; Blob<int> b(v.begin(),v.end()); std::cout<<b.back(); return 0; }
未完待续。。。