c++ primer第五版----学习笔记(十七)Ⅱ

部分习题解答:

17.1、17.2:

#include <iostream>
#include <tuple>
#include <string>
#include <vector>
#include <utility>
using namespace std;

int main(int argc, char **argv)
{
	tuple<int, int, int> tp{ 10,20,30 };
	cout << get<0>(tp) << " " << get<1>(tp) << " " << get<2>(tp) << " " << endl;
	tuple<string, vector<string>, pair<string, int>> tup;
	system("pause");
    return 0;
}

17.3:

#ifndef TEXTQUERY_H
#define TEXTQUERY_H
#include <iostream>
#include <vector>
#include <string>
#include <map>
#include <set>
#include <fstream>
#include <sstream>
#include <tuple>

using namespace std;

class TextQuery {
public:
	using line_no = vector<string>::size_type;
	using QueryResult = tuple< string, shared_ptr<set<line_no>>, shared_ptr<vector<string>>>;
public:
	TextQuery(ifstream&);                          //读取文本,建立联系
	QueryResult query(const string&) const;
private:
	shared_ptr<vector<string>> file;                 //输入文件
	map<string, shared_ptr<set<line_no>>> wm;        //单词与行号关联的map
};

TextQuery::TextQuery(ifstream& is) : file(new vector<string>)
{
	string text;
	while (getline(is, text))          //文件中的每一行,按行读取
	{
		file->push_back(text);          //保存该行文本
		int n = file->size() - 1;       //当前文本行号
		istringstream line(text);      //对于行中的每一个单词
		string word;
		while (line >> word)
		{
			auto &lines = wm[word];    //得到一个shared_ptr指针
			if (!lines)                //如果该指针为空,则分配一个新的set
				lines.reset(new set<line_no>);
			lines->insert(n);           //将行号插入set中
		}
	}
}
TextQuery::QueryResult TextQuery::query(const string &s) const
{
	//如果未找到给定单词,则返回一个指针
	static shared_ptr<set<line_no>> nodata(new set<line_no>);
	//使用find查找,避免将单词插入到wm中
	auto loc = wm.find(s);
	if (loc == wm.end())
	{
		return QueryResult( s, nodata, file );
	}
	else
		return QueryResult(s, loc->second, file);
}
#endif
//test.cpp
#include <iostream>
#include <tuple>
#include <string>
#include <vector>
#include <utility>
#include "TextQuery.h"
using namespace std;

ostream &print(ostream &os, const TextQuery::QueryResult &qr)
{
	os << get<0>(qr) << "\n";
	for (auto num : *get<1>(qr))
	{
		os << "\t(lint " << num + 1 << ") " << *(get<2>(qr)->begin() + num) << endl;
	}
	return os;
}
int main(int argc, char **argv)
{
	ifstream isfile("17.txt");
	if (!isfile)
	{
		cout << "can't open the file" << endl;
		exit(1);
	}
	TextQuery tq(isfile);
	print(cout, tq.query("c++"));
	system("pause");
        return 0;
}

17.4、17.5、17.6:

bool compareIsbn(const Sales_data &lhs, const Sales_data &rhs)
{
	return lhs.isbn() < rhs.isbn();
}
//17.4
typedef tuple<vector<Sales_data>::size_type,
	vector<Sales_data>::const_iterator,
	vector<Sales_data>::const_iterator> matches;
