第10章 泛型算法

C++ primer 5th 第10章 泛型算法

=====================================================================

第10章 泛型算法      336页    算法algorithm头文件

=====================================================================

//QQ108201645编写
#include <iostream>
#include <vector>
#include <string>
#include <list>
#include <algorithm>
using namespace std;

int main()
{
	vector<int> ivec = { 1,2,3,4,5,6};
	int ival = 42;//我们想查找的值
	//如果在vec中找到想要的元素,则返回结果指向它,否则返回结果为vec.cend()
	auto res = find(ivec.begin(), ivec.end(), ival);
	cout << "the value " << ival
		<< (res == ivec.cend() ? " is not present" : " is present")
		<< endl;

	list<string> lst{ "hello ","a value ","world" };
	string s = "a value ";
	//此调用在list中查找元素
	auto res1 = find(lst.begin(), lst.end(), s);
	cout << s << " is " << (res1 == lst.cend() ? "No" : "Yes") << endl;

	int ia[] = { 27,210,12,47,109,83 };
	int val = 83;
	int* res2= find(begin(ia), end(ia), val);
	cout << *res2 << endl;

	//在从ia[1]开始,直到(但不包含)的ia[4]的范围内查找元素
	auto res3 = find(ia + 1, ia + 4, val);
	system("pause");
	return 0;
}
#ifdef DECLARATION
find的工作实在一个未排序的元素序列中寻找一个特定的元素,执行的步骤:

1. 访问序列中的首元素。

2. 比较此元素与我们要查找的元素。

3. 如果此元素与我们要查找的值匹配,find返回标识此元素的值。

4. 否则,find前进到下一个元素,重复执行步骤2和3。

5. 如果到达序列末尾,find应停止。

6. 如果find到达序列末尾,他应该返回一个指出元素未找到的值。此值和步骤3
返回的值必须具有相容的类型。
#endif

=====================================================================

第10章 泛型算法      337页    练习题

=====================================================================

//QQ108201645编写
#include <iostream>
#include <vector>
#include <string>
#include <list>
#include <algorithm>
using namespace std;

int main()
{
	/*练习10.1:头文件algorithm中定义了一个名为count的函数,它类似find,接受
	一对迭代器和一个值作为参数。count返回给定值在序列中出现的次数。编写程序,读
	取int序列存入vector中,打印有多少个元素的值等于给定值。*/
	vector<int> ivec = { 1,2,3,4,5,6,1,2,3,4,5,3,2 };
	int ival = count(ivec.begin(), ivec.end(), 2);//统计2出现的次数,返回该值并传给ival
	cout << ival << endl;//输出内容:3

	/*练习10.2:重做上一题,但读取string序列存入 list 中。*/
	list<string> slst = { "abc","def","abc" };
	string s = "abc";
	int value = count(slst.begin(), slst.end(), s);//查找"abc"出现的次数
	cout << value << endl;//输出内容:2

	system("pause");
	return 0;
}

=====================================================================

#include<vector>
#include<algorithm>
#include<iostream>
using namespace std;

bool SearchVal(vector<int>& v, int val)
{
	if (find(v.begin(), v.end(), val) != v.end())//如果结果不等v1.end表示找到,
	{
		int cnt = count(v.begin(), v.end(), val);//val出现的次数
		cout << cnt << endl;
		return true;
	}
	else
		cout << "未找到 " << val << endl;
	return false;
}
int main()
{
	vector<int> v1 = { 7,1,2,3,4,5,6,7,1,3,5,7 };
	int val = 100;
	SearchVal(v1, val);//查找100出现的次数

	SearchVal(v1, 7);//查找7出现次数

	system("pause");
	return 0;

}

=====================================================================

第10章 泛型算法      338页    只读算法

=====================================================================

//QQ108201645编写
#include <numeric>//numeric译:数
#include <vector>
#include <string>
#include <iostream>
using namespace std;

int main()
{
	/*
	只读算法
	一些算法只会读取其输入范围内的元素,而不会改变这些值,find就是其中的一种算法,
	在10.1节练习(第337页)中使用的count函数也是如此。

	另一个只读算法是accumulate,它包含在头文件<numeric>中,accumulate函数
	接受三个参数:前两个表示了需要求和的元素的范围,第三个表示和的初值。

	accumulate的第三个值决定了函数中使用哪个加法运算符以及返回值类型。

	而且,accumulate有一个编程假定:将范围里的元素加到第三个参数上的操作是可行的,这些元素类型必须和第三个参数的类型匹配,或者能转换为第三个参数值的类型。

	*/
	vector<int> ivec{11, 22, 33, 44, 55, 66, 77, 88, 99};
	int sum = accumulate(ivec.begin(), ivec.end(), 0);//从ivec.begin开始,到end结束,初值是0
	cout << sum << endl;//输出495

	
	vector<string> svec{ "hello ","world ","How ","you ","doing " };
	string s = accumulate(svec.begin(), svec.end(), string(""));//把vector的元素连接起来


	//错误:因为传递的是字符串值,const char*上没有定义+运算符
	//string s = accumulate(svec.cbegin(), svec.cend(), "");//开始连接字符串

	cout << s << endl; //输出hello world How you doing


	/*只读算法equal,用于比较两个序列是否保存相同的值。它将第一个序列中
	的每个元素与第二个序列中的对应元素进行比较。如果对应元素都相等,则返回
	true,否则返回false。算法接受三个迭代器:前两个(与以往一样)表示第一个序
	列中的元素范围,第三个表示第二个序列的首元素*/
	vector<string> svec1(svec);
	//svec1与svec中的元素数目应该相同才能比较
	bool result = equal(svec.cbegin(), svec.cend(), svec1.cbegin());
	cout << result << endl;//输出1

	vector<int> v1{ 1, 2, 3, 4, 5 };
	vector<int> v2{ 1, 2, 3, 4, 6 };
	cout << (equal(v1.cbegin(), v1.cend(), v2.cbegin()) == true ? "euqal" : "not euqal") << endl;
	//输出not euqal


	system("pause");
	return 0;
}

=====================================================================

第10章 泛型算法      338页    练习题

=====================================================================

//QQ108201645编写
#include<vector>
#include<algorithm>
#include<numeric>
#include<iostream>
#pragma warning(disable:4996)
using namespace std;

int main()
{
	/*练习10.3:用accumulate求一个vector<int>中的元素之和。*/
	vector<int> v1 = { 1,2,3,4,5,6,7 };
	int val = accumulate(v1.begin(), v1.end(), 0);//所在头文件numeric
	cout << val << endl;//输出28

	/*练习10.4:假定v是一个vector<double>,那么调用 accumulate(v.cbegin(),
	v.cend(), 0) 有何错误(如果存在的话)?
	
	由于类型不同,隐式转换时会导致丢失精度,要把0.0作为第三个参数传递给accumulate。
	*/

	/*练习10.5:在本节对名册(roster)调用equal 的例子中,如果两个名册中保存的都是
	C风格字符串而不是string,会发生什么?*/

	const char *p[] = { "Hello","World","!" };
	const char *q[] = { strdup(p[0]),strdup(p[1]),strdup(p[2]) };//把p里的元素分别复制到*q[]
	const char *r[] = { p[0],p[1],p[2] };
	cout << equal(begin(p), end(p), q) << endl;//内容相同,但元素地址不同,输出 0
	cout << equal(begin(p), end(p), r) << endl;//p指针的拷贝,指向相同地址,输出 1
	system("pause");
	return 0;

}

=====================================================================

第10章 泛型算法      340页    写容器的算法

=====================================================================

//QQ108201645编写
#include <vector>
#include <iostream>
using namespace std;

typedef vector<int> INTVEC;

void ShowVec(INTVEC& v)
{
	for (int i : v)
	{
		cout << i << " ";
	}
	cout << endl;
}
int main()
{
	INTVEC vec{ 1,2,3,4,5,6,7,9 };
	ShowVec(vec);//输出内容1 2 3 4 5 6 7 9
	fill(vec.begin(), vec.end(), 0);//接受一对迭代器表示一个范围,fill将给给这个值并赋值给范围内的每个元素
	ShowVec(vec); //输出内容0 0 0 0 0 0 0 0
	fill(vec.begin(), vec.begin() + vec.size() / 2, 10);//把迭代器begin到end()的一半的元素每个都写入10
	ShowVec(vec);//输出内容 10 10 10 10 0 0 0 0

	//接受一个迭代器指定首位置,一个计数器指定写入个数,还有一个值
	fill_n(vec.begin(), vec.size(), 0);//把0写入到从begin开始的位置,每写入一次后,迭代器自增,写入次数为vec.size(),
	ShowVec(vec);//输出内容0 0 0 0 0 0 0 0

	fill_n(vec.begin()+5, 3, 1);//从begin()偏移5的位置开始写入单个字符,每写入一个后,迭代器自增,大小3个字符
	ShowVec(vec);//输出内容0 0 0 0 0 1 1 1

	cout << "大小: " << vec.size() << endl;//输出内容  大小: 8
	//fill_n(vec.begin(), 10, 0);//错误,修改从begin开始的10个元素,但根本没有10个,越界

	system("pause");
	return 0;

}

=====================================================================

第10章 泛型算法      340页    介绍back_insert

=====================================================================

//QQ108201645编写
#include <vector>
#include <iostream>
using namespace std;

typedef vector<int> INTVEC;

void ShowVec(INTVEC& v)
{
	cout << "大小: " << v.size() << endl;
	for (int i : v)
	{
		cout << i << " ";
	}
	cout << endl;
}
int main()
{
	INTVEC vec;
	auto it = back_inserter(vec);//通过它赋值会将元素添加到vec中
	
	*it++ = 42;//vec中现在有一个元素,值为42
	*it = 43;//vec中现在有一个元素,值为43
	ShowVec(vec);
	//正确:back_insert创建一个插入迭代器,可用来向vec加元素
	fill_n(back_inserter(vec), 10, 0);//添加10个元素到vec
	ShowVec(vec);
	system("pause");
	return 0;

}

=====================================================================

第10章 泛型算法      341页    拷贝算法

=====================================================================

//QQ108201645编写
#include <iostream>
#include <vector>
#include <list>
#include <algorithm>
using namespace std;

void NewVecShow(vector<int> v)
{
	for (auto i : v)
		cout << i << " ";
	cout << endl;
}
void ShowList(list<int>& v)
{
	for (auto i : v)
		cout << i << " ";
	cout << endl;
}
void ShowVec(vector<int>& v)
{
	for (auto i : v)
		cout << i << " ";
	cout << endl;
}
int main()
{
	int a1[] = { 0,1,2,3,4,5,6,7,8,9 };
	//int每个占4个字节,所以前面是10个数组乘4就是:40/4=10
	int a2[sizeof(a1) / sizeof(*a1)];//a2大小与a1一样
	//ret指向拷贝到a2的尾元素之后的位置
	auto ret = copy(begin(a1), end(a1), a2);//把a1的内容拷贝给a2

	/*int* beg = a2, *end = a2 + sizeof(a1) / sizeof(*a1);*/
	NewVecShow({ begin(a2), end(a2) });//迭代器方式初始化vector
	//输出a2内容:0 1 2 3 4 5 6 7 8 9
	
	list<int> ilst = { 0,1,2,3,4,5,6,7,8,9 ,0 };//创建一个链表对象并初始化
	ShowList(ilst);//输出list内容:0 1 2 3 4 5 6 7 8 9 0

	//replace在算法头文件
	replace(ilst.begin(),ilst.end(), 0, 42);//把list从begin开始到end结束的全部数值为0元素都改为42
	ShowList(ilst);//输出list内容:42 1 2 3 4 5 6 7 8 9 42

	vector<int> ivec{ 42,10,11,12,13,14,15 };
	
	/*前两个是迭代器,表示输入序列,后两个一个是要搜索的值,
	另一个是新值。它将所有等于第一个值的元素替换成第二个值*/
	replace_copy(ilst.cbegin(), ilst.cend(),
		back_inserter(ivec), 42, 43);//把list的内容复制到ivec的尾部,如果原来list中值为42的元素,在vector中就改为43
	ShowList(ilst);//输出list内容: 42 1 2 3 4 5 6 7 8 9 42
	ShowVec(ivec);//输出Vec内容: 42 10 11 12 13 14 15 43 1 2 3 4 5 6 7 8 9 43
	system("pause");
	return 0;

}

=====================================================================

第10章 泛型算法      342页    练习题

=====================================================================

//QQ108201645编写
#include <iostream>
#include <vector>
#include <list>
#include <algorithm>
using namespace std;

void ShowVec(vector<int>& v)
{
	for (auto i : v)
		cout << i << " ";
	cout << endl;
}
int main()
{
	/*练习10.6:编写程序,使用fill_n将一个序列中的 int 值都设置为 0。*/
	vector<int> ivec{ 42,10,11,12,13,14,15 };
	fill(ivec.begin(), ivec.begin() + ivec.size() / 2, 1);
	ShowVec(ivec);//输出Vec内容:1 1 1 12 13 14 15
	fill_n(ivec.begin(), ivec.size(), 0);
	ShowVec(ivec);//输出Vec内容:0 0 0 0 0 0 0

	/*练习10.7:下面程序是否有错误?如果有,请改正:

	(a) vector<int> vec; list<int> lst; int i;
	while (cin >> i)
		lst.push_back(i);
	copy(lst.cbegin(), lst.cend(), vec.begin());
	(b)vector<int> vec;
	vec.reserve(10);//分配能容纳10个元素的内存空间
	fill_n(vec.begin(), 10, 0);
	*/
	/*
	(a)是错误的。因为泛型算法的一个基本特点是:通过迭代器操作容器,
	因此不能直接向/从容器添加、删除元素,无法改变容器的大小。因此,对于copy
	算法,要求目标序列至少要包含与源序列一样多的元素,因此程序中,vec进行缺省
	初始化,它是空的,copy无法进行,如要改变容器大小,需要使用一类特殊的称为
	插入器的迭代器。我们可以将第三个参数改为back_inserter(vec),通过它,
	copy算法即可将lst中元素的拷贝插入到vec的末尾。*/
	list<int> lst{ 1,2,3 };
	vector<int> vec;//输出内容1
	copy(lst.begin(), lst.end(), back_inserter(vec));
	cout << equal(lst.begin(), lst.end(), vec.begin()) << endl;
	ShowVec(vec);//输出内容1 2 3
	cout << vec.size() <<" "<<vec.capacity()<< endl;
	//fill_n(vec.back(), vec.size(), 0);把每个元素都改成0,报错
	fill(vec.begin(), vec.end(), 10);//把每个元素都改成10

	//测试原先元素的vector
	vector<int> ivec1, ivec2{ 1,2,3 };
	//fill_n(ivec1.begin(), 10, 0);//没有元素报错
	fill_n(back_inserter(ivec1), 10, 1);//正确,返回一个迭代器元素并添加数值为1
	//fill_n(ivec2.begin(), 10, 0);//报错.没有多余的7个元素提供改写元素

	fill_n(back_inserter(vec), 10, 0);

	/*练习10.8:本节提到过,标准库算法不会改变它们所操作的容器的大小。为什么使用
	back_inserter不会使这一断言失效?*/
	/*back_inserter不属于标准库泛型算法,它是在头文件iterator中定义的,
	而泛型算法是在algorithm中定义的。
	标准库算法不直接操作容器,只操作迭代器,从而间接访问容器,能不能删除不在于算法,而在
	于传递给它们的迭代器是否有这样的能力*/
	system("pause");
	return 0;

}

