c++primer第五版第十七章练习
程序员文章站
2022-07-04 11:55:39
17.1、17.2
#include
#include
#include
#include
int main()
{
using namespace std;...
17.1、17.2
#include #include #include #include int main() { using namespace std; tuple ti{ 10,20,30 }; cout << get<0>(ti) << " " << get<1>(ti) << " " << get<2>(ti) << endl; tuple, pair> top; system("pause"); return 0; }
17.3
#pragma once #include #include #include #include #include #include #include class textquery { public: typedef std::vector::size_type _type; typedef std::tuple>, std::shared_ptr>> queryresult; private: std::shared_ptr> file; std::map>> ms; public: textquery(std::ifstream &ifile); queryresult query(const std::string &s)const; queryresult query_tuple(const std::string &s); };
#include "textquery.h" #include #include #include textquery::textquery(std::ifstream &ifile) :file(new std::vector) { std::string line; while (std::getline(ifile, line)) { file->push_back(line); std::stringstream sstr(line); std::string word; while (sstr >> word) { //std::shared_ptr> &sptr = ms[word]; auto &sptr = ms[word]; if (!sptr) sptr.reset(new std::set<_type>); sptr->insert(file->size() - 1); } } } textquery::queryresult textquery::query(const std::string &s)const { static std::shared_ptr> nodata(new std::set<_type>); auto iter = ms.find(s); if (iter == ms.end()) return queryresult(s, nodata, file); else return queryresult(s, iter->second, file); } textquery::queryresult textquery::query_tuple(const std::string &s) { static std::shared_ptr> nodata(new std::set<_type>); auto iter = ms.find(s); if (iter == ms.end()) return queryresult(s, nodata, file); else return queryresult(s, iter->second, file); }
#include #include #include "textquery.h" std::ostream &operator<<(std::ostream &os, const textquery::queryresult &q) { os << std::get<0>(q) << "\n"; for (auto &x : *std::get<1>(q)) os << x << " "; os << "\n"; for (auto &x : *std::get<2>(q)) os << x << " "; return os; } int main(int agrc,char **argv) { using namespace std; ifstream ifile(argv[1]); if (!ifile) { cout << "open file error!"; exit(1); } textquery b(ifile); cout<
原来的方法比较好
tuple用于快速生成,但却难以重构,可用于快速的测试
17.4、17.5、17.6
#pragma once #include #include class sales_data { friend sales_data operator+(const sales_data& lhs, const sales_data& rhs); friend std::ostream &operator << (std::ostream& os, const sales_data& s); friend std::istream &operator >> (std::istream& is, sales_data& s); friend sales_data add(const sales_data&, const sales_data&); friend std::ostream &print(std::ostream&, const sales_data&); friend std::istream &read(std::istream&, sales_data&); public: sales_data() = default; sales_data(const std::string &s) : bookno(s) { } sales_data(const std::string &s, unsigned n, double p) :bookno(s), units_sold(n), revenue(p*n){} sales_data(const sales_data &s) :bookno(s.bookno), units_sold(s.units_sold), revenue(s.revenue){} sales_data(sales_data&& s) :bookno(s.bookno), units_sold(s.units_sold), revenue(s.revenue){} ~sales_data() {} sales_data(std::istream &); std::string isbn() const { return bookno; } sales_data& combine(const sales_data&); sales_data& operator =(const sales_data& rhs); sales_data& operator =(const std::string& rhs); sales_data& operator +=(const sales_data& rhs); explicit operator std::string() const { return bookno; } explicit operator double() const { return revenue; } double avg_price() const; private: std::string bookno; unsigned units_sold = 0; double revenue = 0.0; }; inline sales_data operator+(const sales_data& lhs, const sales_data& rhs) { sales_data sum = lhs; sum += rhs; return sum; } std::ostream &operator << (std::ostream& os, const sales_data& item); std::istream &operator >> (std::istream& is, sales_data& s); sales_data add(const sales_data&, const sales_data&); std::ostream &print(std::ostream&, const sales_data&); std::istream &read(std::istream&, sales_data&);
#include #include "sales_data.h" using std::istream; using std::ostream; sales_data::sales_data(std::istream &is) { read(is, *this); } double sales_data::avg_price() const { if (units_sold) return revenue / units_sold; else return 0; } sales_data &sales_data::combine(const sales_data &rhs) { units_sold += rhs.units_sold; revenue += rhs.revenue; return *this; } sales_data &sales_data::operator =(const sales_data &rhs) { this->bookno = rhs.bookno; this->revenue = rhs.revenue; this->units_sold = rhs.units_sold; return *this; } sales_data &sales_data::operator =(const std::string &rhs) { *this = sales_data(rhs); return *this; } sales_data &sales_data::operator +=(const sales_data &rhs) { this->revenue += rhs.revenue; this->units_sold += rhs.units_sold; return *this; } sales_data add(const sales_data &lhs, const sales_data &rhs) { sales_data sum = lhs; sum.combine(rhs); return sum; } istream &read(istream &is, sales_data &item) { double price = 0; is >> item.bookno >> item.units_sold >> price; item.revenue = price * item.units_sold; return is; } ostream &print(ostream &os, const sales_data &item) { os << item.isbn() << " " << item.units_sold << " "<< item.revenue << " " << item.avg_price(); return os; } std::ostream &operator <<(std::ostream &os, const sales_data &item) { os << item.isbn() << " " << item.units_sold << " "<< item.revenue << " " << item.avg_price(); return os; } std::istream &operator >>(std::istream &is, sales_data &s) { double price; is >> s.bookno >> s.units_sold >> price; if (is) s.revenue = s.units_sold * price; else s = sales_data(); return is; }
#include #include #include #include #include //equal_range #include #include //accumulate #include #include "sales_data.h" typedef std::tuple::size_type, std::vector::const_iterator, std::vector::const_iterator> matches; typedef std::pair::size_type, std::pair::const_iterator, std::vector::const_iterator>>matches_pair; inline bool compareisbn(const sales_data &ls, const sales_data &rs) { return ls.isbn() < rs.isbn(); } std::vector findbook(const std::vector> &f, const std::string &book)//17.4 { std::vector ret; for (auto it = f.cbegin(); it != f.cend(); ++it) { auto found = equal_range(it->cbegin(), it->cend(), book, compareisbn); if (found.first != found.second) ret.push_back(make_tuple(it - f.cbegin(), found.first, found.second)); } return ret; } std::vector findbook_pair(const std::vector> &f, const std::string &book)//17.5 { std::vector ret; for (auto it = f.cbegin(); it != f.cend(); ++it) { auto found = equal_range(it->cbegin(), it->cend(), book, compareisbn); if (found.first != found.second) ret.push_back(make_pair(it - f.cbegin(), make_pair(found.first, found.second))); } return ret; } struct matches_struct//17.6 { std::vector::size_type st; std::vector::const_iterator first; std::vector::const_iterator second; matches_struct(std::vector::size_type s, std::vector::const_iterator fi, std::vector::const_iterator se) :st(s), first(fi), second(se) {} }; std::vector findbook_struct(const std::vector> &f, const std::string &book) { std::vector ret; for (auto it = f.cbegin(); it != f.cend(); ++it) { auto found = equal_range(it->cbegin(), it->cend(), book, compareisbn); if (found.first != found.second) ret.push_back(matches_struct(it - f.cbegin(), found.first, found.second)); } return ret; } void reportrestults(std::istream &is, std::ostream &os, const std::vector> &f) { std::string s; while (is >> s) { auto tran = findbook(f, s); if (tran.empty()) { std::cout << s << " not found in any stores" << std::endl; continue; } for (const auto &x : tran) os << "store " << std::get<0>(x) << " sales: " << std::accumulate(std::get<1>(x), std::get<2>(x), sales_data(s)) << std::endl; } } std::vector *write_sales(std::fstream &f) { sales_data temp; auto ptr = new std::vector; while (read(f, temp)) { ptr->push_back(temp); } return ptr; } int main(int argc,char **argv) { using namespace std; fstream f1(argv[1]), f2(argv[2]), f3(argv[3]); if (!f1&&!f2&&!f3) { cerr << "error!"; exit(1); } std::vector> file; file.push_back(*write_sales(f1)); file.push_back(*write_sales(f2)); file.push_back(*write_sales(f3)); reportrestults(cin, cout, file); system("pause"); return 0; }
17.7
更倾向于tuple,相对于其他版本,它更方便
17.8
创建的是使用sales_data默认构造函数创建的对象
这样的结果就是书名为空,其他数据为0
17.9
a、00000000 00000000 00000000 00000000 00000000 00000000 00000000 00100000
b、00000000 00001111 01101001 10110101
c、视输入的内容而定,但是输入的字符非0或1那么就会抛出invalid_argument异常
17.10
#include #include int main() { using namespace std; int v[] = { 1,2,3,5,8,13,31 }; bitset<32> bit1; for (auto x : v) bit1.set(x); bitset<32> bit2; for (size_t i = 0; i < bit1.size(); ++i) bit2[i] = bit1[i]; cout << bit1 << endl << bit2; system("pause"); return 0; }
17.11、17.12、17.13
#pragma once #include #include #include template class bit //17.11 { std::bitset bit; public: bit() = default; bit(std::string &s) :bit(s) {} void updata(size_t n, bool b) //17.12 { bit.set(n, b); } template //17.13 friend size_t text(const bit &lb, const bit &rb); template friend std::ostream &operator<<(std::ostream &os, const bit &b); }; template size_t text(const bit &lb, const bit &rb) { auto temp = lb.bit^rb.bit; //得出答错的题目 temp.flip(); //翻转所有 return temp.count(); //返回答对的题目 } template std::ostream &operator<<(std::ostream &os, const bit &b) { os << b.bit; return os; }
17.14
#include #include #include int main() { using namespace std; try { regex reg("[^cei"); } catch (regex_error e){ cout << e.what() << "\ncode: " << e.code() << endl; } system("pause"); return 0; }
17.15、17.16
#include #include #include int main() { using namespace std; regex reg("[[:alpha:]]*[^c]ei[[:alpha:]]*",regex::icase);//17.15 string str; smatch m; while (cin >> str&&str!="q") { if (regex_search(str, m, reg)) cout << str << " is ok" << endl; else cout << str << " is not ok" << endl; } reg = "[^c]ei";//17.16 好像...并没有什么变化 while (cin >> str&&str != "q") { if (regex_search(str, m, reg)) cout << str << " is ok" << endl; else cout << str << " not is ok" << endl; } system("pause"); return 0; }
17.17、17.18
#include #include #include #include #include int main(int argc, char **argv) { using namespace std; ifstream file(argv[1]); if (!file) { cerr << "open file error!"; exit(1); } string p("[^c]ei"); p = "[[:alpha:]]*" + p + "[[:alpha:]]*"; regex reg(p, regex::icase); string temp, str; while (getline(file, temp)) str = str + temp + "\n"; vector vec{ "albeit","beige","feint","heir","reign","their", "counterfeit","foreign","inveigh","rein","veil","deign", "forfeit","inveigle","seize","veineiderdown","freight", "leisure","skein","weigheight","heifer","neigh","sleigh", "weighteither","height","neighbour","sleight","weirfeign", "heinous neither surfeit weird" }; for (sregex_iterator it(str.begin(), str.end(), reg), end_it; it != end_it; ++it) { if (find(vec.begin(), vec.end(), it->str()) != vec.end())//17.8 continue; cout << it->str(); system("pause"); auto pos = it->prefix().length(); cout << it->prefix().str().substr(pos > 40 ? pos - 40 : 0) << "[> " << it->str() << "<]" << it->suffix().str().substr(0, 40) << endl; } system("pause"); return 0; }
17.19
m4和m6都是分隔符,两者必须是相同的字符,如果一方不匹配或两者不相同,那么就为true
17.20
#include #include #include bool valid(const std::smatch &m); int main() { using namespace std; string phone = "(\\()?(\\d{3})(\\))?([-. ])?(\\d{3})([-. ])?(\\d{4})"; regex reg; try { reg.assign(phone); } catch (regex_error e) { cout << e.what() << "\ncode: " << e.code(); } smatch m; string s; while (getline(cin, s)&&s!="q") { for (sregex_iterator it(s.begin(), s.end(), reg), end_it; it != end_it; ++it) { if (valid(*it)) cout << "valid: " << it->str() << endl; else cout << "not valid: " << it->str() << endl; } } system("pause"); return 0; } bool valid(const std::smatch &m) { if (m[1].matched)//如果存在"("左括号 // ")"右括号必须存在,和区号分隔符不存在,或区号分隔符为空格 return m[3].matched && (m[4].matched == 0 || m[4].str() == " "); else //如果不存在"("左括号 // ")"右括号必须不存在,和区号分隔符与号码分隔符必须相同 return !m[3].matched&&m[4].str() == m[6].str(); }
17.21
#include #include #include #include #include #include struct personinfo { std::string name; std::vector phones; }; bool valid(const std::smatch &m); bool read_record(std::istream &is, std::vector&people); void format_record(std::ostream &os, const std::vector &people); int main() { using namespace std; vector people; string filename; cout << "enter input file name:"; cin >> filename; ifstream fin(filename); if (read_record(fin, people)) { cout << "enter output file name:"; string outname; cin >> outname; ofstream fout(outname, ofstream::trunc); //覆盖文件:trunc format_record(fout, people); } else cout << "open file error:" << filename << endl; system("pause"); return 0; } bool valid(const std::smatch &m) { if (m[1].matched) return m[3].matched && (m[4].matched == 0 || m[4] == " "); else return !m[3].matched&&m[4].str() == m[6].str(); } bool read_record(std::istream &is, std::vector &people) { if (is) { std::string line, word; while (getline(is, line)) //读取一行到line { personinfo info; std::istringstream record(line); //关联流到line,把record绑定到要读取的行line record >> info.name; //把流中第一个字符串输入到name,这一行的第一个,也就是名字 while (record >> word) info.phones.push_back(word);//把名字后面的电话号码保存 people.push_back(info); //添加一个联系人 } return true; } else return false; } void format_record(std::ostream &os, const std::vector &people) { std::string phone = "(\\()?(\\d{3})(\\))?([-. ])?(\\d{3})([-. ]?)(\\d{4})"; std::regex reg; try { reg.assign(phone); } catch (std::regex_error e) { std::cout << e.what() << "\ncode: " << e.code() << std::endl; } std::smatch m; for (const auto &x : people) { std::ostringstream formatted, badnums; for (const auto &n : x.phones) { for (std::sregex_iterator it(n.begin(), n.end(), reg), end_it; it != end_it; ++it) { if (!valid(*it)) badnums << " " << n; //将数据放入流,暂时保存 else formatted << " " << n; } } if (badnums.str().empty()) os << x.name << " " << formatted.str() << std::endl; //将流中的数据以string的形式放入os流中 else std::cerr << "file error: " << x.name << " invalid number " << badnums.str() << std::endl; } }
17.22
#include #include #include bool valid(const std::smatch &m); int main() { using namespace std; string phone = "(\\()?(\\d{3})(\\))?([[:blank:]]*)?(\\d{3})([[:blank:]]*)?(\\d{4})"; //([[:blank:]])匹配0-哪个空格或制表符 regex reg; try { reg.assign(phone); } catch (regex_error e) { cout << e.what() << "\ncode: " << e.code(); } smatch m; string s; while (getline(cin, s)&&s!="q") { for (sregex_iterator it(s.begin(), s.end(), reg), end_it; it != end_it; ++it) { if (valid(*it)) cout << "valid: " << it->str() << endl; else cout << "not valid: " << it->str() << endl; } } system("pause"); return 0; } bool valid(const std::smatch &m) { if (m[1].matched)//如果存在"("左括号 // ")"右括号必须存在,和区号分隔符不存在,或区号分隔符为空格 return m[3].matched && (m[4].matched == 0 || m[4].str() == " "); else //如果不存在"("左括号 // ")"右括号必须不存在,和区号分隔符与号码分隔符必须相同 return !m[3].matched&&m[4].str() == m[6].str(); }
17.23
#include #include #include int main() { using namespace std; string s = "(\\d{5})([-])?(\\d{4})?"; string num; regex reg(s); smatch m; while (getline(cin, num) && num != "q") { for (sregex_iterator it(num.begin(), num.end(), reg), end_it; it != end_it; ++it) { if ((*it)[3].matched) cout << it->str(); else cout << it->str(1); cout << endl; } } system("pause"); return 0; }
17.24
#include #include #include int main() { using namespace std; string phone = "(\\()?(\\d{3})(\\))?([[:blank:]]*)?(\\d{3})([[:blank:]]*)?(\\d{4})"; regex reg; try { reg.assign(phone); } catch (regex_error e) { cout << e.what() << "\ncode: " << e.code(); } string fmt = "$2.$5.$7"; smatch m; string s; while (getline(cin, s) && s != "q") { cout << regex_replace(s, reg, fmt) << endl; } system("pause"); return 0; }
17.25
#include #include #include int main() { using namespace std; string pattern = "(\\()?(\\d{3})(\\))?([-. ])?(\\d{3})([-. ])?(\\d{4})"; string fmt = "$2.$5.$7"; regex r(pattern); string s; while (getline(cin, s)) { smatch result; regex_search(s, result, r); if (!result.empty()) { //prefix输出匹配前的字符 //format(fmt)输出匹配的格式的字符串 cout << result.prefix() << result.format(fmt) << endl; } else { cout << "木有匹配的" << endl; } } system("pause"); return 0; }
17.26
#include #include #include int main() { using namespace std; string pattern = "(\\()?(\\d{3})(\\))?([-. ])?(\\d{3})([-. ])?(\\d{4})"; string fmt = "$2.$5.$7"; regex r(pattern); string s; while (getline(cin, s)) { smatch result; regex_search(s, result, r); if (!result.empty()) { //prefix输出匹配前的字符 //suffix输出匹配的字符串后面的字符 cout << result.prefix() << result.suffix()<< endl; } else { cout << "木有匹配的" << endl; } } system("pause"); return 0; }
17.27
#include #include #include int main() { using namespace std; string p = "(\\d{5})(\\d{4})"; regex reg(p); string fmt = "$1-$2"; smatch m; string n; while (getline(cin, n) && n != "q") { cout << regex_replace(n, reg, fmt, regex_constants::match_flag_type::format_no_copy); } system("pause"); return 0; }
17.28、17.29、17.30
#include #include #include unsigned ran() //17.28 { std::default_random_engine e; std::uniform_int_distribution u; return u(e); } unsigned ran(unsigned s)//7.29 { std::default_random_engine e(s); std::uniform_int_distribution u; return u(e); } unsigned ran(unsigned s, int f, int l)//17.30 { std::default_random_engine e(s); std::uniform_int_distribution u(f, l); return u(e); } int main() { using namespace std; unsigned f, l; cout << ran() << endl; cout << ran(time(0)); cout << "enrer seed:"; cin >> f >> l; cout << ran(time(0), f, l); system("pause"); return 0; }
17.31
结果每次都相同。
因为引擎返回相同的随机数序列,所以必须在循环外声明引擎对象,否则每次循环都会创建一个新的引擎(随机数序列不变),而每次都会输出引擎的序列
17.32
resp不在作用域,找不到resp对象
如果在循环里创建resp:
do{
string resp;
}while(...);
在这里,while的前面循环体已经退出,释放所有在循环体定义的对象,所以resp已经不存在
17.33
#include #include #include #include #include #include std::map buildmap(std::ifstream &ifile) //初始化map { std::map temp; std::string str, f, s; while (getline(ifile, str)) { std::istringstream sst(str); sst >> f >> s; temp[f] = s; //把暗文对应的明文设置 } return temp; } std::string trans(const std::string &s, std::map &m)//转换 { auto temp = m.find(s); if (temp != m.end()) //如果是暗文 return m[s]; //返回暗文对应的明文 else return s; } std::string trans_random(const std::string &s, std::map &m)//转换 { auto temp = m.find(s); if (temp != m.end()) //如果是暗文 return (m[s]+"!"); //返回暗文对应的明文 else return s; } int main(int argc, char **argv) { using namespace std; ifstream ifpw(argv[1]), iftxt(argv[2]); if (!ifpw&&!iftxt) { cerr << "open file error!\n"; exit(1); } map pw(buildmap(ifpw)); //初始化密码文件 string temp, f; default_random_engine e; bernoulli_distribution b; bool t; while (getline(iftxt, temp)) { istringstream iss(temp); while (iss >> f) { t = b(e); if(t) cout << trans_random(f, pw) << " "; //输出f的明文(如果f是暗文) else cout << trans(f, pw) << " "; //输出f的明文(如果f是暗文) } cout << endl; } system("pause"); return 0; }
17.34、17.35、17.36
#include #include int main() { using namespace std; cout << unitbuf;//17.34 cout << boolalpha << (5 < 4 ? true : false) << noboolalpha << endl; cout << showpos << showbase << hex << 1000 << " " << oct << 1000 << " " << dec << 1000 << noshowbase << noshowpos << endl; cout << uppercase << 3.14159 << " " << hex << 1000 << dec << nouppercase << endl; cout << setfill('#') << setw(10) << internal << showpos << 1024 << noshowpos << nounitbuf << ends << endl << flush; cout << setw(10) << left <="" noskipws;="" while="" (cin="" >>="" ch&&ch="" !="q" )="" cout="" <<="" ch;="" cin="" skipws;="" endl;="" uppercase;="" 17.35="" "default="" format:="" "="" 100="" *="" sqrt(2.0)="" '\n'="" "scientific:="" scientific="" "fixed="" decimal:="" fixed="" "hexidecimal:="" uppercase="" hexfloat="" "use="" defaults:="" defaultfloat="" setfill('="" ');="" 17.36="" left="" setw(20)="" format:"="" setw(25)="" right="" "scientific:"="" decimal:"="" "hexidecimal:"="" defaults:"="" "\n\n";="" system("pause");="" return="" 0;="" }
17.37
#include #include int main(int argv, char **argc) { using namespace std; ifstream ifile(argc[1]); if (!ifile) { cout << "open file error!"; exit(1); } char ar[100]; do { ifile.getline(ar, 10);//当行超出10个字符时停止 cout << ar << ' '; } while (ifile); ifile.close(); system("pause"); return 0; }
17.38
#include #include int main(int argv, char **argc) { using namespace std; ifstream ifile(argc[1]); if (!ifile) { cout << "open file error!"; exit(1); } char ar[100]; do { ifile.getline(ar, 100,' '); cout << ar << ' '; } while (ifile); ifile.close(); system("pause"); return 0; }
17.39
#include #include #include int main(int argc, char **argv) { using namespace std; fstream iofile(argv[1],fstream::ate|fstream::in|fstream::out);//以只读、只写和文件指针跳到文件尾的方式打开 if (!iofile) { cerr << "open file error!"; exit(1); } auto end_mark = iofile.tellg();//返回当前文件指针的位置 iofile.seekg(0, fstream::beg);//文件指针跳到文件头,偏移0 size_t cnt = 0; string line; while (iofile&&iofile.tellg() != end_mark&&getline(iofile,line))//确定当前文件io流可用与文件当前位置不是原文件尾 { cnt += line.size() + 1;//增加当前行的长度,+1表示换行符也算 auto mark = iofile.tellg();//保存当前文件指针 iofile.seekp(0, fstream::end);//文件指针跳到文件尾 iofile << cnt;//写入长度 if (mark != end_mark)//确定原位置不是原文件尾 iofile << " "; iofile.seekg(mark); } iofile.seekp(0, fstream::end); iofile << "\n"; iofile.close(); system("pause"); return 0; }
下一篇: 井塘村在什么地方 井塘村简介