c++primer第五版第九章练习

9.1

a vector或duque

b duque

c vector


9.2

list<duque<int>> ldint;


9.3

需指向同一个容器 不能在begin之前


9.4

bool findint(vector<int>::iterator b,vector<int>::iterator e,int n)
{
	auto iter=b;
	while(iter!=e)
	{
		if(*iter==n)
			return true;
        ++iter;
	}
	return false;
}

9.5

vector<int>::iterator findint(vector<int>::iterator b,vector<int>::iterator e,int n)
{
	auto iter=b;
	while(iter!=e)
	{
		if(*iter==n)
			return iter;
++iter;
	}
	return NULL;
}


9.6

操作符 < 不能用于list的迭代器

while(iter1!=iter2) /* ... */

9.7

vector<int>::size_type


9.8

题目是"读取" list<string>::iterator 或者是 list<string>::const_iterator 都行,看程序是否需要修改

写入 list<string>::iterator


9.9

begin返回的是iterator迭代器,可用解引用运算符进行修改值,而cbegin返回的是const_iterator,无法通过解引用修改


9.10

it1 iterator it2、it3、it4const_iterator


9.11

1 vector<int> vint;//空

2 vector<int> vint(10);//10个值为零的元素

3 vector<int> vint(10,1);//10个值为1的元素

4 vector<int> vint{1,2,3};//3个值,分别为1 2 3

5 vector<int> vint(beg,end);//内容为迭代器beg到end前的元素

6 vector<int> vint(vint2);//内容为容器vint2的元素


9.12

接受一个容器必须是同类型的,而且是全部复制,接受迭代器的只需要对象的基本类型相同或可以转换即可而且还可以指定范围


9.13

#include <iostream>
#include <list>
#include <vector>

int main()
{
	using namespace std;
	list<int> lint = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
	vector<int> vint = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
	vector<double> vd1(lint.begin(),lint.end());
	vector<double> vd2(vint.begin(), vint.end());
	for (auto x : vd1)
		cout << x;
	for (auto x : vd2)
		cout << x;
	system("pause");
	return 0;
}

9.14

#include <iostream>
#include <list>
#include <string>
#include <vector>

int main()
{
	using namespace std;
	list<char *> lcp = { "123", "abc", "[];" };
	vector<string> vstr;
	vstr.assign(lcp.begin(), lcp.end());
	for (auto &x : vstr)
		cout << x << endl;

	system("pause");
	return 0;
}

9.15

#include <iostream>
#include <vector>

int main()
{
	using namespace std;
	vector<int> vint1 = { 1, 2, 3, 4, 5 };
	vector<int> vint2 = { 1, 2, 3, 4, 5 };
	vector<int> vint3 = { 1, 2, 3, 4 };
	cout << "vint1==vnt2 :" << (vint1 == vint2 ? "yes" : "no") << endl;
	cout << "vint1==vnt3 :" << (vint1 == vint3 ? "yes" : "no") << endl;
	system("pause");
	return 0;
}

9.16

#include <iostream>
#include <list>
#include <vector>
int main()
{
	using namespace std;
	list<int> lint = { 1, 2, 3, 4, 5 };
	vector<int> vint1 = { 1, 2, 3, 4, 5 };
	vector<int> vint2 = { 2, 3, 4, 5 };
	cout << (vector<int>(lint.begin(), lint.end()) == vint1 ? "yes" : "no") << endl;
	cout << (vector<int>(lint.begin(), lint.end()) == vint2 ? "yes" : "no") << endl;
	system("pause");
	return 0;
}

9.17

c1和c2必须是同类型的容器,而且基本类型必须相同

基本类型必须支持"<"运算符


9.18

#include <iostream>
#include <string>
#include <deque>

int main()
{
	using namespace std;
	deque<string> ds;
	string temp;
	while (cin >> temp)
	{
		ds.push_back(temp);
	}
	auto iter = ds.cbegin();
	while (iter != ds.cend())
	{
		cout << *iter++ << "\t";
	}
	system("pause");
	return 0;
}

9.19

#include <iostream>
#include <string>
#include <list>