=====================================================================

第10章 泛型算法      343页    重排容器元素的算法

=====================================================================

the quick red fox jumps over the slow red turtle

fox

jumps

over

quick

red

slow

the

turtle

 

消除重复单词

=====================================================================

//QQ108201645编写
#include <iostream>
#include <vector>
#include <string>
#include <sstream>
#include <algorithm>
using namespace std;

void elimDups(vector<string>& words)
{
	//按字典序排序words,以便查找重复单词
	sort(words.begin(), words.end());//进行排序
	//unique重排输入范围,使得每个单词只出现一次
	//排列在范围的前部,返回指向不重复区域之后一个位置的迭代器
	auto end_unique = unique(words.begin(), words.end());
	//unique并不删除任何元素,只是覆盖重复的相邻元素
	//使用向量操作erase删除重复单词(删除重复元素),返回的迭代器指向最后一个不重复元素之后的位置
	//使用erase删除从end_unique开始直到words末尾的范围内的所有元素。即使没有重复单词,这样的调用erase也是安全的
	words.erase(end_unique, words.end());
}

void ShowVec(vector<string>& v)
{
	cout << "size = " << v.size() << endl;
	for (auto i : v)
		cout << i << " ";
	cout << endl;
}
int main()
{
	istringstream InitIs;
	InitIs.str("the quick red fox jumps over the slow red turtle");//把字符串传给InitIs
	vector<string> svec;
	string s;
	while (!InitIs.eof())
	{
		InitIs >> s;
		svec.push_back(s);
	}
	ShowVec(svec);//输出内容: size = 10		the quick red fox jumps over the slow red turtle

	elimDups(svec);
	ShowVec(svec);//输出内容: size = 8	fox jumps over quick red slow the turtle
	system("pause");
	return 0;

}

=====================================================================

fox

jumps

over

quick

red

red

slow

the

the

turtle

注意,单词red和the各出现了两次

使用unique,vector将变成

fox

jumps

over

quick

red

slow

the

turtle

???

???

最后一个不重复元素之后的位置就是end_unique

=====================================================================

第10章 泛型算法      344页    练习题

=====================================================================

//QQ108201645编写
#include<iostream>
#include<algorithm>
#include<vector>
using namespace std;

/*练习10.9:实现你自己的elimDups。测试你的程序,分别在读取输入后、调用 unique
后以及调用erase后打印vector的内容。*/

void elimDups(vector<int>& v)
{
	sort(v.begin(), v.end());//如果不排序则无法删除不是间隔的555
	/*auto*/ vector<int>::const_iterator pos = unique(v.begin(), v.end());
	cout << typeid(pos).name() << endl;
	v.erase(pos, v.end());
}
void Show(vector<int> &v)
{
	cout << v.size() << endl;
	for (auto i : v)
		cout << i << " ";
	cout << endl;
}
int main()
{
	vector<int> ivec{ 111,111,222,333,444,444,555,666,777,888,999,555 };
	cout << ivec.size() << endl;
	elimDups(ivec);
	Show(ivec);
	vector<int> ivec1;
	replace_copy(ivec.begin(), ivec.end(), back_inserter(ivec1), 0, 42);
	Show(ivec1);
	cout << equal(ivec.begin(), ivec.end(), ivec1.begin()) << endl;

	/*练习10.10:你认为算法不改变容器大小的原因是什么?
	算法与容器分离,算法不改变容器将使用户不需要顾忌容器的迭代器失效问题。*/

	system("pause");
	return 0;
}

=====================================================================

//删除vector电话号码排序及删除重复元素
#include<iostream>
#include<algorithm>
#include<string>
#include<vector>
using namespace std;

void Show(vector<string> &v)
{
	cout << "------------" << endl;
	for (auto i : v)
	{
		cout << i << endl;
	}
	cout << "------------" << endl;
}
int main()
{
	vector<string> svec = { "18600001112","18244443333","18600011111",
		"13800001111","13800001112","15611112222","15611112223","15611112224","13800001111" };
	Show(svec);
	cout << "排序后" << endl;
	sort(svec.begin(), svec.end());//排序
	string s = "13800001111";
	svec.erase(unique(svec.begin(), svec.end()), svec.end());//删除重复的"13800001111"
	Show(svec);
	cout << "删除13800001111" << endl;
	svec.erase(remove(svec.begin(), svec.end(), s), svec.end());//删除vector内内容为"13800001111"的元素
	Show(svec);
	system("pause");
	return 0;
}
/*
输出内容
------------
18600001112
18244443333
18600011111
13800001111
13800001112
15611112222
15611112223
15611112224
13800001111
------------
排序后
------------
13800001111
13800001112
15611112222
15611112223
15611112224
18244443333
18600001112
18600011111
------------
删除13800001111
------------
13800001112
15611112222
15611112223
15611112224
18244443333
18600001112
18600011111
------------
请按任意键继续. . .
*/

=====================================================================

第10章 泛型算法      344页    向算法传递函数(排序)

=====================================================================

//QQ108201645编写
#include<iostream>
#include<algorithm>
#include<string>
#include<vector>
#include<sstream>
using namespace std;

void Show(vector<string> &v)
{
	cout << "------------" << endl;
	for (auto i : v)
	{
		cout << i << " ";
	}
	cout << "\n------------" << endl;
}
bool isShorter(const string& s1, const string& s2)
{
	return s1.size() < s2.size();
}
void elimDups(vector<string>& words)
{
	//按字典序排序words,以便查找重复单词
	sort(words.begin(), words.end());//进行排序
	//unique重排输入范围,使得每个单词只出现一次
	//排列在范围的前部,返回指向不重复区域之后一个位置的迭代器
	auto end_unique = unique(words.begin(), words.end());
	//unique并不删除任何元素,只是覆盖重复的相邻元素
	//使用向量操作erase删除重复单词(删除重复元素),返回的迭代器指向最后一个不重复元素之后的位置
	//使用erase删除从end_unique开始直到words末尾的范围内的所有元素。即使没有重复单词,这样的调用erase也是安全的
	words.erase(end_unique, words.end());
}
#ifdef DECLARATION
C++中sort和stable_sort的区别:

1.sort是快速排序实现,因此是不稳定的;stable_sort是归并排序实现,因此是稳定的;
2.对于相等的元素sort可能改变顺序,stable_sort保证排序后相等的元素次序不变;
3.如果提供了比较函数,sort不要求比较函数的参数被限定为const,而stable_sort则要求参数被限定为const,否则编译不能通过。
#endif
int main()
{
	istringstream InitIs;
	InitIs.str("the quick red fox jumps over the slow red turtle");//把字符串传给InitIs
	vector<string> svec;
	string s;
	while (!InitIs.eof())
	{
		InitIs >> s;
		svec.push_back(s);
	}
	cout << "输出内容" << endl;
	Show(svec);
	cout << "字典序,并消除重复单词" << endl;
	elimDups(svec);
	Show(svec);

	cout << "按短至长排序" << endl;
	sort(svec.begin(), svec.end(), isShorter);
	Show(svec);

	cout << "按字典重排,并消除重复单词" << endl;
	elimDups(svec);//按字典重排,并消除重复单词
	cout << "按长度重新排序,长度相同的单词维持字典序" << endl; 
	stable_sort(svec.begin(), svec.end(), isShorter);
	Show(svec);

	cout << "按字典重排" << endl;
	stable_sort(svec.begin(), svec.end());
	Show(svec);
	system("pause");
	return 0;
}
/*
输出内容
------------
the quick red fox jumps over the slow red turtle
------------
字典序,并消除重复单词
------------
fox jumps over quick red slow the turtle
------------
按短至长排序
------------
fox red the over slow jumps quick turtle
------------
按字典重排,并消除重复单词
按长度重新排序,长度相同的单词维持字典序
------------
fox red the over slow jumps quick turtle
------------
按字典重排
------------
fox jumps over quick red slow the turtle
------------
请按任意键继续. . .
*/

=====================================================================

第10章 泛型算法      345页    练习题

=====================================================================

//QQ108201645编写
#include<iostream>
#include<algorithm>
#include<string>
#include<vector>
#include<sstream>
using namespace std;

void Show(vector<string>& v)
{
	for (auto c : v)
		cout << c << " ";
	cout << endl;
}
void elimDups(vector<string>& v)
{
	sort(v.begin(), v.end());
	v.erase(unique(v.begin(), v.end()), v.end());
}
bool isShorter(const string& iv, const string& iv1)
{
	return iv.size() < iv1.size();
}
int main()
{
	/*练习10.11:编写程序,使用stable_sort和isShorter将传递给你的elimDups
	版本的vector排序。打印vector的内容,验证你的程序的正确性。*/
	vector<string> ivec{ "111","2222","333","444","5555",
		"6666","777","888","apple","111000","111","2222","333","444","5555" };
	//elimDups(ivec);
	Show(ivec);
	stable_sort(ivec.begin(), ivec.end(), isShorter);
	Show(ivec);
	sort(ivec.begin(), ivec.end(), isShorter);
	Show(ivec);
	system("pause");
	return 0;
}

=====================================================================

//QQ108201645编写
//保存为Sales_data.h头文件
#ifndef _SALES_DATA_H_
#define _SALES_DATA_H_
#include <string>
#include <iostream>
#include <fstream>
using namespace std;
/*定义在public:说明符之后的成员在整个程序内可被访问public成员定义类的
接口*/
/*定义在private:说明符之后成员只被类的函数访问,但不能被使用
该类的代码访问,private封装了(即隐藏了)类的实现细节*/

//使用class而非struct开始类的定义,只是形式不同,唯一区别就是默认访问权限不同
//没有定义public:	protected: private: 的情况下.在struct里都是public
class Sales_data
{
public://公有成员
	//新增构造函数(不同的类内初始化方式)
	Sales_data() = default;//默认构造函数可以声明在类类部,也可以作为定义出现在类的外部

	explicit Sales_data(const std::string &s, unsigned n, double p) :
		bookNo(s), units_sold(n), revenue(p*n) {}
	/*Sales_data(std::istream& is)
	{
		read(is, *this);
	}*/
	//保留默认构造函数
	explicit Sales_data(std::string s)
		:bookNo(s) {}//bookNo(s)表示构造函数列表初始化(构造函数初始值列表)
	//只允许出现在类内声明构造函数时使用explicit
	explicit Sales_data(std::istream& is)
	{
		read(is, *this);
	}

	friend Sales_data add(const Sales_data&, const Sales_data&);
	friend std::istream& read(std::istream&, Sales_data&);
	friend std::ostream& print(std::ostream&, const Sales_data&);

	friend ifstream& read(ifstream& in, Sales_data& item)
	{
		double price = 0;
		in >> item.bookNo >> item.units_sold >> price;
		item.revenue = price * item.units_sold;
		return in;
	}
	friend ofstream& print(ofstream& out, const Sales_data& item)
	{
		out << item.isbn() << " " << item.units_sold << " "
			<< item.revenue << " " << item.ave_price() << endl;
		return out;
	}

	friend std::istream& operator>>(std::istream& is, Sales_data&);//operator>>重载,支持cin>>对象名接收
	friend std::ostream& operator<<(std::ostream& os, const Sales_data&);//operator<<重载,支持cin>>对象名直接输出内容
	//之前已有的其它成员
	std::string isbn() const;
	Sales_data& combine(const Sales_data&);


private://私有成员
	double ave_price()const;
	std::string bookNo;
	unsigned units_sold = 0;//c++11开始支持类体内初始化(变量名译:单独售出)
	double revenue = 0.0;//初始化revenue(译:财政收入)
};//这里要加分号

Sales_data add(const Sales_data &lhs, const Sales_data& rhs)
{
	Sales_data sum = lhs;//把lhs的数据拷贝给sum
	sum.combine(rhs);//把rhs的数据成员加到sum当中
	return sum;
}

//定义read和print函数
std::istream& read(std::istream& is, Sales_data& item)
{
	double price = 0;
	cout << "输入书的编号、售出数量、单价" << endl;
	is >> item.bookNo >> item.units_sold >> price;
	item.revenue = price * item.units_sold;
	return is;
}
std::ostream& print(std::ostream& os, const Sales_data& item)
{
	os << item.isbn() << " " << item.units_sold << " "
		<< item.revenue << " " << item.ave_price() << endl;
	return os;
}
//上面两个等同于operator>>与operator<<重载
std::istream& operator>>(std::istream& is, Sales_data& item)
{
	double price = 0;
	is >> item.bookNo >> item.units_sold >> price;
	item.revenue = price * item.units_sold;
	return is;
}
std::ostream& operator<<(std::ostream& os, const Sales_data& item)
{
	os << item.isbn() << " " << item.units_sold << " "
		<< item.revenue << " " << item.ave_price();
	return os;
}


std::string Sales_data::isbn() const
{
	//return bookNo;//用于返回Sales_data的数据成员
	return this->bookNo;//同上
	//默认情况this指针指向非常量的常量指针
}
//函数combine设计初衷类型复合赋值运算符+=
Sales_data& Sales_data::combine(const Sales_data& rhs)
{
	units_sold += rhs.units_sold;//把rhs的成员加到this对象的成员上
	revenue += rhs.revenue;
	return *this;//返回调用该函数的对象
}
double Sales_data::ave_price()const
{
	return units_sold ? revenue / units_sold : 0;
}