vector<matches>
findBook(const vector<vector<Sales_data>> &files, const string &book)
{
	vector<matches> ret;
	for (auto it = files.cbegin(); it != files.cend(); ++it)
	{
		auto found = equal_range(it->cbegin(), it->cend(), book, compareIsbn);
		if (found.first != found.second)
			ret.push_back(make_tuple(it - files.cbegin(), found.first, found.second));
	}
	return ret;
}
//17.5
vector<matches_pair>
findBook(const vector<vector<Sales_data>> &files, const string &book)
{
	vector<matches_pair> ret;
	for (auto it = files.cbegin(); it != files.cend(); ++it)
	{
		auto found = equal_range(it->cbegin(), it->cend(), book, compareIsbn);
		if (found.first != found.second)
			ret.push_back(make_pair(it - files.cbegin(), make_pair(found.first, found.second)));
	}
	return ret;
}
//17.6
struct matches_struct {
	vector<Sales_data>::size_type st;
	vector<Sales_data>::const_iterator fir;
	vector<Sales_data>::const_iterator sec;
	matches_struct(vector<Sales_data>::size_type s, vector<Sales_data>::const_iterator first, 
		vector<Sales_data>::const_iterator second):st(s),fir(first),sec(second){}
};
vector<matches_struct>
findBook(const vector<vector<Sales_data>> &files, const string &book)
{
	vector<matches_struct> ret;
	for (auto it = files.cbegin(); it != files.cend(); ++it)
	{
		auto found = 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.7:
更倾向于tuple,相比其他更为方便
17.8:
创建的是使用Sales_data默认构造函数创建的对象,使用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 <iostream>
#include <bitset>
using namespace std;

int main(int argc, char **argv)
{
	int xulie[] = { 1,2,3,5,8,13,21 };
	bitset<32> bit1;
	for (auto x : xulie)
		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:

#ifndef  BIT_H
#define BIT_H

#include <iostream>
#include <string>
#include <bitset>
using namespace std;

template <unsigned N>
class Bit {
	bitset<N> bit;
public:
	Bit() = default;
	Bit(string &s) : bit(s) { }
	void updata(int n, bool b)    //更新测验的答案
	{
		bit.set(n, b);
	}

	template <unsigned M>
	size_t text(const Bit<M> &lb, const Bit<M> &rb);     //生成测验成绩

	template <unsigned M>
	friend ostream& operator<<(ostream &os, const Bit<M> &lb);   //重载输出运算符
};

template <unsigned M>
size_t Bit<M>::text(const Bit<M> &lb, const Bit<M> &rb)
{
	auto tmp = lb.bit ^ rb.bit;    //找出错误问题(^是按位异或)
	tmp.flip();                    //将所有位翻转
	return tmp.count();            //得出正确答案
}

template <unsigned M>
ostream& operator<<(ostream &os, const Bit<M> &lb)
{
	os << lb.bit;
	return os;
}
#endif // ! BIT_H

17.14:

#include <iostream>
#include <bitset>
#include <regex>
using namespace std;

int main(int argc, char **argv)
{
	try {
		regex r("[^cei");
		regex f("[z-a]");
	}
	catch(regex_error e)
	{
		cout << e.what() << "\node: " << e.code() << endl;
		//regex_error(error_brack): The expression contained mismatched [ and ].
                                //code: 4
	}
	try {
		regex f("[z-a]");
	}
	catch (regex_error e)
	{
		cout << e.what() << "\node: " << e.code() << endl;
		//regex_error(error_range): The expression contained an invalid character range, such as [b-a] in most encodings.
                               // code: 8
	}
	system("pause");
        return 0;
}

17.15、17.16: 

#include <iostream>
#include <bitset>
#include <regex>
using namespace std;

int main(int argc, char **argv)
{
	regex r("[[:alpha:]]*[^c]ei[[:alpha:]]*", regex::icase);
	string word;
	smatch results;
	cout << "please input word: ";
	while (cin >> word)
	{
		if (regex_search(word, results, r))
		{
			cout << word << " is ok" << endl;
		}
		else
			cout << word << " is not ok" << endl;
	}
	cin.clear();   //重置输入流
	r = "[^c]ei";
	cout << "please input word: ";
	while (cin >> word)
	{
		if (regex_search(word, results, r))
		{
			cout << word << " is ok" << endl;
		}
		else
			cout << word << " is not ok" << endl;
	}
	system("pause");
        return 0;
}

17.17、17.18:

#include <iostream>
#include <fstream>
#include <string>
#include <regex>
using namespace std;

int main(int argc, char **argv)
{
	ifstream file("17.17.txt");
	if (!file)
	{
		cout << "file open wrong!" << endl;
		exit(1);
	}
	regex r("[[:alpha:]]*[^c]ei[[:alpha:]]*", regex::icase);
	string tmp, str;
	while (getline(file, tmp))
	{
		str += tmp + "\n";
	}
	vector<string> 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(), r), end_it; it != end_it; ++it)
	{
		if (find(vec.begin(), vec.end(), it->str()) != vec.end())
			continue;
		cout << it->str() << endl;
		auto pos = it->prefix().length();
		pos = pos > 40 ? pos - 40 : 0;
		cout << it->prefix().str().substr(pos)
			<< "\n\t\t>>> " << it->str() << " <<<\n"
			<< it->suffix().str().substr(0, 40)
			<< endl;
	}
	system("pause");
        return 0;
}

17.19:
m[4]和m[6]都是分隔符,两者必须是相同的,若一方不匹配或两者不相同,返回false
17.20:

#include <iostream>
#include <string>
#include <regex>
using namespace std;

bool valid(const 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();
}
int main(int argc, char **argv)
{
	string phone = "(\\()?(\\d{3})(\\))?([-. ])?(\\d{3})([-. ])?(\\d{4})";
	regex r(phone);
	smatch m;
	string s;
	while (getline(cin, s))
	{
		for (sregex_iterator it(s.begin(), s.end(), r), 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;
}

17.21:

#include <iostream>
#include <sstream>
#include <fstream>
#include <string>
#include <vector>
#include <regex>

struct PersonInfo {
	std::string name;
	std::vector<std::string> phones;
};
bool valid(const std::smatch &m);
bool read_record(std::istream &is, std::vector<PersonInfo> &people);
void format_record(std::ostream &os, const std::vector<PersonInfo> &people);

int main()
{
	using namespace std;
	vector<PersonInfo> 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<PersonInfo> &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<PersonInfo> &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:

std::string phone = "(\\()?(\\d{3})(\\))?([-. ])?(\\d{3})([-. ]?)(\\d{4})";

改为
 

string phone = "(\\()?(\\d{3})(\\))?([[:blank:]]*)?(\\d{3})([[:blank:]]*)?(\\d{4})";

17.23:

#include <iostream>
#include <string>
#include <regex>
using namespace std;

bool valid(const smatch& m)
{
	//若存在分隔符且匹配
	if (m[2].matched)
		//则后4位也要匹配
		return m[3].matched;
	else
		return 1;
}
int main(int argc, char **argv)
{
	string post_code = "(\\d{5})([-])?(\\d{4})?";
	regex r(post_code);
	smatch m;
	string s;
	while (getline(cin, s))
	{
		for (sregex_iterator it(s.begin(), s.end(), r), 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;
}

17.24:

#include <iostream>
#include <string>
#include <regex>
using namespace std;

int main(int argc, char **argv)
{
	string phone = "(\\()?(\\d{3})(\\))?([-. ])?(\\d{3})([-. ]?)(\\d{4})";
	regex r(phone);
	smatch m;
	string s;
	string fmt = "$2.$5.$7";
	while (getline(cin, s))
	{
		cout << regex_replace(s, r, fmt) << endl;
	}
	system("pause");
	    return 0;
}

17.25:

#include <iostream>
#include <sstream>
#include <string>
#include <regex>
using namespace std;

int main(int argc, char **argv)
{
	using std::regex_constants::format_no_copy;
	string phone = "(\\()?(\\d{3})(\\))?([-. ])?(\\d{3})([-. ]?)(\\d{4})";
	regex r(phone);
	string s;
	string fmt = "$2.$5.$7";
	while (getline(cin, s))
	{
		smatch result;
		regex_search(s, result, r);  //先找到所有匹配的字符串,然后进行格式转换
		if (!result.empty())
		{
			cout << result.format(fmt, format_no_copy) << endl;
		}
		else
			cout << "没有匹配!" << endl;
	}
	system("pause");
	    return 0;
}

17.26: 

#include <iostream>
#include <sstream>
#include <string>
#include <regex>
using namespace std;

int main(int argc, char **argv)
{
	using std::regex_constants::format_no_copy;
	string phone = "(\\()?(\\d{3})(\\))?([-. ])?(\\d{3})([-. ]?)(\\d{4})";
	regex r(phone);
	string s;
	string fmt = "$2.$5.$7";
	while (getline(cin, s))
	{
		smatch result;
		regex_search(s, result, r);
		if (!result.empty())
		{
			string str = result.suffix();
			cout << regex_replace(str,r,fmt,format_no_copy) << endl;
		}
		else
			cout << "没有匹配!" << endl;
	}
	system("pause");
	    return 0;
}

17.27:

#include <iostream>
#include <sstream>
#include <string>
#include <regex>
using namespace std;

int main(int argc, char **argv)
{
	using std::regex_constants::format_no_copy;
	string post_code = "(\\d{5})(\\d{4})";
	regex r(post_code);
	string fmt = "$1-$2";
	string s;
	while (getline(cin, s))
	{
		cout << regex_replace(s, r, fmt, format_no_copy) << endl;
	}
	system("pause");
	return 0;
}

17.28、17.29、17.30:

#include <iostream>
#include <sstream>
#include <string>
#include <regex>
#include <random>
using namespace std;

unsigned ran()   //17.28
{
	default_random_engine e;
	uniform_int_distribution<unsigned> u;
	return u(e);
}

unsigned ran(unsigned s)   //17.29
{
	default_random_engine e(s);
	uniform_int_distribution<unsigned> u;
	return u(e);
}

unsigned ran(unsigned s, unsigned min, unsigned max)   //17.30
{
	default_random_engine e(s);
	uniform_int_distribution<unsigned> u(min, max);
	return u(e);
}
int main(int argc, char **argv)
{
	unsigned min, max;
	cout << ran() << endl;
	cout << ran(time(0)) << endl;
	cin >> min >> max;
	cout << ran(time(0), min, max);
	system("pause");
	return 0;
}

17.31:
如果在do循环内定义b和e,引擎返回的随机数序列相同
17.32:
在循环内定义resp,当while前面的循环体已退出,释放所有在循环体定义的对象,所以resp不存在
17.33:

#include <iostream>
#include <fstream>
#include <sstream>
#include <vector>
#include <string>
#include <list>
#include <map>
#include <set>
#include <algorithm>
#include <random>
using namespace std;

map<string, string>
buildmap(ifstream &map_file)
{
	map<string, string> trans_map;         //保存转换规则
	string key;          //要转换的单词
	string value;        //替换后的内容
						 //读取第一个单词存入key中,行中剩余内容存入value
	while (map_file >> key && getline(map_file, value))
	{
		if (value.size() > 1)
		{
			trans_map[key] = value.substr(1);    //value为关键字之后的所有字符,包括与关键字之间的空格,所以令参数为1消去空格
		}
		else
			throw runtime_error("no rule for " + key);
	}
	return trans_map;
}
string 
transform(const string &s, const map<string, string> &m)
{
	auto map_it = m.find(s);
	//如果单词在转换规则之中
	if (map_it != m.cend())
	{
		return map_it->second;        //使用替换短语
	}
	else
		return s;                    //如果单词不在转换规则中,则返回原单词
}
string 
transform_random(const string &s,  map<string, string> &m)
{
	auto map_it = m.find(s);
	//如果单词在转换规则之中
	if (map_it != m.cend())
	{
		return m[s] + "!";        //使用替换短语
	}
	else
		return s;                    //如果单词不在转换规则中,则返回原单词
}
void word_transform(ifstream &map_file, ifstream &input)
{
	auto trans_map = buildmap(map_file);   //保存转换规则
	string text;      //保存输入的每一行
	static default_random_engine e;
	static bernoulli_distribution b;
	bool t;
	while (getline(input, text))           //读取每一行输入
	{
		istringstream stream(text);        //读取一行中的每个单词
		string word;
		bool firstword = true;             //控制是否打印空格
		while (stream >> word)
		{
			if (firstword)                //如果读取的单词不为空,则之后打印一个空格
				firstword = false;
			else
				cout << " ";
			t = b(e);
			if (!t)
				cout << transform(word, trans_map); //将需要转换的单词转换
			else
				cout << transform_random(word, trans_map);
		}
		cout << endl;
	}
}
int main(int argc, char**argv)
{
	ifstream map_file("17.txt");
	ifstream input("17.33.txt");
	word_transform(map_file, input);
	system("pause");
	return 0;
}

17.34、7.35、17.36:

#include <iostream>
#include <iomanip>
using namespace std;

int main()
{
	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 << fixed << 3.14 << " " << right
		<< scientific << 3.14 << endl;
	cout << hexfloat << 3.14159 << endl;
	cout << setprecision(3) << 3.14159 << endl;
	cout << setbase(8) << 1000 << endl;
	char ch;
	cin >> noskipws;
	while (cin >> ch && ch != 'q')
		cout << ch;
	cin >> skipws;
	cout << endl;


	cout << uppercase;//17.35
	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)
		<< endl;

	cout << setfill(' ');//17.36
	cout << left << setw(20) << "default format:" << setw(25) << right << 100 * sqrt(2.0) << '\n'
		<< left << setw(20) << "scientific:" << scientific << setw(25) << right << 100 * sqrt(2.0) << '\n'
		<< left << setw(20) << "fixed decimal:" << setw(25) << fixed << right << 100 * sqrt(2.0) << '\n'
		<< left << setw(20) << "hexidecimal:" << setw(25) << uppercase << hexfloat << right << 100 * sqrt(2.0) << '\n'
		<< left << setw(20) << "use defaults:" << setw(25) << defaultfloat << right << 100 * sqrt(2.0)
		<< "\n\n";
	system("pause");
	return 0;
}

17.37:

#include <iostream>
#include <iomanip>
#include <vector>
#include <fstream>
using namespace std;

int main(int argc, char **argv)
{
	ifstream ifile("17.37.txt");
	if (!ifile)
	{
		cout << "can't open the file" << endl;
		exit(1);
	}
	char array[100];
	do {
		ifile.getline(array, 10);
		cout << array << " ";
	} while (ifile);
	ifile.close();
	system("pause");
	return 0;
}

17.38:

#include <iostream>
#include <iomanip>
#include <vector>
#include <fstream>
using namespace std;

int main(int argc, char **argv)
{
	ifstream ifile("17.37.txt");
	if (!ifile)
	{
		cout << "can't open the file" << endl;
		exit(1);
	}
	char array[100];
	do {
		ifile.getline(array, 100,' ');
		cout << array << " ";
	} while (ifile);
	ifile.close();
	system("pause");
	return 0;
}

17.39:

#include <iostream>
#include <iomanip>
#include <string>
#include <fstream>
using namespace std;

int main(int argc, char **argv)
{
	fstream ifile("17.37.txt", fstream::ate | fstream::in | fstream::out);   //以只读、只写和文件指针跳到文件尾的方式打开
	if (!ifile)
	{
		cout << "Unable to open file" << endl;
		return EXIT_FAILURE;
	}
	auto end_mark = ifile.tellg();       //记住原文件尾位置
	ifile.seekg(0, fstream::beg);        //重定位到文件开始
	size_t cnt = 0;                      //字节数累加器
	string line;                         //保存输入中的每行
	//继续读取的条件,还未遇到错误且还存在读取数据
	while (ifile && ifile.tellg () != end_mark && getline(ifile, line) )
	{
		cnt += line.size() + 1;               //加1表示换行符
		auto mark = ifile.tellg();           //记住读取位置
		ifile.seekp(0, fstream::end);         //将写标记移动到文件尾
		ifile << cnt;                        //输出累计的长度
		if (mark != end_mark)                //如果不是最后一行,打印一个分隔符
			ifile << " ";             
		ifile.seekg(mark);                    //恢复读位置
	}
	ifile.seekp(0, fstream::end);          //定位到文件尾
	ifile << "\n";                              //在文件尾输出一个换行符
	return 0;
	system("pause");
	return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_38790716/article/details/83417433