int main()
{
	using namespace std;
	list<string> ds;
	string temp;
	while (cin >> temp)
	{
		ds.push_back(temp);
	}
	auto iter = ds.cbegin();
	while (iter != ds.cend())
	{
		cout << *iter++ << "\t";
	}
	system("pause");
	return 0;
}

9.20

#include <iostream>
#include <list>
#include <deque>
int main()
{
	using namespace std;
	list<int> li;
	int temp;
	while (cin >> temp)
		li.push_back(temp);
	deque<int> di1, di2;
	auto iterb = li.cbegin(), itere = li.cend();
	while (iterb != itere)
	{
		if (*iterb % 2 == 0)
			di1.push_back(*iterb);
		else
			di2.push_back(*iterb);
		++iterb;
	}
	for (auto x : di1)
		cout << x << "\t";
	cout << endl;
	for (auto x : di2)
		cout << x << "\t";
	system("pause");
	return 0;
}

9.21

相同,因为list的insert和vector的insert都是把值插入都迭代器之前和返回插入元素的迭代器。


9.22

死循环,iter的值没有改变

因为进行了insert操作,所以iter和mid迭代器失效(因为insert操作会把元素插入到iter之前,所以iter也失效)

while (iter != mid)
{
	if (*mid == some_val)
		mid = iv.insert(mid, 2 * some_val);
	else
		--mid
}

9.23

所有值都指向第一个元素


9.24

#include <iostream>
#include <vector>
int main()
{
	using namespace std;
	vector<int> vint;
	cout << vint.at(0);
	cout << vint[0];
	cout << vint.front();
	cout << *vint.begin();
	system("pause");
	return 0;
}

9.25

elem1==elem2 erase将删除elem1到elem2之前的元素[elem1,elem2) 也就是说什么也没发生

如果elem2是尾后迭代器,将删除elem1到结尾的所有元素

如果elem1和elem2都是尾迭代器然而还是什么都没发生


9.26

#include <iostream>
#include <list>
#include <vector>

int main()
{
	using namespace std;
	int ia[] = { 0, 1, 1, 2, 3, 5, 8, 13, 21, 55, 89 };
	list<int> lint(ia, end(ia));
	vector<int> vint(ia, end(ia));
	auto iter = lint.begin();
	while (iter != lint.end())
	{
		if (*iter % 2)
			iter = lint.erase(iter);
		else
			++iter;
	}
	auto iter1 = vint.begin();
	while (iter1 != vint.end())
	{
		if (!(*iter1 % 2))
			iter1 = vint.erase(iter1);
		else
			++iter1;
	}
	for (auto x : lint)
		cout << x << "\t";
	for (auto x : vint)
		cout << x << "\t";
	system("pause");
	return 0;
}

9.27

#include <iostream>
#include <forward_list>
int main()
{
	using namespace std;
	forward_list<int> fli;
	int temp;
	while (cin >> temp)
	{
		fli.push_front(temp);
	}
	auto iter = fli.before_begin(),beg=fli.begin();
	while (beg != fli.cend())
	{
		if (*beg % 2)
			beg = fli.erase_after(iter);				//删除iter地址的下一个元素,即iter位置的元素 该方法返回被删元素的下一个地址
		else
			iter = beg++;						//把iter设为beg之前
	}
	for (auto x : fli)
		cout << x << "\t";
	system("pause");
	return 0;
}

9.28

#include <iostream>
#include <forward_list>
#include <string>
void flsf(std::forward_list<std::string> &t, const std::string &s, const std::string &e);	
//接受一个string的forward list对象和两个string,在s出现的位置后插入e,没有找到s就在末尾插入e
int main()
{
	using namespace std;
	forward_list<string> fls;
	string temp;
	auto iter = fls.before_begin();
	while (cin >> temp)
	{
		iter=fls.insert_after(iter,temp);
	}
	flsf(fls, string("nonororo"), string("ikaro"));
	for (auto &x : fls)
		cout << x << " ";
	system("pause");
	return 0;
}
void flsf(std::forward_list<std::string> &t, const std::string &s, const std::string &e)
{
	auto iter = t.begin();
	std::cout << "fun" << std::endl;
	auto tend = iter;
	while (iter != t.end())
	{
		if (*iter == s)
		{
			t.insert_after(iter, e);
			return;
		}
		tend = iter++;
	}
	t.insert_after(tend, e);
}