#endif

 

―――――――――――――――――――――――――――――――――――――――

//QQ108201645编写
#include<iostream>
#include<algorithm>
#include<vector>
#include "Sales_data.h"
using namespace std;
/*练习10.12:遍写名为compareIsbn的函数,比较两个 Sales_data 对象的isbn()
成员。使用这个函数排序一个保存 Sales_data 对象的 vector。*/

bool compareIsbn(const Sales_data& lhs, const Sales_data& rhs)
{
	return lhs.isbn() < rhs.isbn();
}

void Show(vector<Sales_data>& v)
{
	for (auto i : v)
	{
		cout << i << endl;
	}
	cout << endl;
}
int main()
{
	vector<Sales_data> sdata;
	Sales_data sd;
	while (read(cin,sd))
	{
		sdata.push_back(sd);
	}
	stable_sort(sdata.begin(), sdata.end(), compareIsbn);
	Show(sdata);
	system("pause");
	return 0;
}
/*
输出:
输入书的编号、售出数量、单价
12-45 5 20
输入书的编号、售出数量、单价
12-45 5 20
输入书的编号、售出数量、单价
12-46 5 20
输入书的编号、售出数量、单价
12-45 6 23
输入书的编号、售出数量、单价
12-46 7 55
输入书的编号、售出数量、单价
^Z
12-45 5 100 20
12-45 5 100 20
12-45 6 138 23
12-46 5 100 20
12-46 7 385 55
*/

=====================================================================

//QQ108201645编写
#include <iostream>
#include <vector>
#include <algorithm>
#include <string>
using namespace std;

inline void output_words(vector<string>::iterator beg, vector<string>::iterator end)
{
	while (beg!=end)
	{
		cout << *beg++ << " ";
	}
	cout << endl;
}

bool five_or_more(const string& s1)
{
	return s1.size() >= 5;//判断元素中的长度是否大等于5,如果是的话就排到前面
}


int main()
{
	string s;
	vector<string> words;
	while (cin >> s)
	{
		words.push_back(s);
	}
	output_words(words.begin(), words.end());
	auto iter = partition(words.begin(), words.end(), five_or_more);//结果为true时排在容器的前面
	cout << "经由partition处理后" << endl;
	output_words(words.begin(), words.end());
	cout << "---------" << endl;

	system("pause");
	return 0;
}
/*
控制台内容
abc def hij 1234a 45678b abcde
^Z
abc def hij 1234a 45678b abcde
经由partition处理后
abcde 45678b 1234a hij def abc
---------
请按任意键继续. . .

*/

=====================================================================

//QQ108201645编写
#include<iostream>
#include<algorithm>
using namespace std;
void Show(int *beg, int *end)
{
	while (beg != end)
	{
		cout << *beg++ << " ";
	}
	cout << endl;
}
bool Intcmp(const int& val)
{
	return val <5;
}
int main()
{
	int ia[] = { 1,2,6,7,5,4,3 };
	partition(begin(ia), end(ia), Intcmp);//使小于5的数排在前面
	Show(begin(ia), end(ia));
	system("pause");
	return 0;
}
/*
1 2 3 4 5 7 6
*/

=====================================================================

//QQ108201645编写
//电话号码(根据名字或号码)排序、删除重复的号码
#include<iostream>
#include<string>
#include<vector>
#include<sstream>
#include<algorithm>
using namespace std;

const string s = "大黄 15600100002 张三 13805000001 李四 15808002111 林五 15808002111 黄六 15600100002 陈七 13805000002 王八 17624005200 ";

struct Tel
{
	string name_;
	string number_;
	Tel(const string & name, const string & number)
		:name_(name), number_(number) {}
	Tel() = default;
	friend ostream & operator<<(ostream & os, const Tel & T)
	{
		os << T.name_ << " " << T.number_;
		return os;
	}
	bool operator<(const Tel& T1)
	{
		return number_ < T1.number_;
	}
	bool operator==(const Tel& T1)
	{
		return number_ == T1.number_;
	}
};
void Show(vector < Tel > &v)
{
	cout << "..............." << endl;
	for (auto i : v)
		cout << i << endl;
	cout << "..............." << endl;
}
bool isName(const struct Tel& t1, const struct Tel& t2)
{
	return t1.name_ < t2.name_;
}
bool isNumber(const struct Tel& t1, const struct Tel& t2)
{
	return t1.number_ < t2.number_;
}
int main()
{
	vector < Tel > tvec;
	istringstream is;
	is.str(s);
	string name, number;
	while (!is.eof())
	{
		is >> name >> number;
		tvec.emplace_back(name, number);
	}
	Show(tvec);
	cout << "根据姓名排序" << endl;
	stable_sort(tvec.begin(), tvec.end(), isName);
	Show(tvec);
	cout << "根据号码排序" << endl;
	stable_sort(tvec.begin(), tvec.end(), isNumber);
	Show(tvec);
	cout << "删除重复电话号码" << endl;
	vector<Tel>::iterator end_unique = unique(tvec.begin(), tvec.end());
	tvec.erase(end_unique, tvec.end());//删除重复内容
	Show(tvec);
	system("pause");
	return 0;
}

=====================================================================

第10章 泛型算法      345页    lambda表达式

=====================================================================

/*           一个lambda表达式表示一个可调用的代码单元。我们可以理解成一个未命名的

内联函数。与任何函数类似,一个lambda具有一个返回类型、一个参数列表和一个函数

体。但与函数不同,lambda可能定义在函数内部。一个lambda表达式具有如下形式

[capture list](parameter list) -> return type { function body }                                            */

=====================================================================

//QQ108201645编写
#include<iostream>
#include<string>
#include<vector>
#include<algorithm>
#include<functional>
using namespace std;
void ShowVec(vector<string>::iterator beg,//范围输出
	vector<string>::iterator end, string::size_type sz);//函数声明
void ShowVec(vector<string> &v);//函数声明

//如果ctr的值大于1,返回word的复数形式(201页内容)
string make_plural(size_t ctr, const string &word,
	const string& ending)
{
	return (ctr > 1) ? word + ending : word;
}
void elimDups(vector<string>& words)
{
	//按字典序排序words,以便查找重复单词
	sort(words.begin(), words.end());//进行排序
	//unique重排输入范围,使得每个单词只出现一次
	//排列在范围的前部,返回指向不重复区域之后一个位置的迭代器
	auto end_unique = unique(words.begin(), words.end());
	//unique并不删除任何元素,只是覆盖重复的相邻元素
	//使用向量操作erase删除重复单词(删除重复元素),返回的迭代器指向最后一个不重复元素之后的位置
	//使用erase删除从end_unique开始直到words末尾的范围内的所有元素。即使没有重复单词,这样的调用erase也是安全的
	words.erase(end_unique, words.end());
}

bool isShorter(const string& s1, const string& s2)
{
	return s1.size() < s2.size();
}
string::size_type check_size(const string& s, string::size_type sz)
{
	return s.size() >= sz;
}

void biggies(vector<string> &words,
	vector<string>::size_type sz)
{
	elimDups(words);//将words按字典序排序,删除重复单词
	//按长度排序,长度相同的单词维持字典序
	ShowVec(words);
#ifdef DECLARATION
	stable_sort(words.begin(), words.end(), isShorter);
#endif
	//使用下面这条替换上面这条代码,功能相同
	stable_sort(words.begin(), words.end(),
		[](const string& s1, const string& s2)//下标:捕获列表是空的话,表明此lambda不使用它所在函数中任何局部变量
	{ return s1.size() < s2.size(); });
	//获取一个迭代器,指向第一个满足size()>=sz的元素
	//计算满足size >=sz的元素的数目
#ifdef DECLARATION
	auto it = find_if(words.begin(), words.end(),
		[sz](const string& s) { return s.size() >= sz; });//捕获下标sz就可以在函数体中使用s.size() >= sz
#endif
	//上面这句也可以用这句替换
	//find_if的调用返回一个迭代器,指向第一个长度不小于给定参数sz的元素
	//如果元素不存在,则返回words.end()的一个拷贝
	auto it = find_if(words.begin(), words.end(),
		bind(check_size, std::placeholders::_1, sz));//bind所在头文件functional
	//bind表示绑定check_size函数的第一个参数const string& s,是第二个参数是sz

	//计算满足size >= sz的元素的数目
	auto count = words.end() - it;
	cout << count << " " << make_plural(count, "word", "s")
		<< " of length " << sz << " or longer" << endl;
#ifdef DECLARATION
	ShowVec(it, words.end(), sz);
#endif
	//打印长度大于等于给定词的单词,每个单词后面接一个空格
	for_each(it, words.end(),//从it迭代器开始到end结束
		[](const string& s) { cout << s << " "; });//s是自己的参数
	cout << endl;
}
void ShowVec(vector<string>::iterator beg,
	vector<string>::iterator end, string::size_type sz)//范围打印
{
	cout << "打印长度大等于" << sz << "的字符串" << endl;
	while (beg != end)
	{
		cout << *beg++ << " ";
	}
	cout << endl;
}
void ShowVec(vector<string> &v)//全部打印
{
	cout << "全部打印" << endl;
	for (auto c : v)
		cout << c << " ";
	cout << endl;
}
int main()
{
	vector<string> svec{ "the", "quick", "red", "fox",
		"jumps", "over", "the", "slow", "red", "turtle" };
	biggies(svec, 5);
	ShowVec(svec);
	system("pause");
	return 0;
}

=====================================================================

//QQ108201645编写
//数组排序输出
#include<iostream>
#include<algorithm>
using namespace std;
int main()
{
	int ia[] = { 300,5, 8 ,35,44,57,68,1,23,47,68 };
	stable_sort(begin(ia), end(ia), 
		[](const int val,const int val1){ return val < val1; });//从小到大排序

	for_each(begin(ia), end(ia),
		[](const int val) {cout << val << " "; });//输出内容
	cout << "\nMin = " << ia[0] << "\t Max = " << ia[sizeof(ia) / sizeof(int) - 1] << endl;
	system("pause");
	return 0;
}

=====================================================================

#include<iostream>
#include<string>
#include<vector>
#include<algorithm>
#include<numeric>
using namespace std;
void Show(vector<string>& v)
{
	for_each(v.begin(), v.end(),
		[](const string& s){ cout << s << " "; });
	cout << endl;
}
int main()
{
	vector<string> svec{ "the", "quick", "red", "fox",
		"jumps", "over", "the", "slow", "red", "turtle" };
	Show(svec);
	size_t sz = 4;
	partition(svec.begin(), svec.end(), [sz](const string& s1)
	{return s1.size() <= sz; });
	Show(svec);
	stable_sort(svec.begin(), svec.end(), [](const string& s1,
		const string& s2){return s1.size() <s2.size(); });
	Show(svec);
	string s = accumulate(svec.begin(), svec.end(),string(""));//连接元素的内容拷贝给s
	cout << s << endl;
	system("pause");
	return 0;
}

=====================================================================

第10章 泛型算法      349页    练习题

=====================================================================

//QQ108201645编写
#include<iostream>
#include <string>
#include <vector>
#include<algorithm>
using namespace std;

//如果ctr的值大于1,返回word的复数形式(201页内容)
string make_plural(size_t ctr, const string &word,
	const string& ending)
{
	return (ctr > 1) ? word + ending : word;
}

void Show(vector<string>& v)
{
	for (auto i : v)
		cout << i << " ";
	cout << endl;
}
int main()
{
	/*练习10.14:编写一个 lambda ,接受两个int,返回它们的和。*/
	auto f = [](int i, int j) {return i + j; };
	int a = f(3, 4);
	cout << a << endl;//输出7

	/*练习10.15:编写一个 lambda ,捕获它所在函数的 int,并接受一个 int参数。lambda
	应该返回捕获的 int 和 int 参数的和。*/
	auto sum = [a](int b) {return a + b; };
	cout << sum(1) << endl;

	/*练习10.16:使用 lambda 编写你自己版本的 biggies。*/
	void biggies(vector<string>& words, vector<string>::size_type sz);//函数声明
	vector<string> svec{ "the", "quick", "red", "fox",
		"jumps", "over", "the", "slow", "red", "turtle" };
	biggies(svec, 5);
	Show(svec);
	system("pause");
	return 0;
}
void biggies(vector<string>& words, vector<string>::size_type sz)
{
	sort(words.begin(), words.end());//排序
	words.erase(unique(words.begin(), words.end()), words.end());//删除重复内容
	stable_sort(words.begin(), words.end(), [](const string& s1,
		const string& s2) {return s1.size() < s2.size(); });
	//获取一个迭代器,指向第一个满足size()>=sz的元素
	auto it = find_if(words.begin(), words.end(), [sz](const string& s) {return s.size() >= sz; });
	auto count = words.end() - it;
	cout << count << " " << make_plural(count, "word", "s")
		<< " of length " << sz << " or longer" << endl;
	for_each(it, words.end(),
		[](const string& s) {cout << s << " "; });
	cout << endl;
}

=====================================================================

//QQ108201645编写
//保存为Sales_data.h头文件
#ifndef _SALES_DATA_H_
#define _SALES_DATA_H_
#include <string>
#include <iostream>
#include <fstream>
using namespace std;
/*定义在public:说明符之后的成员在整个程序内可被访问public成员定义类的
接口*/
/*定义在private:说明符之后成员只被类的函数访问,但不能被使用
该类的代码访问,private封装了(即隐藏了)类的实现细节*/

//使用class而非struct开始类的定义,只是形式不同,唯一区别就是默认访问权限不同
//没有定义public:	protected: private: 的情况下.在struct里都是public
class Sales_data
{
public://公有成员
	//新增构造函数(不同的类内初始化方式)
	Sales_data() = default;//默认构造函数可以声明在类类部,也可以作为定义出现在类的外部

