C++ Primer(第五版)|練習題答案與解析(第十七章:標準庫特殊設施)
本博客主要記錄C++ Primer(第五版)中的練習題答案與解析。
參考:C++ Primer
練習題17.1
定義一個保存三個int值的tuple,並將其分別初始化爲10,20和30。
練習題17.2
定義一個tuple,保存一個string、一個vector<string>和一個pair<string, int>
#include <tuple>
#include <string>
#include <vector>
int main()
{
auto three_ints = std::make_tuple(10, 20, 30);
using SomeTuple = std::tuple < std::string, std::vector<std::string>, std::pair<std::string, int> > ;
SomeTuple some_tuple;
return 0;
}
練習題17.4
編寫並測試你自己版本的findBook函數
練習題17.5
重寫findBook,令其返回一個pair,包含一個索引和迭代器pair。
練習題17.6
重寫findBook,不使用tuple或pair。
練習題17.7
解釋你更傾向哪一個版本findBook。
練習題17.8
在本節最後一段代碼中,如果將Sales_data()作爲第三個參數傳給accumulate,會發生什麼?
搬運:C++ Primer
SalesData.h
#ifndef SALES_DATA_H
#define SALES_DATA_H
#include <string>
#include <iostream>
class Sales_data
{
// friends
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:
// constructors
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&);
// assignments
Sales_data& operator =(const Sales_data& rhs);
Sales_data& operator =(const std::string& rhs);
Sales_data& operator +=(const Sales_data& rhs);
// conversion
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;
};
// overloaded operators added 10.Jan.2014 for ex14.2
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);
// nonmember Sales_data interface functions
Sales_data add(const Sales_data&, const Sales_data&);
std::ostream &print(std::ostream&, const Sales_data&);
std::istream &read(std::istream&, Sales_data&);
// used in future chapters
inline
bool compareIsbn(const Sales_data &lhs, const Sales_data &rhs)
{
return lhs.isbn() < rhs.isbn();
}
#endif
SalesData.cpp
#include <iostream>
using std::istream; using std::ostream;
#include "SalesData.h"
Sales_data::Sales_data(std::istream &is)
{
// read will read a transaction from is into this object
read(is, *this);
}
double
Sales_data::avg_price() const {
if (units_sold)
return revenue/units_sold;
else
return 0;
}
// add the value of the given Sales_data into this object
Sales_data&
Sales_data::combine(const Sales_data &rhs)
{
units_sold += rhs.units_sold; // add the members of rhs into
revenue += rhs.revenue; // the members of ``this'' object
return *this; // return the object on which the function was called
}
// = Sales_data
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;
}
// =string
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; // copy data members from lhs into sum
sum.combine(rhs); // add data members from rhs into sum
return sum;
}
// transactions contain ISBN, number of copies sold, and sales price
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;
}
// added 10.Jan 2014
std::ostream &
operator <<(std::ostream &os, const Sales_data &item)
{
os << item.isbn() << " " << item.units_sold << " "
<< item.revenue << " " << item.avg_price();
return os;
}
// added 12.Jan 2014
std::istream&
operator >>(std::istream &is, Sales_data &s)
{
double price;
// read input
is >> s.bookNo >> s.units_sold >> price;
// if successful, write into the object, give the object default state otherwise.
if(is)
s.revenue = s.units_sold * price;
else
s = Sales_data();
return is;
}
mian.cpp
#include <iostream>
#include <tuple>
#include <string>
#include <vector>
#include <algorithm>
#include <utility>
#include <numeric>
#include "SalesData.h"
// for ex17.4
// maches has 3 members:
// an index of a store and iterators into that store's vector
typedef std::tuple<std::vector<Sales_data>::size_type,
std::vector<Sales_data>::const_iterator,
std::vector<Sales_data>::const_iterator>
matches;
// for ex17.5
// return a pair that holds an index and a pair of iterators.
typedef std::pair<std::vector<Sales_data>::size_type,
std::pair<std::vector<Sales_data>::const_iterator,
std::vector<Sales_data>::const_iterator>>
matches_pair;
// for ex17.6
// return a struct that holds an index of a store and iterators into that store's vector
struct matches_struct
{
std::vector<Sales_data>::size_type st;
std::vector<Sales_data>::const_iterator first;
std::vector<Sales_data>::const_iterator last;
matches_struct(std::vector<Sales_data>::size_type s,
std::vector<Sales_data>::const_iterator f,
std::vector<Sales_data>::const_iterator l) : st(s), first(f), last(l) { }
} ;
// for ex17.4
// return a vector with an entry for each store that sold the given book.
std::vector<matches>
findBook(const std::vector<std::vector<Sales_data>>& files,
const std::string& book);
// print the result using the given iostream
void reportResults(std::istream& in, std::ostream os,
const std::vector<std::vector<Sales_data>>& files);
// for ex17.5
// return a vector with an entry for each store that sold the given book.
std::vector<matches_pair>
findBook_pair(const std::vector<std::vector<Sales_data> > &files,
const std::string &book);
// for ex17.6
// return a vector with an entry for each store that sold the given book.
std::vector<matches_struct>
findBook_struct(const std::vector<std::vector<Sales_data> > &files,
const std::string &book);
int main()
{
return 0;
}
// for ex17.4
// return a vector with an entry for each store that sold the given book.
std::vector<matches>
findBook(const std::vector<std::vector<Sales_data>>& files,
const std::string& book)
{
std::vector<matches> ret;
// for each strore find the range of matching books, if any
for (auto it = files.cbegin(); it != files.cend(); ++it)
{
// find the range of Sales_data tat have the same ISBN
auto found = std::equal_range(it->cbegin(), it->cend(), book, compareIsbn);
if(found.first != found.second)
ret.push_back(std::make_tuple(it - files.cbegin(),
found.first, found.second));
}
return ret;
}
// for ex17.4
// print the result using the given iostream
void reportResults(std::istream& in, std::ostream os,
const std::vector<std::vector<Sales_data>>& files)
{
std::string s;
while(in >> s)
{
auto trans = findBook(files, s);
if(trans.empty()){
std::cout << s << "not found in any stores" << std::endl;
continue;
}
for(const auto& store :trans)
os << "store " << std::get<0>(store) << " sales: "
<< std::accumulate(std::get<1>(store), std::get<2>(store),
Sales_data(s))
<< std::endl;
}
}
// for ex17.5
// return a vector with an entry for each store that sold the given book
std::vector<matches_pair>
findBook_pair(const std::vector<std::vector<Sales_data> > &files,
const std::string &book)
{
std::vector<matches_pair> ret;
for(auto it = files.cbegin(); it != files.cend(); ++it)
{
auto found = std::equal_range(it->cbegin(), it->cend(), book, compareIsbn);
if(found.first != found.second)
ret.push_back(std::make_pair(it - files.cbegin(),
std::make_pair(found.first, found.second)));
}
return ret;
}
// for ex17.6
// return a vector with an entry for each store that sold the given book.
std::vector<matches_struct>
findBook_struct(const std::vector<std::vector<Sales_data> > &files,
const std::string &book)
{
std::vector<matches_struct> ret;
for(auto it = files.cbegin(); it != files.cend(); ++it)
{
auto found = std::equal_range(it->cbegin(), it->cend(), book, compareIsbn);
if(found.first != found.second)
ret.push_back(matches_struct(it - files.cbegin(), found.first, found.second));
}
return ret;
}
練習題17.9
解釋下列每個bitset對象所包含的位模式。
(a)(a) bitset<64> bitvec(32);
0000000000000000000000000000000000000000000000000000000000100000
// ^
(b)bitset<32> bv(1010101);
輸出:00000000000011110110100110110101
(c)string bstr; cin >> bstr; bitset<8>bv(bstr);
取決於輸入了什麼。
練習題17.10
使用序列1、2、3、5、8、13、21初始化一個bitset,將這些位置位。對另一個bitset進行默認初始化,並編寫程序將其恰當的位置位。
#include <iostream>
#include <bitset>
#include <vector>
int main()
{
std::vector<int> v = { 1, 2, 3, 5, 8, 13, 21 };
std::bitset<32> bset;
for (auto i : v) bset.set(i);
std::bitset<32> bset2;
for (unsigned i = 0; i != 32; ++i)
bset2[i] = bset[i];
std::cout <<bset <<std::endl;
std::cout <<bset2<<std::endl;
}
測試
00000000001000000010000100101110
00000000001000000010000100101110
練習題17.11
定義一個數據結構,包含一個整型對象,記錄一個包含10個問題的真/假測驗的解答,如果測驗包含100道題,你需要對數據結構做出什麼改變?
練習題17.12
使用前一題的數據結構,編寫一個函數,它接受一個問題的編號和一個表示真/假解答的值,函數根據這兩個參數更新測驗的解答。
練習題17.13
編寫一個整型對象,包含真/假測驗的正確答案。使用它來爲前兩題中的數據結構生成測驗成績。
#ifndef QUIZ
#define QUIZ
#include <iostream>
#include <bitset>
#include <utility>
#include <string>
#include <iostream>
//class Quiz
template<std::size_t N>
class Quiz
{
public:
//constructors
Quiz() = default;
Quiz(std::string& s) :bitquiz(s){ }
//generate grade
template<std::size_t M>
friend std::size_t grade(Quiz<M> const&, Quiz<M> const&);
//print
template<std::size_t M>
friend std::ostream& operator<<(std::ostream&, Quiz<M> const&);
//update bitset
void update(std::pair<std::size_t, bool>);
private:
std::bitset<N> bitquiz;
};
#endif
template<std::size_t N>
void Quiz<N>::update(std::pair<std::size_t, bool> pair)
{
bitquiz.set(pair.first, pair.second);
}
template<std::size_t M>
std::ostream& operator<<(std::ostream& os, Quiz<M> const& quiz)
{
os << quiz.bitquiz;
return os;
}
template<std::size_t M>
std::size_t grade(Quiz<M> const& corAns, Quiz<M> const& stuAns)
{
auto result = stuAns.bitquiz ^ corAns.bitquiz;
result.flip();
return result.count();
}
int main()
{
std::cout << "練習題17.11" << std::endl;
std::string s = "1010101";
Quiz<10> quiz(s);
std::cout << quiz << std::endl;
std::cout << "練習題17.12" << std::endl;
quiz.update(std::make_pair(1, true));
std::cout << quiz << std::endl;
std::cout << "練習題17.13" << std::endl;
std::string answer = "10011";
std::string stu_answer = "11001";
Quiz<5> ans(answer), stu_ans(stu_answer);
std::cout << grade(ans, stu_ans) << std::endl;
return 0;
}
測試:
練習題17.11
0001010101
練習題17.12
0001010111
練習題17.13
3
練習題17.14
編寫幾個正則表達式,分別觸發不同錯誤。運行你的程序,觀察編譯器對每個錯誤的輸出。
練習題17.15
編寫程序,使用模式查找“i在e之前,除非在e之後”規則的單詞。你的程序應該提示用戶輸入一個單詞,然後指出此單詞是否符合要求。用一些違反和違反規則的單詞測試你的程序。
練習題17.16
如果前一題程序中的regex對象用“[^c]ei”進行初始化,會發生什麼?測試你的程序。
#include <iostream>
using std::cout;
using std::cin;
using std::endl;
#include <string>
using std::string;
#include <regex>
using std::regex;
using std::regex_error;
int main()
{
// for ex17.14
// error_brack
std::cout<<"練習題17.14:"<<std::endl;
try{
regex r("[[:alnum:]+\\.(cpp|cxx|cc)$", regex::icase);
}
catch(regex_error e)
{
cout << e.what() << " code: " << e.code() << endl;
}
// for ex17.15
std::cout<<"練習題17.15:"<<std::endl;
regex r("[[:alpha:]]*[^c]ei[[:alpha:]]*", regex::icase);
string s;
cout << "Please input a word! Input 'q' to quit!" << endl;
while(cin >> s && s != "q")
{
if(std::regex_match(s, r))
cout << "Input word " << s << " is okay!" << endl;
else
cout << "Input word " << s << " is not okay!" <<endl;
cout << "Please input a word! Input 'q' to quit!" << endl;
}
cout << endl;
// for ex17.16
std::cout<<"練習題17.16:"<<std::endl;
r.assign("[^c]ei", regex::icase);
cout << "Please input a word! Input 'q' to quit!" << endl;
while(cin >> s && s != "q")
{
if(std::regex_match(s, r))
cout << "Input word " << s << " is okay!" << endl;
else
cout << "Input word " << s << " is not okay!" <<endl;
cout << "Please input a word! Input 'q' to quit!" << endl;
}
return 0;
}
測試:
練習題17.14:
regex_error code: 4
練習題17.15:
Please input a word! Input 'q' to quit!
input
Input word input is not okay!
Please input a word! Input 'q' to quit!
eixt
Input word eixt is not okay!
Please input a word! Input 'q' to quit!
cied
Input word cied is not okay!
Please input a word! Input 'q' to quit!
ie
Input word ie is not okay!
Please input a word! Input 'q' to quit!
ei
Input word ei is not okay!
Please input a word! Input 'q' to quit!
q
練習題17.16:
Please input a word! Input 'q' to quit!
exit
Input word exit is not okay!
Please input a word! Input 'q' to quit!
ei
Input word ei is not okay!
Please input a word! Input 'q' to quit!
q
練習題17.17
更新你的程序,令他查找輸入序列中所有違反“ei”語法規則的單詞。
練習題17.18
修改你的程序,忽略包含“ei”但並非拼寫錯誤的單詞,如“albeit”和“neighbor”。
#include <iostream>
using std::cout;
using std::cin;
using std::endl;
#include <string>
using std::string;
#include <regex>
using std::regex;
using std::sregex_iterator;
int main()
{
string s;
cout << "Please input a sequence of words:" << endl;
getline(cin, s);
cout << endl;
cout << "Word(s) that violiate the \"ei\" grammar rule:" << endl;
string pattern("[^c]ei");
pattern = "[[:alpha:]]*" + pattern + "[[:alpha:]]*";
regex r(pattern, regex::icase);
for (sregex_iterator it(s.begin(), s.end(), r), end_it; it != end_it; ++it)
cout << it->str() << endl;
return 0;
}
測試:
Please input a sequence of words:
albeit
Word(s) that violiate the "ei" grammar rule:
albeit
練習題17.19
爲什麼不先檢查m[4]是否匹配了就直接調用m[4].str()?
我們期望m[4]和m[6]中的兩個分隔符是相同的。如果m[4](或m[6])不匹配,則m[4].str()(或m[6].str()分別)返回一個空字符串,該字符串也可以與其他分隔符進行比較。
練習題17.20
編寫你自己版本的驗證電話號碼程序。
#include <iostream>
using std::cout;
using std::cin;
using std::endl;
#include <string>
using std::string;
#include <regex>
using std::regex;
using std::sregex_iterator;
using std::smatch;
bool valid(const smatch& m);
int main()
{
string phone = "(\\()?(\\d{ 3 })(\\))?([-. ])?(\\d{ 3 })([-. ]?)(\\d{ 4 })";
regex r(phone);
smatch m;
string s;
bool valid_record;
// read each record from the input file
while (getline(cin, s))
{
valid_record = false;
// for each matching phone number
for (sregex_iterator it(s.begin(), s.end(), r), end_it; it != end_it; ++it)
{
valid_record = true;
// check whether the number's formatting is valid
if (valid(*it))
cout << "valid phone number: " << it->str() << endl;
else
cout << "invalid phone number: " << it->str() << endl;
}
if (!valid_record)
cout << "invalid record!" << endl;
}
return 0;
}
bool valid(const smatch& m)`在這裏插入代碼片`
{
// if there is an open parenthesis before the area code
if (m[1].matched)
// the area code must be followed by a close parenthesis
// and followed immediately by the rest of the number or a space
return m[3].matched && (m[4].matched == 0 || m[4].str() == " ");
else
// then there can't be a close after the area code
// the delimiters between the other two components must match
return !m[3].matched && m[4].str() == m[6].str();
}
練習題17.21
使用本節定義的valid函數重寫8.3.2節中的電話號碼程序。
#include <iostream>
using std::cerr;
using std::cout;
using std::cin;
using std::endl;
using std::istream;
using std::ostream;
#include <fstream>
using std::ifstream;
using std::ofstream;
#include <sstream>
using std::istringstream;
using std::ostringstream;
#include <string>
using std::string;
#include <vector>
using std::vector;
#include <regex>
using std::regex;
using std::sregex_iterator;
using std::smatch;
struct PersonInfo
{
string name;
vector<string> phones;
};
bool valid(const smatch& m);
bool read_record(istream& is, vector<PersonInfo>& people);
void format_record(ostream& os, const vector<PersonInfo>& people);
// fake function that makes the program compile
string format(const string &num) { return num; }
int main()
{
vector<PersonInfo> people;
string filename;
cout << "Please input a record file name: ";
cin >> filename;
cout << endl;
ifstream fin(filename);
if (read_record(fin, people))
{
ofstream fout("data\\result.txt", ofstream::trunc);
format_record(fout, people);
}
else
{
cout << "Fail to open file " << filename << endl;
}
return 0;
}
bool valid(const smatch& m)
{
// if there is an open parenthesis before the area code
if (m[1].matched)
// the area code must be followed by a close parenthesis
// and followed immediately by the rest of the number or a space
return m[3].matched && (m[4].matched == 0 || m[4].str() == " ");
else
// then there can't be a close after the area code
// the delimiters between the other two components must match
return !m[3].matched && m[4].str() == m[6].str();
}
bool read_record(istream& is, vector<PersonInfo>& people)
{
if (is)
{
string line, word; // will hold a line and word from input, respectively
// read the input a line at a time until cin hits end-of-file (or another error)
while (getline(is, line))
{
PersonInfo info; // create an object to hold this record's data
istringstream record(line); // bind record to the line we just read
record >> info.name; // read the name
while (record >> word) // read the phone numbers
info.phones.push_back(word); // and store them
people.push_back(info); // append this record to people
}
return true;
}
else
return false;
}
void format_record(ostream& os, const vector<PersonInfo>& people)
{
string phone = "(\\()?(\\d{ 3 })(\\))?([-. ])?(\\d{ 3 })([-. ]?)(\\d{ 4 })";
regex r(phone);
smatch m;
for (const auto &entry : people)
{
// for each entry in people
ostringstream formatted, badNums; // objects created on each loop
for (const auto &nums : entry.phones)
{
for (sregex_iterator it(nums.begin(), nums.end(), r), end_it; it != end_it; ++it)
{
// for each number
// check whether the number's formatting is valid
if (!valid(*it))
// string in badNums
badNums << " " << nums;
else
// "writes" to formatted's string
formatted << " " << format(nums);
}
}
if (badNums.str().empty()) // there were no bad numbers
os << entry.name << " " // print the name
<< formatted.str() << endl; // and reformatted numbers
else // otherwise, print the name and bad numbers
cerr << "input error: " << entry.name
<< " invalid number(s) " << badNums.str() << endl;
}
}
練習題17.23
編寫查找郵政編碼的正則表達式。一個美國的郵政編碼可以由五位數或九位數字組成。前五位數字和後四位數字之間可以用一個短橫線分隔。
#include <iostream>
using std::cout;
using std::cin;
using std::endl;
#include<string>
using std::string;
#include <regex>
using std::regex;
using std::sregex_iterator;
using std::smatch;
bool valid(const smatch& m);
int main()
{
string zipcode =
"(\\d{5})([-])?(\\d{4})?\\b";
regex r(zipcode);
smatch m;
string s;
while (getline(cin, s))
{
//! for each matching zipcode number
for (sregex_iterator it(s.begin(), s.end(), r), end_it;
it != end_it; ++it)
{
//! check whether the number's formatting is valid
if (valid(*it))
cout << "valid zipcode number: " << it->str() << endl;
else
cout << "invalid zipcode number: " << s << endl;
}
}
return 0;
}
bool valid(const smatch& m)
{
if ((m[2].matched)&&(!m[3].matched))
return false;
else
return true;
}
測試:
55555-5555
valid zipcode number: 55555-5555
練習題17.24
編寫你自己版本的重排電話號碼格式的程序。
#include <iostream>
#include <regex>
#include <string>
using namespace std;
string pattern = "(\\()?(\\d{3})(\\))?([-. ])?(\\d{3})([-. ])?(\\d{4})";
string format = "$2.$5.$7";
regex r(pattern);
string s;
int main()
{
while(getline(cin,s))
{
cout<<regex_replace(s,r,format)<<endl;
}
return 0;
}
測試:
drew (973)555.0130
drew 973.555.0130
morgan (201) 555-2368 862-555-0123
morgan 201.555.2368 862.555.0123
lee (609) 555-0132 2015550175 800.555-0000
lee 609.555.0132 201.555.0175 800.555.0000
練習題17.25
重寫你的電話號碼程序,使之只輸出每個人的第一個電話號碼。
#include <iostream>
#include <regex>
#include <string>
using namespace std;
string pattern = "(\\()?(\\d{3})(\\))?([-. ])?(\\d{3})([-. ])?(\\d{4})";
string fmt = "$2.$5.$7";
regex r(pattern);
string s;
int main()
{
while(getline(cin,s))
{
smatch result;
regex_search(s,result,r);
if(!result.empty())
{
cout<<result.prefix()<<result.format(fmt)<<endl;
}
else
{
cout<<"Sorry, No match."<<endl;
}
}
return 0;
}
測試:
morgan (201) 555-2368 862-555-0123
morgan 201.555.2368
練習題17.27
編寫程序,將九位數字郵政編碼轉換爲ddddd-dddd
#include <iostream>
#include <regex>
#include <string>
using namespace std;
string pattern = "(\\d{5})([.- ])?(\\d{4})";
string fmt = "$1-$3";
regex r(pattern);
string s;
int main()
{
while(getline(cin,s))
{
smatch result;
regex_search(s,result, r);
if(!result.empty())
{
cout<<result.format(fmt)<<endl;
}
else
{
cout<<"Sorry, No match."<<endl;
}
}
return 0;
}
測試:
941551234
94155-1234
555784612
55578-4612
練習題17.28
編寫函數,每次調用生成並返回一個均勻分佈的隨機unsigned int。
練習題17.29
修改上一題中編寫的函數,允許用戶提供一個這種作爲可選參數。
練習題17.30
再次修改,此次再增加兩個參數,表示函數允許返回的最小值和最大值。
#include <iostream>
#include <random>
#include<string>
// default version
unsigned random_gen();
// with seed spicified
unsigned random_gen(unsigned seed);
// with seed and range spicified
unsigned random_gen(unsigned seed, unsigned min, unsigned max);
int main()
{
std::string temp;
while(std::cin >> temp)
std::cout << std::hex << random_gen(19, 1, 10) << std::endl;
return 0;
}
unsigned random_gen()
{
static std::default_random_engine e;
static std::uniform_int_distribution<unsigned> ud;
return ud(e);
}
unsigned random_gen(unsigned seed)
{
static std::default_random_engine e(seed);
static std::uniform_int_distribution<unsigned> ud;
return ud(e);
}
unsigned random_gen(unsigned seed, unsigned min, unsigned max)
{
static std::default_random_engine e(seed);
static std::uniform_int_distribution<unsigned> ud(min, max);
return ud(e);
}
```+-
## 練習題17.33
>修改11.3.6節(P392)中的單詞轉換程序,允許對一個給定單詞有多種轉換方式,每次修改隨機選擇一種進行實際轉換。
```cpp
#include <iostream>
using std::cout;
using std::endl;
#include <fstream>
using std::ifstream;
#include <string>
using std::string;
#include <vector>
using std::vector;
#include <random>
using std::default_random_engine;
using std::uniform_int_distribution;
#include <ctime>
using std::time;
#include <algorithm>
using std::sort;
using std::find_if;
#include <utility>
using std::pair;
int main() {
typedef pair<string, string> ps;
ifstream i("d.txt");
vector<ps> dict;
string str1, str2;
// read wirds from dictionary
while (i >> str1 >> str2) {
dict.emplace_back(str1, str2);
}
i.close();
// sort words in vector
sort(dict.begin(), dict.end(), [](const ps &_ps1, const ps &_ps2){ return _ps1.first < _ps2.first; });
i.open("i.txt");
default_random_engine e(unsigned int(time(0)));
// read words from text
while (i >> str1) {
// find word in dictionary
vector<ps>::const_iterator it = find_if(dict.cbegin(), dict.cend(),
[&str1](const ps &_ps){ return _ps.first == str1; });
// if word doesn't exist in dictionary
if (it == dict.cend()) {
// write it itself
cout << str1 << ' ';
}
else {
// get random meaning of word
uniform_int_distribution<unsigned> u (0, find_if(dict.cbegin(), dict.cend(),
[&str1](const ps &_ps){ return _ps.first > str1; }) - it - 1);
// write random meaning
cout << (it + u(e))->second << ' ';
}
}
return 0;
}
練習題17.35
修改P670頁中的程序,打印2的平方根,但這次打印十六進制數字的大寫形式。
練習題17.36
修改上一題中的程序,打印不同的浮點數,使它們排成一列。
#include <iostream>
#include <iomanip>
#include <math.h>
using namespace std;
int main()
{
std::cout << "練習題17.35:" << std::endl;
cout << "default format: " << 100 * sqrt(2.0) << '\n'
<< "scientific: " << scientific << 100 * sqrt(2.0) << '\n'
<< "fixed decimal: " << fixed << 100 * sqrt(2.0) << '\n'
<< "hexidecimal: " << uppercase << hexfloat << 100 * sqrt(2.0) << '\n'
<< "use defaults: " << defaultfloat << 100 * sqrt(2.0)
<< "\n\n";
std::cout << "練習題17.36:" << std::endl;
cout << left << setw(15) << "default format:" << setw(25) << right << 100 * sqrt(2.0) << '\n'
<< left << setw(15) << "scientific:" << scientific << setw(25) << right << 100 * sqrt(2.0) << '\n'
<< left << setw(15) << "fixed decimal:" << setw(25) << fixed << right << 100 * sqrt(2.0) << '\n'
<< left << setw(15) << "hexidecimal:" << setw(25) << uppercase << hexfloat << right << 100 * sqrt(2.0) << '\n'
<< left << setw(15) << "use defaults:" << setw(25) << defaultfloat << right << 100 * sqrt(2.0)
<< "\n\n";
}
測試:
練習題17.35:
default format: 141.421
scientific: 1.414214e+02
fixed decimal: 141.421356
hexidecimal: 0X1.1AD7BCP+7
use defaults: 141.421
練習題17.36:
default format: 141.421
scientific: 1.414214E+02
fixed decimal: 141.421356
hexidecimal: 0X1.1AD7BCP+7
use defaults: 141.421
練習題17.37
用爲格式化版本的getline逐行讀取一個文件。測試你的程序,給它一個文件,既包含空行又包含長度超過你傳遞給getline的字符數組大小的行。
#include <iostream>
#include <fstream>
#include <iomanip>
using namespace std;
int main () {
ifstream myfile("test.txt");
if (myfile) cout << 1 << endl;
char sink [250];
while(myfile.getline(sink,250))
{
cout << sink << endl;
}
return 0;
}
測試:
1
I'm expressin' with my full capabilities,
And now I'm livin' in correctional facilities,
Cause some don't agree with how I do this.
I get straight, meditate like a Buddhist
I'm droppin' flava, my behaviour is heriditery,
But my technique is very necessary.
Blame it on Ice Cube... Because he says it gets funky
When you got a subject and a predacit.
Add it on a dope beat
And that'll make you think.
Some suckaz just tickle me pink
To my stomache. 'Cause they don't flow like this one.
You know what? I won't hesitate to dis one
Or two before I'm through.
So don't try to sing this!
Some drop science
While I'm droppin' English.
Even if Yella
Makes it a-capella
I still express, yo, I don't smoke weed or a sess.
Cause its known to give a brother brain damage.
And brain damage on the mic don't manage
Nuthin'
But makin' a sucker and you equal.
Don't be another sequel...
這節是過了一遍,待用上的時候仔細看。