9.29

在vec后面添加75个元素,值为默认构造

只保留前10个的值,其他的删除


9.30

基础类型必须有默认构造函数


9.31

list和forward_list没有定于"+=2"的操作,forward_list只有insert_after和erase_after

list:

#include <iostream>
#include <list>

int main()
{
	using namespace std;
	list<int> li = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
	auto iter = li.begin();
	while (iter != li.end())
	{
		if (*iter % 2)
		{
			iter = li.insert(iter, *iter);
			++iter; ++iter;
		}
		else
			iter = li.erase(iter);
	}
	for (auto x : li)
		cout << x << "\t";
	system("pause");
	return 0;
}
forward_list:

#include <iostream>
#include <forward_list>
int main()
{
	using namespace std;
	forward_list<int> fli = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
	auto iter = fli.begin(), siter = fli.before_begin();
	while (iter != fli.end())
	{
		if (*iter % 2)
		{
			iter = fli.insert_after(siter, *iter);
			++iter;					//跳过最后插入的元素与原有元素
			siter=iter++;				//把siter设为iter的前一个
		}
		else
		{
			iter = fli.erase_after(siter);		//删除迭代器的下一个元素,并把删除后元素的下一个地址返回
		}
	}
	for (auto x : fli)
		cout << x << "\t";
	system("pause");
	return 0;
}

9.32

不合法,不同编译器不同结果

因为调用insert时iter的值可能如期望的iter也可能是iter+1,这个视编译器而异


9.33

在使用insert插入新元素后原有迭代器失效

#include <iostream>
#include <vector>
using std::vector; using std::cout; using std::endl;
int main()
{
	vector<int> v{ 1, 2, 3, 4, 5, 6, 7, 8, 9 };
	auto begin = v.begin();
	while (begin != v.end()) {
		++begin;
		v.insert(begin, 42);
		++begin;
	}
	for (auto i : v)
		cout << i << " ";
	system("pause");
	return 0;
}


9.34

复制奇数并插入到原奇数之前,但是本题的while喜欢只是对if有效,++iter无效,可能是书本错误

并且根据书上的iter会一直指向第一个奇数,是死循环

改变后:

#include <iostream>
#include <vector>
int main()
{
	using namespace std;
	vector<int> vi = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
	auto iter = vi.begin();
	while (iter != vi.end())
	{
		if (*iter % 2)
		{
			iter = vi.insert(iter, *iter);
			iter += 2;
		}
		else
		{
			++iter;
		}
	}
	for (auto x : vi)
		cout << x << "\t";
	system("pause");
	return 0;
}

9.35

capacity是容器当前已分配的内存,表示当前最大容量

size是当前容器已有的元素的数量


9.36

不可能,最多是与size相等,当size大于capacity时会自动分配内存


9.37

list是链表,空间不是连续的

array的空间是定义时就固定的,无法改变


9.38

视编译器而异,本机是capacity在小于size自动增长为size的150%左右

#include <iostream>
#include <vector>

int main()
{
	using namespace std;
	vector<int> vi;
	cout << vi.size() << "\t" << vi.capacity() << endl;
	for (int i = 0; i<100; ++i)
		vi.push_back(i);
	cout << vi.size() << "\t" << vi.capacity() << endl;
	vi.shrink_to_fit();
	cout << vi.size() << "\t" << vi.capacity() << endl;
	vi.push_back(0);
	cout << vi.size() << "\t" << vi.capacity() << endl;
	system("pause");
	return 0;
}

9.39

一直从cin读取字符串到word并压入svec中,虽然svec设置了reserve(100),但这只是说明reserve在不进行新的空间分配的情况下最大我100个,但是当读取到101个时还是会自动增加空间(本机是150%左右地增加,即变成150),直到cin遇到结束字符或vector到达max_size。

然后调用resize重设大小为当前元素个数的150%,多出的50%的值为基本类型的默认构造函数


9.40