	explicit Sales_data(const std::string &s, unsigned n, double p) :
		bookNo(s), units_sold(n), revenue(p*n) {}
	/*Sales_data(std::istream& is)
	{
		read(is, *this);
	}*/
	//保留默认构造函数
	explicit Sales_data(std::string s)
		:bookNo(s) {}//bookNo(s)表示构造函数列表初始化(构造函数初始值列表)
	//只允许出现在类内声明构造函数时使用explicit
	explicit Sales_data(std::istream& is)
	{
		read(is, *this);
	}

	friend Sales_data add(const Sales_data&, const Sales_data&);
	friend std::istream& read(std::istream&, Sales_data&);
	friend std::ostream& print(std::ostream&, const Sales_data&);

	friend ifstream& read(ifstream& in, Sales_data& item)
	{
		double price = 0;
		in >> item.bookNo >> item.units_sold >> price;
		item.revenue = price * item.units_sold;
		return in;
	}
	friend ofstream& print(ofstream& out, const Sales_data& item)
	{
		out << item.isbn() << " " << item.units_sold << " "
			<< item.revenue << " " << item.ave_price() << endl;
		return out;
	}

	friend std::istream& operator>>(std::istream& is, Sales_data&);//operator>>重载,支持cin>>对象名接收
	friend std::ostream& operator<<(std::ostream& os, const Sales_data&);//operator<<重载,支持cin>>对象名直接输出内容
	//之前已有的其它成员
	std::string isbn() const;
	Sales_data& combine(const Sales_data&);


private://私有成员
	double ave_price()const;
	std::string bookNo;
	unsigned units_sold = 0;//c++11开始支持类体内初始化(变量名译:单独售出)
	double revenue = 0.0;//初始化revenue(译:财政收入)
};//这里要加分号

Sales_data add(const Sales_data &lhs, const Sales_data& rhs)
{
	Sales_data sum = lhs;//把lhs的数据拷贝给sum
	sum.combine(rhs);//把rhs的数据成员加到sum当中
	return sum;
}

//定义read和print函数
std::istream& read(std::istream& is, Sales_data& item)
{
	double price = 0;
	cout << "输入书的编号、售出数量、单价" << endl;
	is >> item.bookNo >> item.units_sold >> price;
	item.revenue = price * item.units_sold;
	return is;
}
std::ostream& print(std::ostream& os, const Sales_data& item)
{
	os << item.isbn() << " " << item.units_sold << " "
		<< item.revenue << " " << item.ave_price() << endl;
	return os;
}
//上面两个等同于operator>>与operator<<重载
std::istream& operator>>(std::istream& is, Sales_data& item)
{
	double price = 0;
	is >> item.bookNo >> item.units_sold >> price;
	item.revenue = price * item.units_sold;
	return is;
}
std::ostream& operator<<(std::ostream& os, const Sales_data& item)
{
	os << item.isbn() << " " << item.units_sold << " "
		<< item.revenue << " " << item.ave_price();
	return os;
}


std::string Sales_data::isbn() const
{
	//return bookNo;//用于返回Sales_data的数据成员
	return this->bookNo;//同上
	//默认情况this指针指向非常量的常量指针
}
//函数combine设计初衷类型复合赋值运算符+=
Sales_data& Sales_data::combine(const Sales_data& rhs)
{
	units_sold += rhs.units_sold;//把rhs的成员加到this对象的成员上
	revenue += rhs.revenue;
	return *this;//返回调用该函数的对象
}
double Sales_data::ave_price()const
{
	return units_sold ? revenue / units_sold : 0;
}

#endif

―――――――――――――――――――――――――――――――――――――――

//QQ108201645编写
#include<iostream>
#include <vector>
#include<algorithm>
#include "Sales_data.h"
using namespace std;

int main()
{
	/*练习10.17:重写10.3.1节练习10.12(第345页)的程序,在对sort的调用中使用 lambda 
	来代替函数 compareIsbn。*/
	Sales_data data;
	vector<Sales_data> trans;
	while (read(cin, data))
		trans.push_back(data);
	sort(trans.begin(), trans.end(), [](const Sales_data& lhs,
		const Sales_data& rhs) {return lhs.isbn() < rhs.isbn(); });
	for_each(trans.begin(), trans.end(), [](const Sales_data& lhs)
	{cout << lhs << endl; });
	system("pause");
	return 0;
}

=====================================================================

//QQ108201645编写
#include<iostream>
#include <string>
#include <vector>
#include<algorithm>
using namespace std;

//如果ctr的值大于1,返回word的复数形式(201页内容)
string make_plural(size_t ctr, const string &word,
	const string& ending)
{
	return (ctr > 1) ? word + ending : word;
}

void Show(vector<string>& v)
{
	for (auto i : v)
		cout << i << " ";
	cout << endl;
}
int main()
{
	/*练习10.18:重写 biggies,用 partition 代替 find_if。我们在10.3.1节练习10.13
	(第345页)中介绍了 partition 算法。*/
	void biggies(vector<string>& words, vector<string>::size_type sz);//函数声明
	vector<string> svec{ "the", "quick", "red", "fox",
		"jumps", "over", "the", "slow", "red", "turtle" };
	biggies(svec, 5);
	Show(svec);
	system("pause");
	return 0;
}
void biggies(vector<string>& words, vector<string>::size_type sz)
{
	sort(words.begin(), words.end());//排序
	words.erase(unique(words.begin(), words.end()), words.end());//删除重复内容
	stable_sort(words.begin(), words.end(), [](const string& s1,
		const string& s2) {return s1.size() < s2.size(); });
	//获取一个迭代器,指向第一个满足size()>=sz的元素
	/*
	auto it = find_if(words.begin(), words.end(), [sz](const string& s) {return s.size() >= sz; });
	auto count = words.end() - it;
	cout << count << " " << make_plural(count, "word", "s")
		<< " of length " << sz << " or longer" << endl;
	for_each(it, words.end(),
		[](const string& s) {cout << s << " "; });
	cout << endl;
*/


	auto it = partition(words.begin(), words.end(), [sz](const string& s) {return s.size() >= sz; });
	//partition返回最后一个为true的元素之后的位置
	auto count = it-words.begin();
	cout << count << " " << make_plural(count, "word", "s")
		<< " of length " << sz << " or longer" << endl;
	for_each(words.begin(),it,
		[](const string& s) {cout << s << " "; });
	cout << endl;
}

=====================================================================

#include<iostream>
#include <string>
#include <vector>
#include<algorithm>
using namespace std;

//如果ctr的值大于1,返回word的复数形式(201页内容)
string make_plural(size_t ctr, const string &word,
	const string& ending)
{
	return (ctr > 1) ? word + ending : word;
}

void Show(vector<string>& v)
{
	for (auto i : v)
		cout << i << " ";
	cout << endl;
}
int main()
{
	/*练习10.19:用 stable_partition 重写前一题的程序,与 stable_sort 类似,在
	划分后的序列中维持原有元素的顺序。*/
	void biggies(vector<string>& words, vector<string>::size_type sz);//函数声明
	vector<string> svec{ "the", "quick", "red", "fox",
		"jumps", "over", "the", "slow", "red", "turtle" };
	biggies(svec, 5);
	Show(svec);
	system("pause");
	return 0;
}
void biggies(vector<string>& words, vector<string>::size_type sz)
{
	sort(words.begin(), words.end());//排序
	words.erase(unique(words.begin(), words.end()), words.end());//删除重复内容
	stable_sort(words.begin(), words.end(), [](const string& s1,
		const string& s2) {return s1.size() < s2.size(); });


	/*auto it = partition(words.begin(), words.end(), [sz](const string& s) {return s.size() >= sz; });
	//partition返回最后一个为true的元素之后的位置
	auto count = it-words.begin();
	cout << count << " " << make_plural(count, "word", "s")
		<< " of length " << sz << " or longer" << endl;
	for_each(words.begin(),it,
		[](const string& s) {cout << s << " "; });	*/
	/*输出
3 words of length 5 or longer
turtle quick jumps
turtle quick jumps over slow the red fox
	*/
	auto it = stable_partition(words.begin(), words.end(), [sz](const string& s) {return s.size() >= sz; });
	//stable_partition可以保持原来的顺序
	auto count = it - words.begin();
	cout << count << " " << make_plural(count, "word", "s")
		<< " of length " << sz << " or longer" << endl;
	for_each(words.begin(), it,
		[](const string& s) {cout << s << " "; });
	/*输出
3 words of length 5 or longer
jumps quick turtle
jumps quick turtle fox red the over slow
	*/
	cout << endl;
}

=====================================================================

第10章 泛型算法      352页    lambda捕获和返回

=====================================================================

//QQ108201645编写
#include<iostream>
#include <string>
#include <vector>
#include<algorithm>
using namespace std;
//值捕获
void fcn1()
{
	size_t v1 = 42;//局部变量
	//将v1拷贝到名为f的可调用对象
	auto f = [v1] {return v1; };//下标内捕获v1的值
	v1 = 0;
	auto j = f();//j为42;f保存了我们创建它时v1的拷贝
}
//引用捕获
void fcn2()
{
	size_t v1 = 42;//局部变量
	//将v1拷贝到名为f的可调用对象
	auto f2 = [&v1] {return v1; };//捕获引用地址
	v1 = 0;
	auto j = f2();//j为42;f保存了我们创建它时v1的拷贝
}
void biggies(vector<string> &words,
	vector<string>::size_type sz,
	ostream &os = std::cout, char c = ' ')
{
	//与之前一样的重排words的代码
	sort(words.begin(), words.end());
	words.erase(unique(words.begin(), words.end()), words.end());
	stable_sort(words.begin(), words.end(), [](const string& s1,
		const string& s2) {return s1.size() < s2.size(); });
	//打印count的语句改为打印到os
	for_each(words.begin(), words.end(),
		[&os, c](const string& s) {os << s << c; });
	cout << endl;
}
int main()
{
	fcn1();
	fcn2();
	vector<string> svec{ "the", "quick", "red", "fox",
		"jumps", "over", "the", "slow", "red", "turtle" };
	biggies(svec, 5);

	system("pause");
	return 0;
}

=====================================================================

#include<iostream>
#include <string>
#include <vector>
#include<algorithm>
using namespace std;

void biggies(vector<string> &words,
	vector<string>::size_type sz,
	ostream &os = std::cout, char c = ' ')
{
	//与之前一样的重排words的代码
	sort(words.begin(), words.end());
	words.erase(unique(words.begin(), words.end()), words.end());
	auto it = find_if(words.begin(), words.end(), [=](const string& s)
	{return s.size() >= sz; });

	//os隐式捕获,引用捕获方式;c显式捕获,值捕获方式
	for_each(words.begin(), words.end(),
		[&, c](const string& s) {os << s << c; });
	cout << endl;

	//os显式捕获,引用捕获方式;c隐式捕获,值捕获方式
	for_each(words.begin(), words.end(),
		[=, &os](const string& s) {os << s << c; });
}
#ifdef DECLARATION
速记:
[ ]空捕获,{}里的内容根据parameter list的参数调用
[ names ],names代表值捕获(捕获内容的改变不影响调用),如果是&names是引用方式捕获
[ & ] 隐式引用捕获方式
[ = ] 隐式值捕捞方式
[&, ldentifier_list]除了ldentifier_list是显式,值捕获,函数体任何调用的变量都是隐式引用捕获
[=, ldentifier_list]除了ldentifier_list是显示值捕获或加上&变成显式,引用捕获方式,函数体任何调用的变量都是隐式值捕获
#endif
int main()
{
	vector<string> svec{ "the", "quick", "red", "fox",
		"jumps", "over", "the", "slow", "red", "turtle" };
	biggies(svec, 5);

	system("pause");
	return 0;
}

=====================================================================

 

表10.1:lambda捕获列表

[ ]

空捕获列表。lambda不能使用所在函数中的变量。一个lambda只有捕获变量后才能使用它们

[names]

names是一个逗号分隔的名字列表,这些名字都是lambda所在函数的局部变量。默认情况下,捕获列表中的变量都被拷贝。名字前如果使用了&,则采用引用捕获方式

[ & ]

隐式捕获列表,采用引用捕获方式。lambda体中所使用的来自所在函数的实体都采用引用方式捕获

[ = ]

隐式捕获列表,采用值捕获方式。lambda体将拷贝所使用的来自所在函数的实体的值

[ &, ldentifier_list ]

ldentifier_list是一个逗号分隔的列表,包含0个或多个来自所在函数的变量。这些变量采用值捕获方式,而任何隐式捕获的变量都采用引用方式捕获。identifier_list中的名字前面不能使用&

[ =, ldentifier_list ]

ldentifier_list中的变量都采用引用方式捕获,而任何隐式捕获的变量都采用值方式捕获。identifier_list中的名字不能包括this,且这些名字之前必须使用&

 

=====================================================================

第10章 泛型算法      352页    可变lambda

=====================================================================

//QQ108201645编写
#include <iostream>
using namespace std;
#ifdef DECLARATION
void Test()
{
	size_t v1 = 42;
	//f可以改变它所捕获的变量的值
	auto f = [v1](){return v1++; };//错误,如果不加mutable则为不可变lambda
	v1 = 0;
	auto j = f();//j 为43
}
#endif
//可变lambda
int fcn3()
{
	size_t v1 = 42;
	//f可以改变它所捕获的变量的值
	auto f = [v1]()mutable {return ++v1; };
	v1 = 0;//值捕获后改变vi的值不改变f()里面返回的值
	auto j = f();//j 为43
	return j;
}

int fcn4()
{
	size_t v1 = 42;
	//v1是一个非const变量的引用
	//可以通过f2中的引用来改变它
	auto f2 = [&v1]()mutable {return ++v1; };//一个引用捕获的变量可以进行可变操作
	v1 = 0;//改变f2()里v1的值
	auto j = f2();//j的值为0然后自增等于1
	return j;
}

int main()
{
	//Test();
	cout << fcn3() << endl;
	cout << fcn4() << endl;
	system("pause");
	return 0;
}

=====================================================================

第10章 泛型算法      353页    指定lambda返回类型

=====================================================================

//QQ108201645编写
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
void Test()
{
	vector<int> ivec{ 1,2,3,4,5 };
	find_if(ivec.begin(),ivec.end(),[](int i) {return i < 3 ? -i : i; });//并不会改变里央的内容
	find_if(ivec.begin(), ivec.end(), [](int i){return i < 3 ? -i : i; });
	for_each(ivec.begin(), ivec.end(), [](int i) {cout << i << " "; });
	cout << endl;
}
int main()
{
	Test();
	vector<int> ivec{ 1,2,3,4,5 };
	/*transform接受三个迭代器和一个可调用对象,前两个表示序列,第三个表示目前位置
	算法对输入序列中的每个元素调用 可调用对象,并将结果写到目的位置*/
	transform(ivec.begin(), ivec.end(), ivec.begin(),
		[](int i) {return i < 3 ? -i : i; });//小于3的数改为负数
	for_each(ivec.begin(), ivec.end(), [](int i) {cout << i << " "; });
	cout << endl;

	//错误不能推断的lambda的返回类型
	transform(ivec.begin(), ivec.end(), ivec.begin(),
		[](int i) { if (i < 0) return -i; else return i; });//vs2017编译通过
	for_each(ivec.begin(), ivec.end(), [](int i) {cout << i << " "; });
	/*
	func接受一个int类型的实参,返回一个指针,该指针指向含有10个整数的数组
	auto func(int i) -> int(*)[10];
	尾返回类型跟在形参列表并以一个->符号开头。为了表示函数真正的返回类型跟在形参列表之后
	
	*/
	transform(ivec.begin(), ivec.end(), ivec.begin(),
		[](int i)->int
	{if (i < 0)return -i; else return i; });
	for_each(ivec.begin(), ivec.end(), [](int i) {cout << i << " "; });
	cout << endl;
	system("pause");
	return 0;
}

=====================================================================

第10章 泛型算法      354页    练习题

=====================================================================

//QQ108201645编写
#include <iostream>
#include <vector>
#include <string>
#include <algorithm>
using namespace std;

int main()
{
	/*练习10.20:标准库定义了一个名为 count_if 的算法。类似 find_if,此函数接受
	一对迭代器,表示一个输入范围,还接受一个谓词,会对输入范围中每个元素执行。
	count_if返回一个计数值,表示谓词有多少次为真。使用count_if重写我们程序中
	统计有多少单词长度超过6的部分。*/
	vector<string> svec{ "ok very good","hello","I like C++", };
	auto num = count_if(svec.begin(), svec.end(),
		[](const string& s) {return s.size()>=6; });
	cout << num << endl;

	/*练习10.21:编写一个 lambda,捕获一个局部 int 变量,并递减变量值,直至它变为0。
	一旦变量变为0,再调用lambda应该不再递减变量。lambda应该返回一个bool值,指
	出捕获的变量是否为0。*/
	void mutable_lambda();//函数声明
	mutable_lambda();//函数调用
	system("pause");
	return 0;
}
void mutable_lambda()
{
	int vi = 5;
	auto f = [=]()mutable->bool
	{
		if (vi > 0)
		{
			vi--;
			return false;
		}
		else
			return true;
	};
	for (int j = 0; j < 6; j++)
		cout << f() << " ";
	cout << endl;

}

=====================================================================

第10章 泛型算法      354页    参数绑定

=====================================================================

//QQ108201645编写
#include <iostream>
#include <vector>
#include <string>
#include <algorithm>
#include <functional>//bind所在的头文件
using namespace std;
using std::placeholders::_1;// _1对应声明后才能使用_1
bool check_size(const string& s, string::size_type sz)
{
	return s.size() >= sz;
}
void Show(vector<string>& v)
{
	for_each(v.begin(), v.end(), [](const string& s) {cout << s << " "; });
	cout<<endl;
}
int main()
{
	
	//_1表示第一个参数,_2表示第二个参数依此类推
	//标准库bind函数
	string s = "hello";
	auto check6 = bind(check_size, placeholders::_1, placeholders::_2);
	bool bl = check6(s,6);//会调用check_size(s,6)
	
	vector<string> svec{ "hello","world","good" };
	auto it = find_if(svec.begin(), svec.end(), bind(check_size, placeholders::_1, 5));
	cout << *it << endl;
	Show(svec);

	string::size_type sz = 5;
	//auto wc = find_if(svec.begin(), svec.end(),[sz](const string& s) {s.size() >= sz; });
	//可以替换成如下使用check_size的版本


	auto wc = find_if(svec.begin(), svec.end(), bind(check_size, _1, sz));
	// _n名字都定义在一个名为placeholders的命名空间中
	system("pause");
	return 0;
}

=====================================================================

第10章 泛型算法      354页    bind的参数绑定

=====================================================================

//QQ108201645编写
#include <iostream>
#include <functional>
#include <vector>
using std::bind;
//使用placeholders
using namespace std::placeholders;

using std::placeholders::_1; using std::placeholders::_2;//也可以用这个,等同于上面
using namespace std;

int main()
{
	//g是一个可有两个参数的可调用对象
	
	auto f = [](int a,int b,int c,int d,int e)
	{
		cout << "a = " << a << endl;
		cout << "b = " << b << endl;
		cout << "c = " << c << endl;
		cout << "d = " << d << endl;
		cout << "e = " << e << endl;
		return a+b+c+d+e; 
	};
	int a = 1, b = 2, c = 3;
	auto g = bind(f, a, b, _2, c, _1);
	/*
	g(_1,_2)
	映射为
	f(a,b,_2,c,_1)
	g(X,Y)
	将变成
	f(a,b,Y,c,X)
	*/
	
	cout << g(4, 5) << endl;
	/*cout << typeid(g).name() << endl;*/
	system("pause");
	return 0;
}
/*
输出内容
a = 1
b = 2
c = 5
d = 3
e = 4
15
*/

=====================================================================

//QQ108201645编写
#include <iostream>
#include <algorithm>
#include <functional>
using namespace std::placeholders;
using namespace std;

void ShowArr(int* beg, int* end)
{
	while (beg != end)
	{
		cout << *beg++ << " ";
	}
	cout << endl;
}
int main()
{
	int arr[] = { 11,22,4,65,77,41,224,35,68 };
	auto isShorter = [](int a, int b) {return a < b; };
	stable_sort(begin(arr), end(arr), isShorter);//从小到大排序
	ShowArr(begin(arr), end(arr));
	stable_sort(begin(arr), end(arr), bind(isShorter, _2, _1));//从大到小排序
	ShowArr(begin(arr), end(arr));
	system("pause");
	return 0;
}

=====================================================================

第10章 泛型算法      356页    bind的参数重排

=====================================================================

//QQ108201645编写
#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
#include <functional>
using namespace std::placeholders;
using namespace std;

ostream& print(ostream& os, const string& s, char c)
{
	return os << s << c;
}

int main()
{
	vector<string> svec = { "abcef","def","hello","good","world" };
	auto isShorter = [](const string& s, const string& s1) {return s.size() < s1.size(); };
	sort(begin(svec), end(svec), isShorter);
	//错误,不能拷贝os
	//for_each(begin(svec), end(svec), bind(print, cout, _2, ' '));

	/*如果我们希望传递给bind一个对象而又不拷贝它,就必须使用标准库ref函数,
	函数返回一个对象,包含给定的引用,此对象是可以拷贝的,标准库中还有一个cref函数,生成一个保存const
	的类,与bind一样,函数ref和cref也定义在functional头文件中*/
	for_each(begin(svec), end(svec), bind(print, ref(cout), _1, ' '));
	
	system("pause");
	return 0;
}

=====================================================================

第10章 泛型算法      357页    练习题

=====================================================================

//QQ108201645编写
#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
#include <functional>
using namespace std::placeholders;
using namespace std;



bool isSize(const string& s, string::size_type sz)
{
	return s.size() < sz;
}
ostream& print(ostream& os, const string& s, char c)
{
	return os << s << c;
}

int main()
{
	vector<string> svec = { "identifier","parenthesis","hello","good","world","123456" };
	auto isShorter = [](const string& s, const string& s1) {return s.size() < s1.size(); };
	stable_sort(begin(svec), end(svec), isShorter);
	for_each(svec.begin(), svec.end(), bind(print, ref(cout), _1, ' '));
	cout << endl;
	/*练习10.22:重写统计长度小于等于6的单词数量的程序,使用函数代替 lambda。*/
	
	string::size_type sz = 6;
	/*lambda方式*/
	/*auto isSize = [=](const string& s) {return s.size() < sz; };
	auto cnt = count_if(svec.begin(), svec.end(),isSize); */
	
	auto cnt = count_if(svec.begin(), svec.end(),/*isSize*/ bind(isSize,_1,sz));
	cout << "长度小于6的单词数量:" << cnt << endl;
	for_each(svec.begin(), svec.end(), bind(print,ref(cout),_1,' '));
	cout << endl;

	/*练习10.23:bind 接受几个参数?
	
	bind参数是可变参数,第一个是可调用对象,即实际工作函数A,返回供算法使用的新的可调用对象B。若A接受X
	个参数,则bind的参数是X+1,即除A外,其他参数应对应A所接受的参数,这些参数一部分来自于B(_n),另外一
	些来自所处函数的局部变量*/
	system("pause");
	return 0;
}

=====================================================================

//QQ108201645编写
#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
#include <functional>
using namespace std::placeholders;
using namespace std;
//如果ctr的值大于1,返回word的复数形式(201页内容)
string make_plural(size_t ctr, const string &word,
	const string& ending)
{
	return (ctr > 1) ? word + ending : word;
}

bool check_size(const string& s, size_t len)
{
	return s.size() <= len;
}

void biggis(vector<int>& v, const string& s)
{
	auto it = find_if(v.begin(), v.end(), bind(check_size, s, _1));
	if (it != v.end())
		cout << "位置:" << (it - v.begin()) + 1 << " 大于" << s << "的长度" << endl;
	else
		cerr << "找不到!" <<"比"<<s<<"长度 大的元素"<< endl;
}
void biggis(vector<string>& words, vector<string>::size_type sz)
{
	sort(words.begin(), words.end());//排序
	words.erase(unique(words.begin(), words.end()), words.end());//删除重复单词
	stable_sort(words.begin(), words.end(), [](const string& a,
		const string& b) {return a.size() < b.size(); });
	auto it = partition(words.begin(), words.end(), bind(check_size, _1, sz));
	auto count = it - words.begin();
	cout << count << " " << make_plural(count, "word", "s")
		<< " of length " << sz << " or longer" << endl;
	for_each(words.begin(), words.end(), [](const string& s) {cout << s << " "; });
	cout << endl;
}
int main()
{
	/*练习10.24:给定一个string,使用 bind 和 check_size 在一个 int 的vector
	中查找第一个大于string长度的值。*/
	vector<int> ivec{ 1,2,3,4,5,6,7,8,9,10 };
	biggis(ivec, "hello");
	biggis(ivec, "world");
	biggis(ivec, "const string ");

	/*练习10.25:在10.3.2节(第349页)的练习中,编写了一个使用partition 的biggies
	版本。使用 check_size 和 bind 重写此函数。*/
	vector<string> svec{ "hello","the","what","furniture" };
	biggis(svec, 6);
	system("pause");
	return 0;
}

=====================================================================

第10章 泛型算法      358页    再探迭代器

=====================================================================

//QQ108201645编写

·插入迭代器( insert iterator ): 这些迭代器被绑定在到一个容器上,可用来向容器插入元素。

·流迭代器( stream iterator ): 这些迭代器被绑定到输入或输出流上,可用来遍历所有关联IO流。

·反向迭代器( reverse iterator ): 这些迭代器向后而不是向前移动。除了forward_list之外的标准库都有反向迭代器

·移动迭代器( move iterator ): 这些专用的迭代器不是拷贝其中的元素,而是移动它们,第13.6.2节(第480页)介绍移动迭代器

表10.2:插入迭代器操作

it = t

在it指定的当前位置插入t。假定c是it绑定的容器,依赖于插入迭代器的不同种类,此赋值会分别调用c.push_back(t)、c.push_front(t)或c.insert(t,p),其中p为传递给inserter的迭代器位置

*it,++it,it++

这些操作虽然存在,但还会对it做任何事情。每个操作都返回it

插入迭代器有三种类型差异在于元素插入的位置

·back_inserter(参见10.2.2节,第341页)创建一个push_back的迭代器

·front_inserter创建一个使用push_front的迭代器

·inserter创建一个使用insert的迭代器。此函数接受第二个参数,这个参数必须是一个指向给定容器的迭代器。元素将被插入到给定迭代器所表示的元素之前

只有在容器支持push_front的情况下,我们才可以使用front_inserter。类型的,只有在容器支持push_back的情况下,才能使用back_isnerter。

=====================================================================

第10章 泛型算法      358页    再探迭代器

=====================================================================

//QQ108201645编写
#include <iostream>
#include <list>
#include <iterator>
#include <algorithm>
using namespace std;

int main()
{
	int val = 10;
	list<int> ivec{ 1,2,3 };
	list<int>::iterator iter = ivec.begin();
	//当调用这个时获得一个迭代器
#ifdef DECLARATION
	auto it = inserter(ivec, iter);//it在begin()之前
#endif
	insert_iterator<list<int>> insert_it(ivec, iter);
	*insert_it = val;
	cout << typeid(insert_it).name() << endl;
	for_each(ivec.begin(), ivec.end(), [](int num) {cout << num << " "; });
	//等价于下面
	auto it1 = ivec.begin();
	it1 = ivec.insert(it1, ++val);
	++it1;
	cout << "\n插入11之后的位置的元素:" << *it1 << endl;
	for_each(ivec.begin(), ivec.end(), [](int num) {cout << num << " "; });
	cout << endl;
	system("pause");
	return 0;
}

=====================================================================

//QQ108201645编写
#include <iostream>
#include <list>
#include <iterator>
#include <algorithm>
using namespace std;
void Show(list<int>& l)
{
	for (auto i : l)
		cout << i << " ";
	cout << endl;
}
int main()
{
	list<int> lst = { 1,2,3,4 };
	list<int> lst2, lst3, lst4;
	//拷贝完成之后,lst2包含4 3 2 1
	copy(lst.begin(), lst.end(), front_inserter(lst2));
	//拷贝完成之后,lst3包含1 2 3 4
	copy(lst.cbegin(), lst.cend(), inserter(lst3,lst3.begin()));
	//同上
	copy(lst.begin(), lst.end(), back_inserter(lst4));
	cout << "lst = "; Show(lst);
	cout << "lst2 = "; Show(lst2);
	cout << "lst3 = "; Show(lst3);
	cout << "lst4 = "; Show(lst4);
	system("pause");
	return 0;
}