256 384     573
512 768     1149

....

#include <iostream>
#include <vector>
int main()
{
	using namespace std;
	vector<int> vi;
	for (int i = 0; i < 255; ++i)
		vi.push_back(i);
	vi.shrink_to_fit();
	vi.push_back(1);
	cout << vi.size() << "\t" << vi.capacity() << endl;
	vi.resize(vi.size() + vi.size() / 2);
	cout << vi.size() << "\t" << vi.capacity() << endl;
	system("pause");
	return 0;
}

9.41

#include <iostream>
#include <vector>
#include <string>
int main()
{
	using namespace std;
	vector<char> vc = { 'i', 'k', 'a', 'r', 'o' };
	string str(vc.begin(), vc.end());		//通过迭代器范围初始化
	cout << str << endl;
	system("pause");
	return 0;
}

9.42

使用reserve来分配更大的预存空间,避免重新分配内存的消耗


9.43

#include <iostream>
#include <string>
void freplace(std::string &s, const std::string &o, const std::string &n);//从s里面查找o的内容并全部替换为n
int main()
{
	using namespace std;
	string str, old, news;
	getline(cin, str);
	cout << "old new:";
	cin >> old >> news;
	freplace(str, old, news);
	cout << str << endl;
	system("pause");
	return 0;
}
void freplace(std::string &s, const std::string &o, const std::string &n)
{
	if (s.size() < o.size()||s.empty()||o.empty())				//n可以为空,代表删除
		return;
	for (auto iter = s.begin(); iter <= (s.end()-o.size()+1); ++iter)	//如果iter到达s的倒数第o.size()-1个元素,小于o大小的字符串后不需要检查
	{
		if (s.substr(iter-s.begin(),o.size()) == o)<span style="white-space:pre">			</span>//iter迭代器的位置减去头位置,得到距离,然后复制o.size()个,意思就是返回一个和o对象大小相同的string引用方便对比
		{
			iter = s.erase(iter, iter + o.size());			//删除匹配的范围
			iter = s.insert(iter, n.cbegin(), n.cend());		//插入新的内容,相对于替换就内容为n
			iter += n.size();					//跳过插入的元素
		}
	}
}

9.44

#include <iostream>
#include <string>
void freplace(std::string &s, const std::string &o, const std::string &n);//从s里面查找o的内容并全部替换为n
int main()
{
	using namespace std;
	string str, old, news;
	getline(cin, str);
	cout << "old new:";
	cin >> old >> news;
	freplace(str, old, news);
	cout << str << endl;
	system("pause");
	return 0;
}
void freplace(std::string &s, const std::string &o, const std::string &n)
{
	if (s.size() < o.size() || s.empty() || o.empty())			//n可以为空,代表删除
		return;
	std::string::size_type i = 0;
	while(i <= (s.size() - o.size()))
	{
		if (s.substr(i, o.size()) == o)
		{
			s.replace(i, o.size(), n);
			i += n.size();
		}
		else
			++i;
	}
}


9.45

#include <iostream>
#include <string>

std::string newstr(const std::string &s, const std::string &f, const std::string &l);

int main()
{
	using namespace std;
	string name, fname, lname;
	cout << "nme fname name:";
	cin >> name >> fname >> lname;
	name = newstr(name, fname, lname);
	cout << name << endl;
	system("pause");
	return 0;
}
std::string newstr(const std::string &s, const std::string &f, const std::string &l)
{
	std::string str = s;
	str.insert(str.begin(), f.begin(), f.end());
	str.append(l);
	return str;
}

9.46

#include <iostream>
#include <string>
std::string newstr(const std::string &s, const std::string &f, const std::string &l);
int main()
{
	using namespace std;
	string name, fname, lname;
	cout << "nme fname name:";
	cin >> name >> fname >> lname;
	name = newstr(name, fname, lname);
	cout << name << endl;
	system("pause");
	return 0;
}
std::string newstr(const std::string &s, const std::string &f, const std::string &l)
{
	std::string str = s;
	str.insert(str.begin(), f.begin(), f.end());
	str.insert(str.end(), l.begin(), l.end());
	return str;
}


9.47