=====================================================================

第10章 泛型算法      359页    练习题

=====================================================================

//QQ108201645编写
/*
练习10.26:解释三种插入迭代器的不同之处。
back_inserter尾部插入,要求支持push_back操作
front_inserter首部插入,要求支持front_inserter操作
inserter 插入到指定位置
*/
#include <iostream>
#include <list>
#include <vector>
#include <iterator>
#include <algorithm>
using namespace std;
void ShowVec(vector<int>& v)
{
	for (auto i : v)
		cout << i << " ";
	cout << endl;
}
void ShowList(list<int>& l)
{
	for (auto i : l)
		cout << i << " ";
	cout << endl;
}
int main()
{
	/*
	练习10.27:除了 unique(参见10.2.3节,第343页) 之外,标准库还定义了名为
	unique_copy 的函数,它接受第三个迭代器,表示拷贝不重复元素的目的位置。编写
	一个程序,使用 unique_copy将一个vector中不重复的元素拷贝到一个初始化为空的
	list中。
	*/
	vector<int> ivec = { 1,2,3,3,4,5 };
	list<int> lst;
	unique_copy(ivec.begin(), ivec.end(), back_inserter(lst));
	ShowVec(ivec);//输出 1 2 3 3 4 5
	ShowList(lst);//输出 1 2 3 4 5

	/*练习10.28:一个vector 中保存 1 到 9,将其拷贝到三个其他容器中。分别使用
	inserter、back_inserter 和 front_inserter 将元素添加到三个容器中。对每
	种 inserter,估计输出序列是怎样的,运行程序验证你的估计是否正确。
	*/
	ivec.clear();
	lst.clear();
	ivec.assign({ 1,2,3,4,5,6,7,8,9 });
	ShowVec(ivec);//输出 1 2 3 4 5 6 7 8 9
	unique_copy(ivec.begin(), ivec.end(), inserter(lst, lst.begin()));
	ShowList(lst);//输出1 2 3 4 5 6 7 8 9
	unique_copy(ivec.begin(), ivec.end(), back_inserter(lst));
	ShowList(lst);//输出1 2 3 4 5 6 7 8 9 1 2 3 4 5 6 7 8 9
	unique_copy(ivec.begin(), ivec.end(), front_inserter(lst));
	ShowList(lst);//输出9 8 7 6 5 4 3 2 1 1 2 3 4 5 6 7 8 9 1 2 3 4 5 6 7 8 9
	system("pause");
	return 0;
}

 

=====================================================================

第10章 泛型算法      359页    iostream迭代器

=====================================================================

//QQ108201645编写
#include <iostream>
#include <iterator>
#include <string>
#include <fstream>
#include <vector>
using namespace std;


/*
iterator文件头
istream_iterator读取输入流
ostream_iterator向一个输出流写数据
*/
int main()
{
	fstream on("1.txt");
	on << "abcdefghijklmnopqrstuvwxyz" << endl;
	on.close();

	istream_iterator<int> int_it(cin);//从cin读取int
	istream_iterator<int> int_eof;//尾后迭代器
	ifstream in("1.txt");
	istream_iterator<string> str_it(in);//从1.txt读取字符串
	in.close();


	//下面是用istream_iterator从标准输入读取数据,存入一个vector的例子
	vector<int> vec;
	istream_iterator<int> in_iter(cin);//从cin读取int
	istream_iterator<int> eof;//istream尾后迭代器
	while (in_iter != eof)
	{
		//后置递增运算读取流,返回迭代器的旧值
		//解引用迭代器、获得从流读取的前一个值
		vec.push_back(*in_iter++);
	}

	system("pause");
	return 0;
}

=====================================================================

#include <iostream>
#include <iterator>
#include <algorithm>
#include <vector>
using namespace std;


/*
iterator文件头
istream_iterator读取输入流
ostream_iterator向一个输出流写数据
*/
int main()
{
	istream_iterator<int> in_iter(cin), eof;//循环输入,以ctrl+z结束,从cin读取int
	vector<int> vec(in_iter, eof);//从迭代器范围构造vec
	for_each(vec.begin(), vec.end(), [](int i) {cout << i << " "; });
	system("pause");
	return 0;
}

=====================================================================

表10.3:istream_iterator操作

istream_iterator<T> in (is);

in从输入流is读取类型为T的值

istream_iterator<T> end;

读取类型为T的值的istream_iterator迭代器,表示尾后位置

in1 == in2

in1和in2必须读取相同类型。如果它们都是尾后迭代器,或绑定的输入,则两者相同

in1 != in2

*in

返回从流中读取的值

in->mem

与(*in).mem的含义相同

++in, in++

使用元素类型所定义的>>运算符从输入流中读取下一个值。与以往一样,前置版本返回一个指向递增后迭代器的引用,后置版本返回旧值

   

 

=====================================================================

//QQ108201645编写
#include <iostream>
#include <iterator>
#include <numeric>
using namespace std;

int main()
{
	istream_iterator<int> in(cin), eof; //从cin读取int
	cout << accumulate(in, eof, 0) << endl; //每调用一次in就是一次输入,循环输入,以ctrl+z结束,
	system("pause");
	return 0;
}
/*
如果输入为
23 109 45 89 6 34 12 90 34 23 56 23 8 89 23 ^Z
则输出
664
请按任意键继续. . .
*/

=====================================================================

//QQ108201645编写

表10.4:ostream_iterator操作

ostream_iterator<T> out (os);

out将类型为T的值写到输出流os中

ostream_iterator<T> out (os,d);

out将类型为T的值写到输出流os中,每个值后面都输出一个d。d指向一个空字符结尾的字符数组

out = val

用<<运算符将val写入到out所绑定的ostream中。val的类型必须与out可写的兼容类型

*out, ++out, out++

这些运算符是存在的,但不对out做任何事情。每个运算符都返回out

   

 

=====================================================================

//QQ108201645编写
#include <iostream>
#include <iterator>
#include <vector>
using namespace std;

int main()
{
	vector<int> vec{ 1,2,3 };
	//用ostream_iterator来输出值的序列
	ostream_iterator<int> out_iter(cout, " ");//将每个元素写到cout,每个元素后加空格
	for (auto e : vec)
		*out_iter++ = e;//输出值的序列
	//向out_iter赋值时,可以忽略引用和递增运算。out_iter++ = e也可以,或out_iter=e
	cout << endl;

	//可以通过copy来打印vec中的元素,这比编写循环更简单
	copy(vec.begin(), vec.end(), out_iter);
	cout << endl;
	system("pause");
	return 0;
}

=====================================================================

第10章 泛型算法      359页    使用流迭代器处理类类型

=====================================================================

//QQ108201645编写
//保存为Sales_data.h头文件
#ifndef _SALES_DATA_H_
#define _SALES_DATA_H_
#include <string>
#include <iostream>
#include <fstream>
using namespace std;
/*定义在public:说明符之后的成员在整个程序内可被访问public成员定义类的
接口*/
/*定义在private:说明符之后成员只被类的函数访问,但不能被使用
该类的代码访问,private封装了(即隐藏了)类的实现细节*/

//使用class而非struct开始类的定义,只是形式不同,唯一区别就是默认访问权限不同
//没有定义public:	protected: private: 的情况下.在struct里都是public
class Sales_data
{
public://公有成员
	//新增构造函数(不同的类内初始化方式)
	Sales_data() = default;//默认构造函数可以声明在类类部,也可以作为定义出现在类的外部

	explicit Sales_data(const std::string &s, unsigned n, double p) :
		bookNo(s), units_sold(n), revenue(p*n) {}
	/*Sales_data(std::istream& is)
	{
		read(is, *this);
	}*/
	//保留默认构造函数
	explicit Sales_data(std::string s)
		:bookNo(s) {}//bookNo(s)表示构造函数列表初始化(构造函数初始值列表)
	//只允许出现在类内声明构造函数时使用explicit
	explicit Sales_data(std::istream& is)
	{
		read(is, *this);
	}

	friend Sales_data add(const Sales_data&, const Sales_data&);
#ifdef DECLARATION
	添加一个+=重载
#endif
	Sales_data& operator+=(const Sales_data& rhs)
	{
		return combine(rhs);//直接调用combine加法
	}
	friend std::istream& read(std::istream&, Sales_data&);
	friend std::ostream& print(std::ostream&, const Sales_data&);

	friend ifstream& read(ifstream& in, Sales_data& item)
	{
		double price = 0;
		in >> item.bookNo >> item.units_sold >> price;
		item.revenue = price * item.units_sold;
		return in;
	}
	friend ofstream& print(ofstream& out, const Sales_data& item)
	{
		out << item.isbn() << " " << item.units_sold << " "
			<< item.revenue << " " << item.ave_price() << endl;
		return out;
	}

	friend std::istream& operator>>(std::istream& is, Sales_data&);//operator>>重载,支持cin>>对象名接收
	friend std::ostream& operator<<(std::ostream& os, const Sales_data&);//operator<<重载,支持cin>>对象名直接输出内容
	//之前已有的其它成员
	std::string isbn() const;
	Sales_data& combine(const Sales_data&);


private://私有成员
	double ave_price()const;
	std::string bookNo;
	unsigned units_sold = 0;//c++11开始支持类体内初始化(变量名译:单独售出)
	double revenue = 0.0;//初始化revenue(译:财政收入)
};//这里要加分号

Sales_data add(const Sales_data &lhs, const Sales_data& rhs)
{
	Sales_data sum = lhs;//把lhs的数据拷贝给sum
	sum.combine(rhs);//把rhs的数据成员加到sum当中
	return sum;
}

//定义read和print函数
std::istream& read(std::istream& is, Sales_data& item)
{
	double price = 0;
	cout << "输入书的编号、售出数量、单价" << endl;
	is >> item.bookNo >> item.units_sold >> price;
	item.revenue = price * item.units_sold;
	return is;
}
std::ostream& print(std::ostream& os, const Sales_data& item)
{
	os << item.isbn() << " " << item.units_sold << " "
		<< item.revenue << " " << item.ave_price() << endl;
	return os;
}
//上面两个等同于operator>>与operator<<重载
std::istream& operator>>(std::istream& is, Sales_data& item)
{
	double price = 0;
	is >> item.bookNo >> item.units_sold >> price;
	item.revenue = price * item.units_sold;
	return is;
}
std::ostream& operator<<(std::ostream& os, const Sales_data& item)
{
	os << item.isbn() << " " << item.units_sold << " "
		<< item.revenue << " " << item.ave_price();
	return os;
}


std::string Sales_data::isbn() const
{
	//return bookNo;//用于返回Sales_data的数据成员
	return this->bookNo;//同上
	//默认情况this指针指向非常量的常量指针
}
//函数combine设计初衷类型复合赋值运算符+=
Sales_data& Sales_data::combine(const Sales_data& rhs)
{
	units_sold += rhs.units_sold;//把rhs的成员加到this对象的成员上
	revenue += rhs.revenue;
	return *this;//返回调用该函数的对象
}
double Sales_data::ave_price()const
{
	return units_sold ? revenue / units_sold : 0;
}

#endif

 

―――――――――――――――――――――――――――――――――――――――

//QQ108201645编写

//QQ108201645编写
#include <iostream>
#include <iterator>
#include <vector>
#include "Sales_data.h"
using namespace std;

int main()
{
	istream_iterator<Sales_data> item_iter(cin), eof;
	ostream_iterator<Sales_data> out_iter(cout, "\n");
	//将第一笔交易存在sum中,并读取下一条记录
	Sales_data sum = *item_iter++;
	while (item_iter!=eof)
	{
		//如果当前交易记录(存在item_iter中)有着相同的ISBN号
		if (item_iter->isbn() == sum.isbn())
			sum += *item_iter++;//将其加到sum上并读取下一条记录(要添加+=运算符重载)
		else
		{
			out_iter = sum;//输出当前sum值	
			sum = *item_iter++;//读取下一条记录
		}
	}
	out_iter = sum;//记得打印最后一组记录的和
	system("pause");
	return 0;
}

=====================================================================

第10章 泛型算法      362页    练习题

=====================================================================

//QQ108201645编写
#include <iostream>
#include <iterator>
#include <fstream>
#include <string>
#include <vector>
#include <sstream>
#include <algorithm>
using namespace std;

int main()
{
	/*练习10.29:编写程序,使用流迭代器读取一个文本文件,存入一个vector中的string
	里。*/
	string FileName = "1.txt";
	if (remove(FileName.c_str()) == 0)//如果已有文件则删除
	{
		cout << FileName << "删除成功" << endl;
	}
	fstream in(FileName);
	in.open(FileName,ios::out);
	if (!in)
		cerr << "创建文件" << endl;
	in << "123456789" << endl;//只存入这个
	in << "hello" << endl;
	
	in.close();

	in.open(FileName);
	if (!in)
		cerr << "打开文件失败" << endl;
	istream_iterator<string> iter(in);
	istream_iterator<string> iter_eof;//尾后迭代器
	in.close();
	vector<string> svec;
	while (iter != iter_eof)
	{
		svec.push_back(*iter++);
	}
	ostream_iterator<string> out(cout);
	copy(svec.begin(), svec.end(), out);//输出svec
	cout << endl;

	in.open(FileName);
	if (!in)
		cerr << "打开文件失败" << endl;
	ostringstream os;
	os << in.rdbuf();//读取全部
	cout << "输出\n" << os.str() << endl;
	string s = os.str();

	//out = in.rdbuf();//错误
	out = os.str();
	in.close();
	system("pause");
	return 0;
}

=====================================================================

//QQ108201645编写
#include <iostream>
#include <iterator>
#include <algorithm>
#include <vector>
using namespace std;

int main()
{
	/*练习10.30:使用流迭代器、sort 和 copy 从标准输入读取一个整数序列,将其排序,
	并将结果写到标准输出。*/
	istream_iterator<int> iter(cin), eof;
	
	vector<int> ivec{ iter,eof };//迭代器范围构造ivec (每次调用iter都会调用输入,用ctrl+z结束输入)
	sort(ivec.begin(), ivec.end());//排序
	ostream_iterator<int> out(cout, " ");//每个元素后面加一个空格
	//copy(ivec.begin(), ivec.end(), out);//输出内容

	/*练习10.31:修改前一题的程序,使其只打印不重复的元素。你的程序应该使用
	unique_copy(参见10.4.1节,第359页)。*/
	//将上面代码改为
	unique_copy(ivec.begin(), ivec.end(), out);
	system("pause");
	return 0;
}

=====================================================================

//QQ108201645编写
#include <iostream>
#include <iterator>
#include <algorithm>
#include <vector>
#include <string>
#include <numeric>
using namespace std;

#ifndef SALESITEM_H//未定义SALESITEM_H则继续向下执义
// we're here only if SALESITEM_H has not yet been defined 
#define SALESITEM_H

// Definition of Sales_item class and related functions goes here
#include <iostream>
#include <string>

class Sales_item {
	// these declarations are explained section 7.2.1, p. 270 
	// and in chapter 14, pages 557, 558, 561
	friend std::istream& operator>>(std::istream&, Sales_item&);
	friend std::ostream& operator<<(std::ostream&, const Sales_item&);
	friend bool operator<(const Sales_item&, const Sales_item&);
	friend bool operator==(const Sales_item&, const Sales_item&);
public:
	// constructors are explained in section 7.1.4, pages 262 - 265
	// default constructor needed to initialize members of built-in type
#if defined(IN_CLASS_INITS) && defined(DEFAULT_FCNS)
	Sales_item() = default;
#else
	Sales_item() : units_sold(0), revenue(0.0) { }
#endif
	Sales_item(const std::string &book) 
		:bookNo(book), units_sold(0), revenue(0.0) { }
	Sales_item(std::istream &is) { is >> *this; }
public:
	// operations on Sales_item objects
	// member binary operator: left-hand operand bound to implicit this pointer
	Sales_item& operator+=(const Sales_item&);

	// operations on Sales_item objects
	std::string isbn() const 
	{ 
		return bookNo;
	}
	double avg_price() const;
	// private members as before
private:
	std::string bookNo;      // implicitly initialized to the empty string
#ifdef IN_CLASS_INITS
	unsigned units_sold = 0; // explicitly initialized
	double revenue = 0.0;
#else
	unsigned units_sold;
	double revenue;
#endif
};

// used in chapter 10
bool compareIsbn(const Sales_item &lhs, const Sales_item &rhs)
{
	return lhs.isbn() == rhs.isbn();
}

// nonmember binary operator: must declare a parameter for each operand
Sales_item operator+(const Sales_item&, const Sales_item&);

inline bool operator==(const Sales_item &lhs, const Sales_item &rhs)//==运算符重载
{
	// must be made a friend of Sales_item
	return lhs.units_sold == rhs.units_sold &&
		lhs.revenue == rhs.revenue &&
		lhs.isbn() == rhs.isbn();
}

inline bool operator!=(const Sales_item &lhs, const Sales_item &rhs)
{
	return !(lhs == rhs); // != defined in terms of operator==
}

// assumes that both objects refer to the same ISBN
Sales_item& Sales_item::operator+=(const Sales_item& rhs)//'+='重载
{
	units_sold += rhs.units_sold;
	revenue += rhs.revenue;
	return *this;
}

// assumes that both objects refer to the same ISBN
Sales_item operator+(const Sales_item& lhs, const Sales_item& rhs)//'+'重载
{
	Sales_item ret(lhs);  // copy (|lhs|) into a local object that we'll return
	ret += rhs;           // add in the contents of (|rhs|) 调用+=重载
	return ret;           // return (|ret|) by value	返回临时对象
}

std::istream& operator>>(std::istream& in, Sales_item& s)//重载输入运算符
{
	double price;
	in >> s.bookNo >> s.units_sold >> price;//接受书的编号、数量、价格
	// check that the inputs succeeded
	if (in)//输入不等于空、比如输入ctrl+z再回车
		s.revenue = s.units_sold * price;//收入等于数量乘价格
	else
		s = Sales_item();  // input failed: reset object to default state
	//调用构造函数重置为默认。
	return in;
}

std::ostream& operator<<(std::ostream& out, const Sales_item& s)
{
	out << s.isbn() << " " << s.units_sold << " "
		<< s.revenue << " " << s.avg_price();
	return out;
}

double Sales_item::avg_price() const
{
	if (units_sold)//除数不等于0
		return revenue / units_sold;
	else
		return 0;
}
#endif
bool comIsbn(Sales_item &s1, Sales_item &s2)
{
	return s1.isbn() < s2.isbn();
}

int main()
{
	/*练习10.32:重写1.6节(第21页)中的书店程序,使用一个vector保存交易记录,
	使用不同算法完成处理。使用 sort 和10.3.1节(第345页)中的 compareIsbn 函数
	来排序交易记录,然后使用 find 和 accumulate 求和。*/
	vector<Sales_item> vs;
	istream_iterator<Sales_item> in_iter(cin), eof;
	//读入交易记录,存入vector
	while (in_iter!=eof)
	{
		vs.push_back(*in_iter++);
	}
	if (vs.empty())
	{
		cerr << "No data?!" << endl;
		return -1;//表示失败
	}
	sort(vs.begin(), vs.end(), comIsbn);//comIsbn要自己加一个函数才不会出错

	auto beg = vs.begin();
	while (beg!=vs.end())
	{
		auto item = *beg;//相同ISBN的交易记录中的第一个
		//在后续记录中查找第一个ISBN与item不同者
		auto r = find_if(beg + 1, vs.end(),//满足第一个不同的isbn号的
			[item](const Sales_item& item1)
		{return item1.isbn() != item.isbn(); });

		//将范围(beg,r)间的交易记录累加输出
		cout << accumulate(beg + 1, r, item) << endl;
		//指向下一段交易记录的第一个
		beg = r;

	}
	system("pause");
	return 0;
}

=====================================================================

#include <iostream>
#include <iterator>
#include <fstream>
#include <algorithm>
using namespace std;

int main(int argc,char* argv[])
{
	/*练习10.33:编写程序,接受三个参数:一个输入文件和两个输出文件的文件名。输入
	文件保存的应该是整数。使用 istream_iterator 读取输入文件。使用
	ostream_iterator 将奇数写入第一个输入文件,每个值后面都跟一个空格。将偶数
	写入第二个输出文件,每个值都独占一行。*/
	if (argc != 4)
	{
		cout << "用法:execise.exe in_file"
			"out_file1 out_file2" << endl;
		return -1;
	}
	ifstream in(argv[1]);
	if (!in)
	{
		cout << "打开输入文件失败" << endl;
		exit (1);
	}
	ofstream out1(argv[2]);
	if (!out1)
	{
		cout << "打开输出文件1失败" << endl;
		exit(1);
	}
	ofstream out2(argv[3]);
	if (!out2)
	{
		cout << "打开输出文件2失败" << endl;
		exit(1);
	}
/*操作方法:首先在cpp编译exe所在目录(我的是vs2017路径C:\Users\Administrator\source\repos\01cpp\Debug)
新建一个1.txt
写入如下内容
1 2 3 4 5 6 7 8 9
写好并保存
然后再对这个文件夹shift+鼠标右键,调出此处dos命令窗口,我的文件是01cpp.exe
那就输入01cpp.exe 1.txt 2.txt 3.txt,写完回车,然后输出一个2.txt与3.txt的结果
*/


	//创建流迭代器从文件读入整数与尾后迭代器
	istream_iterator<int> in_iter(in), eof;
	ostream_iterator<int> out1_iter(out1, " "), out2_iter(out2, "\n");
	while (in_iter != eof)
	{
		if (*in_iter & 1)
			*out1_iter++ = *in_iter;
		else
			*out2_iter++ = *in_iter;
		in_iter++;
	}

	system("pause");
	return 0;
}

 

=====================================================================

第10章 泛型算法      363页    反向迭代器

=====================================================================

//QQ108201645编写

/*除了forward_list之外,其他容器都支持反向迭代器。我们可以通过调用rbegin、rend、crbegin和crend成员函数来获得反向迭代器。这些成员函数返回指向容器尾元素和首元素之前一个位置的迭代器。与普通迭代器一样,反向迭代器也有const和非const版本*/

=====================================================================

//QQ108201645编写
#include <iostream>
#include <iterator>
#include <vector>
#include <algorithm>
using namespace std;

void Show(vector<int> &vec)
{
	for (auto iter = vec.cbegin();//将iter绑定到首元素
		iter != vec.cend();//cend指向尾元素之后的位置
		++iter)//递增
		cout << *iter << " ";
	cout << endl;
}
void R_Show(vector<int> &vec)
{
	for (auto r_iter = vec.crbegin();//将r_iter绑定到尾元素
		r_iter != vec.crend();//crend指向首元素之前的位置
		++r_iter)//实际是递减
		cout << *r_iter << " ";
	cout << endl;
}
//流迭代器不支持递减运算
int main(int argc,char* argv[])
{
	vector<int> vec{ 1,2,3,4,5,6,7,8,9 };
	R_Show(vec);//reveser打印9到1
	sort(vec.begin(), vec.end());//按"正常序"排序vec
	Show(vec);//正常打印1到9
	sort(vec.rbegin(), vec.rend());//按"逆序"排序vec,最小元素放在vec末尾
	Show(vec);//正常打印9到1
	system("pause");
	return 0;
}

 

=====================================================================

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

int main(int argc,char* argv[])
{
	string line = "FIRST,MIDDLE,LAST";
	//在一个逗号分隔列表中查找第一个元素
	auto comma = find(line.cbegin(), line.cend(), ',');
	cout << string(line.cbegin(), comma) << endl;
	//在一个逗号分隔的列表中查找最后一个元素
	auto rcomma = find(line.crbegin(), line.crend(), ',');
	//cout << string(line.crbegin(), comma) << endl;//错误:将逆序输出单词的字符
	/*如果输入的是:FIRST,MIDDLE,LAST	则这条语句打找印TSAL	*/
	//可以通过reverse_iterator的base成员函数来完成
	cout << string(rcomma.base(), line.cend())<<endl;
	system("pause");
	return 0;
}

 

=====================================================================

=====================================================================

第10章 泛型算法      365页    练习题

=====================================================================

//QQ108201645编写
#include <iostream>
#include <algorithm>
#include <vector>
#include <iterator>
#include <list>
using namespace std;

int main(int argc,char* argv[])
{
	/*练习10.34:使用 reverse_iterator 逆序打印一个vector。*/
	vector<int> ivec{ 1,2,3,4,5,6 };
	for (vector<int>::reverse_iterator it = ivec.rbegin();
		it != ivec.rend(); ++it)
		cout << *it << " ";
	cout << endl;

	/*练习10.35:使用普通迭代器逆序打印一个vector。*/
	vector<int>::iterator it = ivec.end();
	while(it != ivec.begin())
		cout << *(--it) << " ";
	cout << endl;

	/*练习10.36:使用 find 在一个 int 的list 中查找最后一个值为0的元素。*/
	list<int> lst{ 1,2,0,3,4,5,6,7,8,0,7,8 };
	ostream_iterator<int> out(cout, " ");//将类型为int的值写到输出流中,每个后面跟着空格
	copy(lst.begin(), lst.end(), out);//输出内容
	auto f = find(lst.rbegin(), lst.rend(), 0);
	cout << endl;
	f++;
	size_t p = 1;
	//从链表头开始遍历,计数最后一个0的编号
	for (auto iter = lst.begin(); iter != f.base(); iter++, p++);
	if (p >= lst.size())
		cout << "容器中没有0" << endl;
	else
		cout << "最后一个0在第" << p << "个位置" << endl;

	/*练习10.37:给定一个包含10 个元素的vector,将位置3到7之间的元素按逆序拷贝到一个list中*/

	vector<int> ivec1{ 1,2,3,4,5,6,7,8,9,10 };
	list<int> ilst;

	auto fval = find(ivec1.begin(), ivec1.end(), 3);//查找3的元素
	auto lval = find(ivec1.begin(), ivec1.end(), 7);
	++fval;
	copy(fval, lval, front_inserter(ilst));//从4开始到6
	copy(ilst.begin(), ilst.end(), out);//打印4~6
	cout << endl;
	//第二种方案
	vector<int>::reverse_iterator ra(ivec1.begin() + 2);//轮换为反向迭代器
	vector<int>::reverse_iterator rb(ivec1.begin() + 7);
	ilst.clear();
	copy(rb, ra, back_inserter(ilst));//逆序拷贝
	copy(ilst.begin(), ilst.end(), out);//打印3~7
	cout << endl;

	//第三种方案
	ilst.clear();
	copy(ivec1.begin() + 2, ivec1.end() - 3, front_inserter(ilst));
	copy(ilst.begin(), ilst.end(), out);
	cout << endl;
	system("pause");
	return 0;
}

 

=====================================================================

第10章 泛型算法      365页    泛型算法结构

=====================================================================

//QQ108201645编写

表10.5:迭代器类别

输入迭代器

只读,不写;单遍扫描,只能递增

输出迭代器

只写,不读;单遍扫描,只能递增

前向迭代器

只读写;多遍扫描,只能递增

双向迭代器

可读写;多遍扫描,可递增递减

随机访问迭代器

可读写;多遍扫描,支持全部迭代器运算

 

=====================================================================

第10章 泛型算法      365页    泛型算法结构

=====================================================================

//QQ108201645编写

输入迭代器(input iterator):可以读取序列中的元素。一个输入迭代器必须支持

 