#include <iostream>
#include <string>
void fshowe(const std::string &s);
void fshown(const std::string &s);
int main()
{
	using namespace std;
	string str("ab2c3d7R4E6");
	fshowe(str);
	cout << endl;
	fshown(str);
	system("pause");
	return 0;
}
void fshown(const std::string &s)
{
	std::string n = {"1234567890" };
	for (std::string::size_type i = 0; i <s.size();++i)
	{
		if ((i = s.find_first_of(n,i)) != std::string::npos)	//在位置i开始查找第一个与n中内容相同的字符
			std::cout << s[i];
		else
			break;
	}
}
void fshowe(const std::string &s)
{
	std::string n = { "qwertyuiopasdfghjklzxcvbnmQWERTYUIOPASDFGHJKLZXCVBNM" };
	for (std::string::size_type i = 0; i < s.size();++i)
	{
		if ((i = s.find_first_of(n, i)) != std::string::npos)
			std::cout << s[i];
		else
			break;
	}
}

9.48

string:npos


9.49

#include <iostream>
#include <fstream>
#include <string>
int main(int argc, char **argv)
{
	using namespace std;
	ifstream ifile(argv[1]);
	string e = "acenmorsuvwxz";
	string str,maxstr;
	string::size_type msize = 0;
	while (ifile >> str)
	{
		if (str.find_first_not_of(e) == string::npos&&str.size() > msize)	//如果没有在str中找到与e中不同的字母并且这个单词比前一个记录的长
		{
			msize = str.size();
			maxstr = str;
		}
	}
	ifile.close();
	cout << maxstr << endl;
	return 0;
}

9.50

#include <iostream>
#include <string>
#include <vector>

int stoint(const std::vector<std::string> &s);
double stodouble(const std::vector<std::string> &s);
int main()
{
	using namespace std;
	vector<string> vsint;
	cout << "enter string:";
	string temp;
	while (cin >> temp)
	{
		vsint.push_back(temp);
	}
	int sum = stoint(vsint);
	cout << sum << endl;
	vector<string> vsdouble;
	cout << "enter string:";
	cin.clear();
	while (cin >> temp)
	{
		vsdouble.push_back(temp);
	}
	double dt = stodouble(vsdouble);
	cout << dt << endl;
	system("pause");
	return 0;
}
int stoint(const std::vector<std::string> &s)
{
	int sum = 0;
	for (auto &x:s)
	{
		sum += stoi(x);
	}
	return sum;
}
double stodouble(const std::vector<std::string> &s)
{
	double sum = 0;
	for (auto &x : s)
	{
		sum += stoi(x);
	}
	return sum;
}

9.51