·用于比较两个迭代器的相等和不相等运算符( == 、! =

·用于推进迭代器的前置和后置递增运算(++

·用于读取元素的解引用运算符(*);解引用只会出现在赋值运算符的右侧

·箭头运算符(->),等价于(*it.member,即,解引用迭代器,并提取对象的成员

 

输出迭代器(output iterator):可以看作输入迭代器功能上的补集----只写而不读元素。输出迭代器必须支持

 

·用于推进迭代器的前置和后置递增运算(++

·解引用运算符(*),只出现在赋值运算符的左侧(向一个已经解引用的输出迭代器赋值,就是将值写入它所指向的元素)

前向迭代器(forward iterator):可以读写元素。这类迭代器只能在序列中沿一个方向移动。前向迭代器支持所有输入和输出迭代器的操作,而且可以多次读写同一个元素。因此,我们可以保存前向迭代器的状态,使用前向迭代器的算法可以对序列进行多遍扫描。算法replace要求前向迭代器,forward_list上的迭代器是前向迭代器。

 

双向迭代器(bidirectional iterator):可以正向 / 反向读写序列中的元素。除了支持所有前向迭代器的操作之外,双向迭代器还支持前置和后置递减运算符(--)。算法reverse要求双向迭代器,除了forward_list之外,其他标准库都提供符合双向迭代器要求的迭代器。

 

随机访问迭代器(random - access iterator):提供在常量时间内访问序列中任意元素的能力。此类迭代器支持双向迭代器的所有功能,此外还支持如下操作:

 

·用于比较两个迭代器相对位置的关系运算符(<, <= , > >=

·迭代器和一个整数值的加减运算( + , +=, -, -=, 计算结果是迭代器在序列中前进(或后退)给定整数个元素后的位置

·用于两个迭代器上的减法运算符(-),得到两个迭代器的距离

·下标运算符(iter[n], *(iter[n])等价

算法sort要求随机访问迭代器。arraydequestringvector的迭代器都是随机访问迭代器,用于访问内置数组元素的指针也是

=====================================================================

第10章 泛型算法      367页    练习题

=====================================================================

/*练习10.38:列出5个迭代器类别,以及每类迭代器所支持的操作。
1.输入迭代器:只读,不写;单遍扫描,只能递增
*iterator, ++iterator, == , != , ->
2.输出迭代器:只写,不读;单遍扫描,只能递增
*iterator, ++iterator
3.前向迭代器:只读写;多遍扫描,只能递增
*iterator, ++iterator, == , != , ->
4.双向迭代器:可读写;多遍扫描,可递增递减
*iterator, ++iterator, --iterator, == , != .->
5.随机访问迭代器:可读写;多遍扫描,支持全部迭代器运算
*iterator, ++iterator, --iterator, == , != .->, <, >, +=, -, iterator[n]
*/

=====================================================================

//QQ108201645编写
/*
练习10.39:list 上的迭代器属于哪类?vector呢?
list的迭代器属于双向迭代器
vector的迭代器属于随机访问迭代器
*/
/*练习10.40:你认为 copy 要求哪类迭代器?reverse 和 unique 呢?
copy要求两个输入和一个输出迭代器
reverse要求双向迭代器
unique要求前向迭代器
*/

=====================================================================

第10章 泛型算法      367页    算法形参模式

=====================================================================

//QQ108201645编写

在任何其他算法分类之上,还有一组参数规范。理解这些参数规范对学习新算法很有帮助――通过理解参数的含义,你可以将注意力集中在算法所做的操作上。大多数算法具有如下4种形式之一

alg(beg, end, other args);

alg(beg, end, dest, other args);

alg(beg, end, beg2, other args);

alg(beg, end, beg2, end2, other args);

其中alg是算法的名字,beg和end表示算法所操作的范围,几乎所有算法都接受一个输入范围,是否有其他参数依赖于要执行的操作。这里列出了常见的一种――dest、beg2和end2,都是迭代器参数,顾名思义,如果用到了这些迭代器参数,它们分别承担指定目的位置和第二个范围的角色。除了这些迭代器参数,一些算法还接受额外的、非迭代器的特定参数

=====================================================================

第10章 泛型算法      368页    算法命名规范

=====================================================================

//QQ108201645编写
#include <iostream>
#include <list>
#include <iterator>
#include <vector>
#include <algorithm>
#include <functional>
using namespace std;

bool inCmp(const int i,const int j)
{
	return i < j;
}
void Show(list<int>& v)
{
	auto it = v.begin();
	ostream_iterator<decltype(*it)> out(cout, " ");
	copy(v.begin(), v.end(), out);
	cout << endl;
}
void Show(vector<int>& v)
{
	auto it = v.begin();
	ostream_iterator<decltype(*it)> out(cout, " ");
	copy(v.begin(), v.end(), out);
	cout << endl;
}
int main()
{
	list<int> ilst{ 1,1,2,3,4,5 };
	unique(ilst.begin(), ilst.end());
	Show(ilst);//输出内容1 2 3 4 5 5

	unique(ilst.begin(), ilst.end(), [](int a, int b) {return a == b; });
	Show(ilst);//输出内容1 2 3 4 5 5

	vector<int> ivec{ 1,2,3,4,5 };
	auto it = find(ivec.begin(), ivec.end(), 4);
	cout << (it - ivec.begin() + 1) << endl;//输出内容5
	it = find_if(ivec.begin(), ivec.end(), [](int i) {return i == 4; });
	cout << (it - ivec.begin() + 1) << endl;//输出内容5
	Show(ivec);//输出内容 1 2 3 4 5

	reverse(ivec.begin(), ivec.end());//反转元素
	Show(ivec);//输出内容5 4 3 2 1
	
	vector<int> ivec1, ivec2;
	reverse_copy(ivec.begin(), ivec.end(), inserter(ivec1,ivec1.begin()));
	Show(ivec1);//输出内容1 2 3 4 5

	//将ivec1中删除奇数元素
#ifdef DECLARATION
	remove_if(ivec1.begin(), ivec1.end(),
		[](int i) {return i % 2; });
	Show(ivec1);//输出内容2 4 3 4 5并不能真正有效的删除残余元素
	cout << ivec1.size() << endl;//大小:6
#endif
	ivec1.erase(remove_if(ivec1.begin(), ivec1.end(),
		[](int i) {return i & 1; }),ivec1.end());
	Show(ivec1);//输出内容2 4

	Show(ivec);//输出内容5 4 3 2 1
	//将偶数元素ivec拷贝到ivec2
	remove_copy_if(ivec.begin(), ivec.end(), back_inserter(ivec2),
		[](int i) {return i % 2; });
	Show(ivec2);//输出内容4 2

	system("pause");
	return 0;
}

 

=====================================================================

//QQ108201645编写
#include <iostream>
#include <vector>
#include <algorithm>
#include <iterator>//inserter所在头文件
using namespace std;

void Show(vector<int>& v)
{
	for (auto i : v)
		cout << i << " ";
	cout<<endl;
}

int main()
{
/*练习10.41:仅根据算法和参数的名字,描述下面每个标准库算法执行什么操作:
replace(beg, end, old_val, new_val); //替换beg和end指定范围内所有old_val的值为new_val
replace_if(beg, end, pred, new_val); //替换beg和end指定范围内使得pred为真的所有元素的值为new_val
replace_copy(beg, end, dest, old_val, new_val); //将beg和end指定范围内的所有old_val替换为new_val,并将新的序列写入到dest指定的容器
replace_copy_if(beg, end, dest, pred, new_val); //将beg和end指定范围内使得pred为真的所有元素的值替换为new_val,并将新的序列写入到dest指定的容器
*/
	vector<int> ivec{ 1,2,3,1,2,3 };
	replace(ivec.begin(), ivec.end(), 2, 20);//查找值为2的元素,替换成20
	Show(ivec);//输出内容1 20 3 1 20 3

	replace_if(ivec.begin(), ivec.end(), [](int i) {return i == 3; }, 30);//查找值为3的元素,替换成30
	Show(ivec);//输出内容1 20 30 1 20 30

	vector<int> ivec1, ivec2;
	replace_copy(ivec.begin(), ivec.end(), inserter(ivec1,ivec1.begin()), 1, 10);//dest 是一个指向容器的迭代器
	//把ivec的内容拷贝到ivec1,值为1的元素,替换成10
	Show(ivec1);//输出内容10 20 30 10 20 30

	replace_copy_if(ivec1.begin(), ivec1.end(),back_inserter(ivec2),
		[](int i) {return i == 10 || i == 20 || i == 30; }, 5);
	//把ivec1的内容拷贝到ivec2, 值为10、20、30的元素, 替换成5
	Show(ivec2);//输出内容5 5 5 5 5 5

	cout << "输出全部内容" << endl;
	Show(ivec);//输出内容1 20 30 1 20 30
	Show(ivec1);//输出内容10 20 30 10 20 30
	Show(ivec2);//输出内容5 5 5 5 5 5
	system("pause");
	return 0;
}

 

=====================================================================

第10章 泛型算法      369页    特定容器算法

=====================================================================

//QQ108201645编写

表10.6:list和forward_list成员函数版本的算法

这些操作都返回void

lst.merge ( lst2 )

将来自lst2的元素合并入lst。lst和lst2都必须是有序的。

lst.merge ( lst2,comp)

元素将从lst2中删除。在合并之后,lst2变为空。第一个版本使用<运算符;第二个版本使用给定的比较操作

lst.remove ( val )

调用erase删除掉与给定值相等 ( == ) 或令一元谓词为真的第个元素

lst.remove_if ( pred )

lst.reverse ( )

反转lst中元素的顺序

lst.sort ( )

使用<或给定比较操作排序元素

lst.sort (comp)

lst.unique ( )

调用erase删除同一个值的连续拷贝。第一个版本使用==;第二个版本使用给定的二元谓词

lst.unique (pred)

splice成员

表10.7:list和forward_list的splice成员函数的参数

lst.splice(args)或flst.splice_after(args)

(p, lst2)

p是一个指向lst中元素的迭代器,或一个指向flst首前位置的迭代器。函数将lst2的所有元素移动到lst中p之前的位置或是flst中p之后的位置。将元素从lst2中删除。lst2的类型必须与lst或flst相同,且不能是同一个链表

(p, lst2, p2)

p2是一个指向lst2中位置的有效的迭代器。将p2指向的元素移动到lst中,或将p2之后的元素移动到flst中。lst2可以是与lst或flst相同的链表

(p, lst2, b, e)

b与e必须表示lst2中合法范围。将给定范围中的元素从lst2移动到lst或flst。lst2与lst(或flst)可以是相同的链表,但p不能指向给定范围中元素

 

=====================================================================

//QQ108201645编写
#include <iostream>
#include <list>
#include <iterator>
#include <functional>
#include <algorithm>
using namespace std;
typedef list<int> IST;
bool inCmp(const int i,const int j)
{
	return i < j;
}
void Show(IST& v)
{
	auto it = v.begin();
	ostream_iterator<decltype(*it)> out(cout, " ");
	copy(v.begin(), v.end(), out);
	cout << endl;
}
int main()
{//测试代码
	IST ilst{ 1,5,7,6,2,4,8,9,3 }, ilst1{ 10,20,30 }, ilst2{ 300,200,100 };
	Show(ilst);//输出内容1 5 7 6 2 4 8 9 3
	
	ilst.reverse();//颠倒顺序输出
	Show(ilst);//输出内容3 9 8 4 2 6 7 5 1

	ilst.sort();//按从小到大排序
	Show(ilst);//输出内容1 2 3 4 5 6 7 8 9

	ilst.merge(ilst1);//默认谓词<从小到大顺序才能合并
	Show(ilst);//输出内容1 2 3 4 5 6 7 8 9 10 20 30

	auto f = [](int a, int b) {return a > b; };
	ilst.sort(f);//从大到小排序
	Show(ilst);//输出内容30 20 10 9 8 7 6 5 4 3 2 1
	
	ilst.merge(ilst2,f);
	Show(ilst);//输出内容300 200 100 30 20 10 9 8 7 6 5 4 3 2 1

	ilst.remove(300);//删除300
	ilst.remove_if([](int i) {return i == 200; });//删除元素中为200的
	Show(ilst); //输出内容100 30 20 10 9 8 7 6 5 4 3 2 1

	ilst.push_front(100);//开头插入一个元素100
	Show(ilst);//输出内容100 100 30 20 10 9 8 7 6 5 4 3 2 1

	ilst.unique();//调用erase删除同一个值重复的内容
	Show(ilst);//输出内容100 30 20 10 9 8 7 6 5 4 3 2 1

	ilst.push_back(1);//末尾插入一个元素,值为1
	Show(ilst);//输出内容100 30 20 10 9 8 7 6 5 4 3 2 1 1

	ilst.unique([](int i,int j) {return i == j; });//删除连续为1
	Show(ilst);//输出内容 100 30 20 10 9 8 7 6 5 4 3 2 1
	system("pause");
	return 0;
}

=====================================================================

//QQ108201645编写
#include <iostream>
#include <list>
#include <string>
#include <algorithm>
#include <iterator>//inserter所在头文件
#include <functional>
using namespace std;
list<int>::iterator Ret(list<int>& v, int locat)
{
	list<int>::iterator it = v.begin();
	for (size_t i = 1; i != locat && i < v.size(); ++i)
		++it;
	return it;//返回当前迭代器位置
}
void Show(list<int>& v)
{
	for (auto i : v)
		cout << i << " ";
	cout<<endl;
}

int main()
{//测试代码
	list <int> lst = { 1,2,3,4,5 };
	Show(lst);//输出内容1 2 3 4 5

	list<int> lst2 = { 10,20 };
	lst.splice(lst.begin(), lst2);//将lst2元素移动到lst首元素之前,并清除lst2里的元素
	Show(lst);//输出内容10 20 1 2 3 4 5

	list<int> lst3 = { 35,30,25,20,15,10,5,0 };

	lst.splice(lst.end(), lst3, Ret(lst3,3));//把25移动到lst末尾
	Show(lst);//输出内容10 20 1 2 3 4 5 25

	lst.splice(lst.end(), lst3, lst3.begin(), lst3.end());//把lst3的元素移动到lst末尾
	Show(lst);//输出内容10 20 1 2 3 4 5 25 35 30 20 15 10 5 0
	system("pause");
	return 0;
}

=====================================================================

//QQ108201645编写
#include <iostream>
#include <list>
#include <string>
#include <algorithm>
#include <iterator>//inserter所在头文件
#include <functional>
using namespace std;

void Show(list<string>& v)
{
	for (auto i : v)
		cout << i << " ";
	cout<<endl;
}

int main()
{
	/*练习10.42:使用 list 代替 vector 重新实现10.2.3节中的去除重复单词的程序。*/
	list <string> lst = { "the", "quick", "red",
		"fox", "jumps", "over", "the", "slow", "red", "turtle" };
	lst.sort();//从小到大排序
	Show(lst);//输出内容fox jumps over quick red red slow the the turtle

	lst.unique([](string& s,string& s1) {return s == s1; });//删除重复的
	Show(lst);//输出内容fox jumps over quick red slow the turtle

	system("pause");
	return 0;
}

 

―――――――――――――――――――――――――――――――――――――――

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值