#include <iostream>
#include <string>
#define E "qwertyuiopasdfghjklzxcvbnmQWERTYUIOPASDFGHJKLZXCVBNM"
#define N "0123456789"
#define C "qwertyuiopasdfghjklzxcvbnmQWERTYUIOPASDFGHJKLZXCVBNM0123456789"
class data
{
	unsigned y;
	unsigned m;
	unsigned d;
public:
	data(std::string s)
	{
		if (s.find_first_of(E) == std::string::npos)<span style="white-space:pre">		</span>//如果不包含英文
		{
			std::string::size_type dd=0, mm=0, yy=0;
			dd = stoi(s.substr(0, s.find_first_not_of(N)));	//截取第一段、第二段、第三段
			mm = stoi(s.substr(s.find_first_not_of(N)+1, s.find_first_not_of(N) - s.find_last_not_of(N)));
			yy = stoi(s.substr(s.find_last_not_of(N) + 1));
			if (dd < 13)<span style="white-space:pre">					</span>//如果是以月份为头
			{
				m = dd;
				if (mm < 32)<span style="white-space:pre">				</span>//如果中间是日期
				{
					d = mm;
					y = yy;
				}
				else
				{
					y = mm;
					d = yy;
				}
			}
			else if (dd > 32)<span style="white-space:pre">				</span>//如果以年份为头
			{
				y = dd;
				if (mm < 13)<span style="white-space:pre">				</span>//如果中间是月份
				{
					m = mm;
					d = yy;
				}
				else
				{
					d = mm;
					m = yy;
				}
			}
			else			<span style="white-space:pre">			</span>//否则就是以日期为头
			{
				d = dd;
				if (mm < 13)	<span style="white-space:pre">			</span>//如果中间是月份
				{
					m = mm;
					y = yy;
				}
				else
				{
					m = yy;
					y = mm;
				}
			}
		}
		else
		{
			std::string::size_type f, l, a, b;
			std::string temp1 = s.substr(f = s.find_first_of(E), l = s.find_last_of(E)+1);//截取英文部分
			if (f == 0)	<span style="white-space:pre">				</span>//如果以因为为头
			{
				a = stoi(s.substr(l+1, s.find_last_not_of(N)));
				b = stoi(s.substr(s.find_last_not_of(N) + 1));
			}
			else if (s.find_last_not_of(C) + 1 == f)	//如果以英文结尾
			{
				a = stoi(s.substr(0, s.find_first_not_of(N)));
				b = stoi(s.substr(s.find_first_not_of(N) + 1, s.find_last_of(N)));
			}
			else	<span style="white-space:pre">					</span>//以英文在中间
			{
				a = stoi(s.substr(0, s.find_first_not_of(N)));
				b = stoi(s.substr(s.find_last_not_of(N) + 1));
			}<span style="white-space:pre">						</span>//判断月份
			if (s.find("Jan") != std::string::npos)  m = 1;
			if (s.find("Feb") != std::string::npos)  m = 2;
			if (s.find("Mar") != std::string::npos)  m = 3;
			if (s.find("Apr") != std::string::npos)  m = 4;
			if (s.find("May") != std::string::npos)  m = 5;
			if (s.find("Jun") != std::string::npos)  m = 6;
			if (s.find("Jul") != std::string::npos)  m = 7;
			if (s.find("Aug") != std::string::npos)  m = 8;
			if (s.find("Sep") != std::string::npos)  m = 9;
			if (s.find("Oct") != std::string::npos)  m = 10;
			if (s.find("Nov") != std::string::npos)  m = 11;
			if (s.find("Dec") != std::string::npos)  m = 12;
			if (a < 32)<span style="white-space:pre">					</span>//判断日期与年份
			{
				d = a;
				y = b;
			}
			else
			{
				d = b;
				y = a;
			}
		}
	}
	friend std::ostream &operator<<(std::ostream &os, const data &d)
	{
		os << d.y << "/" << d.m << "/" << d.d << "\n";
		return os;
	}
};
int main()
{
	using namespace std;
	string temp;
	cout << "enter data:";
	getline(cin, temp);
	data time(temp);
	cout << time << endl;
	system("pause");
	return 0;
}

9.52

表示看不懂题目










......好吧,看了几遍于是有点头目

大概意思是把一个字符串里的括号(包含括号,不管什么内容)的内容替换为指定内容

一个栈stack<char> sc;要把"aaa a(a(ds)d(sd))aa aa(aaaa(aaa((a)aa)s))aa"用替换掉,例:变成aaa a#aa aa#aa

#include <iostream>
#include <stack>
#include <string>
int main()
{
	using namespace std;
	string str;
	getline(cin, str);
	int s = 0;
	stack<char> sc;
	for (auto x : str)
	{
		sc.push(x);
		if (x == '(')				
			++s;				//记录'('出现的次数
		if (x == ')'&&s)			//如果之前出现过'('和现在是')'
		{
			while (sc.top() != '(')<span style="white-space:pre">		</span>//弹出刚刚加入的元素,一直到'(',相当于删除了"***)"括号
				sc.pop();			
			sc.pop();			//删除'('
			sc.push('@');			//插入@标记表示这里删除过
			--s;
		}
	}
	string st;
	while (!sc.empty())				//如果sc不为空
	{						//把sc的内容全部复制到st并删除sc所有的内容
		st.insert(st.begin(), sc.top());//把最后一个内容弹出并插入到st的最前面
		sc.pop();				//弹出并删除刚刚弹出的内容
	}
	cout << st << endl;
	system("pause");
	return 0;
}





OK,复习完











  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值