【c++思维导图与代码示例】09 泛型程序设计与c++标准模板库】

【c++思维导图与代码示例】09 泛型程序设计与c++标准模板库】

思维导图:

在这里插入图片描述

代码示例:

  • 示例1:
/*************************************************
**
**Description: 例:从标准输入读入几个整数,存入向量容器,输出它们的相反数
        了解容器、算法、迭代器、函数对象的声明与使用  以及其各自在程序中的逻辑作用
**
** Author:慕灵阁-wupke
** Time:2021-12-28
** Versions :9-1.cpp
** 
*
***************************************************/
#include<iostream>
#include<vector>
#include<iterator>
#include<algorithm>
#include<functional>

using namespace std;

int main(){
    const int N =5;
    vector<int> s(N);     // 使用容器vector
    cout << " 请输入5个整数,获取对应的相反数:  "<< endl;
    for(int i  =0;i<N;i++)
        cin>>s[i];
    transform(s.begin(),s.end(),ostream_iterator<int>(cout," "),negate<int>());
    /*
    vector   容器
    transform  算法
    s.begin() 、s.end()、ostream_iterator  迭代器
    negate   函数对象
    */ 
    cout << endl;

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


transform算法的一种实现:
template <class InputIterator, class OutputIterator, class UnaryFunction>
OutputIterator transform(InputIterator first, InputIterator last, OutputIterator result, UnaryFunction op) {
    for (;first != last; ++first, ++result)
        *result = op(*first);
    return result;
}
• transform算法顺序遍历first和last两个迭代器所指向的元素;
• 将每个元素的值作为函数对象op的参数;
• 将op的返回值通过迭代器result顺序输出;
- 遍历完成后result迭代器指向的是输出的最后一个元素的下一个位置,transform会将该迭代器返回



*/


  • 示例2:
/*************************************************
**
**Description: 从键盘输入读入几个实数,分别将它们的平方输出
        了解容器、算法、迭代器、函数对象的声明与使用  以及其各自在程序中的逻辑作用
**
** Author:慕灵阁-wupke
** Time:2021-12-28
** Versions :9-2.cpp
** 
*
***************************************************/

/*

*/

// #include<vector>
#include<iterator>
#include<iostream>
#include<algorithm>
// #include<functional>

using namespace std;

// 求平方的函数
double spuare(double x){
    return x * x;
}
int main(){
    //从标准输入读入若干个实数,分别将它们的平方输出
    cout << " 请输入整数,获取对应的平方值:  "<< endl;
    transform(istream_iterator<double>(cin),istream_iterator<double>(),ostream_iterator<double>(cout,"\t"),spuare);
    /*
    square:函数对象参数、istream_iterator<double>(cin):输入流迭代器(从键盘输入)、
    istream_iterator<double>():表示输入流的结束位置,需要给出输入流结束的标记(Windows下为Ctrl + z ; linux 下为:Ctrl + d )
    ostream_iterator<double>(cout, "\t"):输出流迭代器,将计算的结果依次送到输出流中;参数cout,表示标准输出设备;"\t"表示输出数据显示时候的分隔符
    */
    cout << endl;

    system("pause");
    return 0;
}


  • 示例3:
/*************************************************
**
**Description: 迭代器的综合示例: 实现对给出的随机元素数组的内容排序后输出
**
** Author:慕灵阁-wupke
** Time:2021-12-28
** Versions :9-3.cpp
** 
*
***************************************************/
//10_3.cpp
#include <algorithm>
#include <iterator>
#include <vector>
#include <iostream>
using namespace std;

//将来自输入迭代器p的n个T类型的数值排序,将结果通过输出迭代器result输出
template <class T, class InputIterator, class OutputIterator>
void mySort(InputIterator first, InputIterator last, OutputIterator result) {
	//通过输入迭代器p将输入数据存入向量容器s中
	vector<T> s;
	for (;first != last; ++first)
		s.push_back(*first);
	//对s进行排序,sort函数的参数必须是随机访问迭代器
	sort(s.begin(), s.end());
	//将s序列通过输出迭代器输出
	copy(s.begin(), s.end(), result);
}

int main() {
	//将s数组的内容排序后输出
	double a[5] = { 1.2, 2.4, 0.8, 3.3, 3.2 };
	mySort<double>(a, a + 5, ostream_iterator<double>(cout, " "));
	cout << endl;
	//从标准输入读入若干个整数,将排序后的结果输出
	mySort<int>(istream_iterator<int>(cin), istream_iterator<int>(), ostream_iterator<int>(cout, " "));
	cout << endl;

    system("pause");
	return 0;
}


  • 示例4:
/*************************************************
**
**Description: 顺序容器的基本操作示例
**
** Author:慕灵阁-wupke
** Time:2021-12-28
** Versions :9-4.cpp
** 
*
***************************************************/

#include<iostream>
#include<algorithm>
#include<iterator>
#include<list>
#include<deque>

using namespace std;

//输出指定的顺序容器的元素 (函数模板)
template<class T>
void printContainer(const char* massage, const T& s){    
    cout << massage << " : " ;
    copy(s.begin(),s.end(),ostream_iterator<int>(cout," "));
    cout << endl;
}

int main(){
    // 从标准输入读入10个整数,将他们分别从s的头部加入
    deque <int> s;  // 顺序容器:队列s用模板生成
    cout << " 请输入10个整数:  " << endl;
    for(int i=0; i < 10; i++){
        int x;
        cin >> x;
        s.push_front(x);    // 元素插入队列
        }   
    printContainer("deque at first", s);


    //用s容器的内容的逆序构造列表容器L

    list<int> L(s.rbegin(),s.rend());      // 用模板生成L列表容器
    /*
     STL为每个可逆容器都提供了逆向迭代器,逆向迭代器可以通过下面的成员函数得到:
	 rbegin() :指向容器尾的逆向迭代器
	 rend():指向容器首的逆向迭代器

    */
    printContainer("list at first: ",L);

    // 将列表容器L的每个相邻元素顺序颠倒
    list<int>::iterator iter = L.begin();
    while(iter != L.end()){
        int v=*iter;
        iter = L.erase(iter);    // erase  删除函数
        L.insert(++iter,v);     //    insert() 插入函数
    }
    printContainer("list at last: ",L);


    // 用列表容器L的内容给 s 赋值, 将s输出
    s.assign(L.begin(),L.end());     // assign  赋值函数
    printContainer("deque at last: ",s); 


    system("pause");
    return 0;
    }


  • 示例5:

/*************************************************
**
**Description: 顺序容器的基本操作示例 :奇偶排序
先按照从大到小顺序输出奇数。再按照从小到大输出偶数
**
** Author:慕灵阁-wupke
** Time:2021-12-28
** Versions :9-5.cpp
** 
*
***************************************************/
#include <vector>
#include <deque>
#include <algorithm>
#include <iterator>
#include <iostream>
using namespace std;

int main() {
	istream_iterator<int> i1(cin), i2;	//建立一对儿输入流迭代器
	vector<int> s1(i1, i2);	//通过输入流迭代器从标准输入流中输入数据
	sort(s1.begin(), s1.end());			//将输入的整数排序
	deque<int> s2;
	//以下循环遍历s1
	for (vector<int>::iterator iter = s1.begin(); iter != s1.end(); ++iter) {
		if (*iter % 2 == 0)	//偶数放到s2尾部
			s2.push_back(*iter);
		else				//奇数放到s2首部
			s2.push_front(*iter);
	}
	//将s2的结果输出
	copy(s2.begin(), s2.end(), ostream_iterator<int>(cout, " "));
	cout << endl;
     
    system("pause");
	return 0;
}



  • 示例6:

/*************************************************
**
**Description: 列表容器的splice接合操作示例
1.splice(p, s2, q1, q2): 将s2中[q1, q2)移动到s1中p所指向元素之前
**
** Author:慕灵阁-wupke
** Time:2022-1-8
** Versions :9-6.cpp
** 
*
***************************************************/

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

int main() {
	string names1[] = { "Alice", "Helen", "Lucy", "Susan" };
	string names2[] = { "Bob", "David", "Levin", "Mike" };
	list<string> s1(names1, names1 + 4); //用names1数组的内容构造列表s1
	list<string> s2(names2, names2 + 4); //用names2数组的内容构造列表s2

	//将s1的第一个元素放到s2的最后
	s2.splice(s2.end(), s1, s1.begin());
	list<string>::iterator iter1 = s1.begin(); //iter1指向s1首
	advance(iter1, 2); //iter1前进2个元素,它将指向s1第3个元素
	list<string>::iterator iter2 = s2.begin();  //iter2指向s2首
	++iter2; //iter2前进1个元素,它将指向s2第2个元素
	list<string>::iterator iter3 = iter2; //用iter2初始化iter3
	advance(iter3, 2); //iter3前进2个元素,它将指向s2第4个元素
	//将[iter2, iter3)范围内的结点接到s1中iter1指向的结点前
	s1.splice(iter1, s2, iter2, iter3); 

	//分别将s1和s2输出
	copy(s1.begin(), s1.end(), ostream_iterator<string>(cout, " "));
	cout << endl;
	copy(s2.begin(), s2.end(), ostream_iterator<string>(cout, " "));
	cout << endl;

    system("pause");
	return 0;
}


  • 示例7:

/*************************************************
**
**Description: 栈容器示例:利用栈反向输出单词
**
** Author:慕灵阁-wupke
** Time:2022-1-8
** Versions :9-7.cpp
** 
*
***************************************************/

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

int main() {
	stack<char> s;
	string str;
	cin >> str;	//从键盘输入一个字符串(无逗号分隔)

	//将字符串的每个元素顺序压入栈中
	for (string::iterator iter = str.begin(); iter != str.end(); ++iter)
		s.push(*iter);

	//将栈中的元素顺序弹出并输出
	while (!s.empty()) {
		cout << s.top();
		s.pop();
	}
	cout << endl;

    system("pause");
	return 0;
}


  • 示例8:

/*************************************************
**
**Description: 优先级队列示例:
     优先级队列也像栈和队列一样支持元素的压入和弹出,
     但元素弹出的顺序与元素的大小有关,每次弹出的总是容器中最“大”的一个元素。
** Author:慕灵阁-wupke
** Time:2022-1-8
** Versions :9-8.cpp
** 
*
***************************************************/
//10_8.cpp
#include <queue>
#include <iostream>
#include <cstdlib>
#include <ctime>
using namespace std;

const int SPLIT_TIME_MIN = 500;		//细胞分裂最短时间
const int SPLIT_TIME_MAX = 2000;	//细胞分裂最长时间

class Cell;
priority_queue<Cell> cellQueue;

class Cell {	//细胞类
private:
	static int count;	//细胞总数
	int id;		//当前细胞编号
	int time;	//细胞分裂时间
public:
	Cell(int birth) : id(count++) {	//birth为细胞诞生时间
		//初始化,确定细胞分裂时间
		time = birth + (rand() % (SPLIT_TIME_MAX - SPLIT_TIME_MIN)) + SPLIT_TIME_MIN;
	}
	int getId() const { return id; }			//得到细胞编号
	int getSplitTime() const { return time; }	//得到细胞分裂时间
	bool operator < (const Cell& s) const { return time > s.time; }	//定义“<”

	//细胞分裂
	void split() const {	
		Cell child1(time), child2(time);	//建立两个子细胞
		cout << time << "s: Cell #" << id << " splits to #"
			<< child1.getId() << " and #" << child2.getId() << endl;
		cellQueue.push(child1);	//将第一个子细胞压入优先级队列
		cellQueue.push(child2);	//将第二个子细胞压入优先级队列
	}
};
int Cell::count = 0;

int main() {
	srand(static_cast<unsigned>(time(0)));
	int t;	//模拟时间长度
	cout << "Simulation time: ";
	cin >> t;
	cellQueue.push(Cell(0));	//将第一个细胞压入优先级队列
	while (cellQueue.top().getSplitTime() <= t) {
		cellQueue.top().split();	//模拟下一个细胞的分裂
		cellQueue.pop();			//将刚刚分裂的细胞弹出
	}
    //system("pause");
	return 0;
}


  • 示例9:
/*************************************************
**
**Description:@ 关联容器-集合(SET)示例
  : 输入一串实数,将重复的去掉,取最大和最小者的中值,分别输出小于等于此中值和大于等于此中值的实数
**  程序并不安全,如果用户直接输入零,集合为空,后续访问 *iter1 时候会导致未定义行为 
** Author:慕灵阁-wupke
** Time:2022-1-8
** Versions :9-9.cpp
** 
*
***************************************************/


#include<iostream>
#include<iterator>
#include<set>
#include<utility>

using namespace std;

int main(){
    set<double> s;
    cout << " 请输入一组实数,以0结尾:  " << endl;
    while (true)
    {
        double v;
        cin >> v;
        if (v==0) break;   // 输入0 表示结束
        // 尝试将v插入
        pair<set<double>::iterator,bool> r=s.insert(v);    // pair:容器的元素类型是pair,即由键类型和元素类型复合而成的二元组
        if (!r.second)   // 如果v已经存在,输出提示信息
            cout<< v << " is duplicated " << endl;   
    }
    //得到第一个元素的迭代器
    set<double>::iterator iter1=s.begin();
    //得到末尾的迭代器
    set<double>::iterator iter2=s.end();
    //得到最小和最大元素的中值
    double medium = (*iter1+*(--iter2)) / 2;
    //输出最小和最大元素的中值
    cout <<  " medium is : " << medium << endl;

    //输出小于或等于中值的元素                                           // 集合是有序的
    cout << " <= medium : " ;
    copy(s.begin(),s.upper_bound(medium),ostream_iterator<double>(cout," "));// 定界:upperbound 找到s中,从第一位数开始到分界点之间的元素,输入到输出流中
    cout << endl;
    //输出大于或等于中值的元素
    cout << " >= medium : " ;
    copy(s.lower_bound(medium),s.end(),ostream_iterator<double>(cout," ")); // 定界:upperbound 分界点到集合最后一个元素之间找到s中比  medium 大的数
    cout << endl;

    system("pause");
    return 0;
}



  • 示例10:
/*************************************************
**
**Description:@ 关联容器-映射(map)示例

**  有五门课程,每门都有相应学分,从中选择三门,输出学分总和

** Author:慕灵阁-wupke
** Time:2022-1-8
** Versions :9-10.cpp
** 
*
***************************************************/

#include <iostream>
#include <map>
#include <string>
#include <utility>
using namespace std;

int main() {
	map<string, int> courses;
	//将课程信息插入courses映射中
	courses.insert(make_pair("CSAPP", 3));
	courses.insert(make_pair("C++", 2));
	courses.insert(make_pair("CSARCH", 4));
	courses.insert(make_pair("COMPILER", 4));
	courses.insert(make_pair("OS", 5));

	int n = 3;		//剩下的可选次数
	int sum = 0;	//学分总和
	while (n > 0) {
		string name;
		cin >> name;	//输入课程名称
		map<string, int>::iterator iter = courses.find(name);//查找课程
		if (iter == courses.end()) {	//判断是否找到
			cout << name << " is not available" << endl;
		} else {
			sum += iter->second;	//累加学分
			courses.erase(iter);	//将刚选过的课程从映射中删除
			n--;
		}
	}

	cout << "Total credit: " << sum << endl;	//输出总学分
	return 0;
}



  • 示例11:
/*************************************************
**
**Description:  映射示例 :统计一句话中每个字母出现的次数
**
** Author:慕灵阁-wupke
** Time:2021-1-8
** Versions :9-11.cpp
** 
*
***************************************************/
/*
• 映射与集合同属于单重关联容器,它们的主要区别在于,集合的元素类型是键本身,而映射的元素类型是由键和附加数据所构成的二元组。
• 在集合中按照键查找一个元素时,一般只是用来确定这个元素是否存在,而在映射中按照键查找一个元素时,除了能确定它的存在性外,还可以得到相应的附加数据。
*/

#include<iostream>
#include<map>
#include<cctype>

using namespace std;

int main(){
    map<char,int> s;  // 声明用来存储字母出现次数的映射
    char c;            //存储输入的字符
    cout<< "please input some words end with '.':   " << endl;
    do{
        cin >> c;      //输入下一个字符
        if (isalpha(c)){  // 判断是否为字母
            c = tolower(c);  // 将字母转化为小写
            s[c]++;  //  将该字母出现的频率 + 1 ,这里用了下标运算,如果映射中没有C 就将c插入映射中,如果已经有了,就返回c的引用 +1
        }
        }while (c!='.');  // 遇到'.'则结束输入
        //输出每个字母出现的次数
        for(map<char,int>::iterator iter = s.begin();iter !=s.end();++iter)  // 循环,用迭代器遍历整个映射
            cout << iter->first << " " << iter->second << " " ;
        cout << endl;

        system("pause");
        return 0;
}


  • 示例12:
/*************************************************
**
**Description:  @关联容器- 多重集合和多重映射 :查询上课时间
**
** Author:慕灵阁-wupke
** Time:2021-1-8
** Versions :9-12.cpp
** 
*
***************************************************/
#include <iostream>
#include <map>
#include <utility>
#include <string>
using namespace std;

int main() {
	multimap<string, string> courses;
	typedef multimap<string, string>::iterator CourseIter;

	//将课程上课时间插入courses映射中
	courses.insert(make_pair("C++", "2-6"));
	courses.insert(make_pair("COMPILER", "3-1"));
	courses.insert(make_pair("COMPILER", "5-2"));
	courses.insert(make_pair("OS", "1-2"));
	courses.insert(make_pair("OS", "4-1"));
	courses.insert(make_pair("OS", "5-5"));
	//输入一个课程名,直到找到该课程为止,记下每周上课次数
	string name;
	int count;
	do {
        cout<<"input one of condiate courses: C++/COMPILER/OS "<<endl;
		cin >> name;
		count = courses.count(name);
		if (count == 0)
			cout << "Cannot find this course!" << endl;
	} while (count == 0);
	//输出每周上课次数和上课时间
	cout << count << " lesson(s) per week: ";
	pair<CourseIter, CourseIter> range = courses.equal_range(name);
	for (CourseIter iter = range.first; iter != range.second; ++iter)
		cout << iter->second << " ";
	cout << endl;

    system("pause");
	return 0;
}


  • 示例13:
/*************************************************
**
**Description:  @函数对象实例:通过定义普通函数表示乘法的函数对象
**
** Author:慕灵阁-wupke
** Time:2021-1-8
** Versions :9-13.cpp
** 
*
***************************************************/
#include <iostream>   
#include <numeric>	//包含数值算法头文件
using namespace std;

int mult(int x, int y) { //定义一个普通函数
    return x * y; 
    };	
int main() {
	int a[] = { 1, 2, 3, 4, 5 };
	const int N = sizeof(a) / sizeof(int);
	cout << "The result by multipling all elements in a is "
		<< accumulate(a, a + N, 1, mult)	//将普通函数mult传递给通用算法 :(在数组a中依次进行mult运算(累乘))实现 1*2*3*4*5 = 120
		<< endl;

    system("pause");
	return 0;
}

  • 示例14:
/*************************************************
**
**Description:  @函数对象实例:通过重载类的“()”运算符表示乘法的函数对象
**
** Author:慕灵阁-wupke
** Time:2021-1-8
** Versions :9-14.cpp
** 
*
***************************************************/
#include <iostream>
#include <numeric>	//包含数值算法头文件
using namespace std;

class MultClass	{  //定义MultClass类
public:
	int operator() (int x, int y) const { return x * y; }	//重载操作符operator()
};

int main() {
	int a[] = { 1, 2, 3, 4, 5 };
	const int N = sizeof(a) / sizeof(int);
	cout << "The result by multipling all elements in a is "
		<< accumulate(a, a + N, 1, MultClass())	//将类multclass传递给通用算法:在数组a中依次进行mult运算(累乘)
		<< endl;

    system("pause");
	return 0;
}

  • 示例15:
/*************************************************
**
**Description:  @函数对象实例:STL提供的函数对象,表示乘法的函数对象
**
** Author:慕灵阁-wupke
** Time:2021-1-8
** Versions :9-15.cpp
** 
*
***************************************************/
#include <iostream>   
#include <numeric>   //包含数值算法头文件
#include <functional>  //包含标准函数对象头文件
using namespace std;	
int main() {
	int a[] = { 1, 2, 3, 4, 5,2 };
	const int N = sizeof(a) / sizeof(int);
	cout << "The result by multipling all elements in A is "
		<< accumulate(a, a + N, 1, multiplies<int>()) //将标准函数对象传递给通用算法
		<< endl;

    system("pause");
	return 0;
}


  • 示例16:
/*************************************************
**
**Description:  @STL提供的函数对象实例:利用STL中的二元谓词函数对象实现将一个数组按照从大到小的顺序排序
**
** Author:慕灵阁-wupke
** Time:2021-1-8
** Versions :9-16.cpp
** 
*
***************************************************/
#include <functional>
#include <iostream>
#include <vector>
#include <iterator>
#include <algorithm>
using namespace std;

int main() {
	int intArr[] = { 23,25,9,30, 90, 10, 40, 70, 50, 20, 80 };
	const int N = sizeof(intArr) / sizeof(int);
	vector<int> a(intArr, intArr + N);

	cout << "before sorting:" << endl;
	copy(a.begin(), a.end(), ostream_iterator<int>(cout, "\t"));
	cout << endl;

	sort(a.begin(), a.end(), greater<int>());

	cout << "after sorting:" << endl;
	copy(a.begin(), a.end(), ostream_iterator<int>(cout, "\t"));
	cout << endl;

    system("pause");
	return 0;
}

  • 示例17:
/*************************************************
**
**Description:  @函数适配器实例: (绑定适配器) 找到数组中第一个大于55的元素
**
** Author:慕灵阁-wupke
** Time:2021-1-8
** Versions :9-17.cpp
** 
*
***************************************************/

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

int main() {
	int intArr[] = { 5,7,8,24,30, 90, 10, 40, 70, 50, 20, 80 };
	const int N = sizeof(intArr) / sizeof(int);
    cout << N << endl;
	vector<int> a(intArr, intArr + N);
	vector<int>::iterator p = find_if(a.begin(), a.end(), bind2nd(greater<int>(),55)); 
	if (p == a.end())
		cout << "no element greater than 55" << endl; // 找不到符合的结果
	else
		cout << "first element greater than 55 is: " << *p << endl; // 找到,输出

    system("pause");
	return 0;
}
/*
注:
find_if算法在STL中的原型声明为:
template<class InputIterator, class UnaryPredicate>
InputIterator find_if(InputIterator first, InputIterator last, UnaryPredicate pred);
它的功能是查找数组[first, last)区间中第一个pred(x)为真的元素。
*/

  • 示例18:
/*************************************************
**
**Description:  @函数适配器实例:  ptr_fun、not1和not2产生函数适配器实例
**
** Author:慕灵阁-wupke
** Time:2021-1-8
** Versions :9-18.cpp
** 
*
***************************************************/

#include <functional>   // 头文件
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;

bool g(int x, int y) {
	return x > y;
}

int main() {
	int intArr[] = { 30, 90, 10, 40, 70, 50, 20, 80 };
	const int N = sizeof(intArr) / sizeof(int);
	vector<int> a(intArr, intArr + N);

	vector<int>::iterator p;
	p = find_if(a.begin(), a.end(), bind2nd(ptr_fun(g), 40));
	if (p == a.end())
		cout << "no element greater than 40" << endl;
	else
		cout << "first element greater than 40 is: " << *p << endl;

	p = find_if(a.begin(), a.end(), not1(bind2nd(greater<int>(), 15)));
	if (p == a.end())
		cout << "no element is not greater than 15" << endl;
	else
		cout << "first element that is not greater than 15 is: " << *p << endl;

	p = find_if(a.begin(), a.end(), bind2nd(not2(greater<int>()), 15));
	if (p == a.end())
		cout << "no element is not greater than 15" << endl;
	else
		cout << "first element that is not greater than 15 is: " << *p << endl;

    system("pause");
	return 0;
}


  • 示例19:
/*************************************************
**
**Description:  @成员函数适配器实例
**
** Author:慕灵阁-wupke
** Time:2021-1-8
** Versions :9-19.cpp
** 
*
***************************************************/
#include <functional>
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;

struct Car {
	int id;
	Car(int id) { this->id = id; }
	void display() const { cout << "car " << id << endl; }
};

int main() {
	vector<Car *> pcars;
	vector<Car> cars;
	for (int i = 0; i < 5; i++)
		pcars.push_back(new Car(i));
	for (int i = 5; i < 10; i++)
		cars.push_back(Car(i));

	cout << "elements in pcars: " << endl;
	for_each(pcars.begin(), pcars.end(), std::mem_fun(&Car::display));
	cout << endl;

	cout << "elements in cars: " << endl;
	for_each(cars.begin(), cars.end(), std::mem_fun_ref(&Car::display));
	cout << endl;

	for (size_t i = 0; i < pcars.size(); ++i)
		delete pcars[i];

    system("pause");
	return 0;
}

  • 示例20:
/*************************************************
**
**Description:  @STL算法实例: 查找算法
**
** Author:慕灵阁-wupke
** Time:2021-1-8
** Versions :9-20.cpp
** 
*
***************************************************/

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

int main() {
	int iarray[] = { 0, 1, 2, 3, 4, 5, 6, 6, 6, 7, 8 };
	vector<int> ivector(iarray, iarray + sizeof(iarray) / sizeof(int));
	int iarray1[] = { 6, 6 };
	vector<int> ivector1(iarray1, iarray1 + sizeof(iarray1) / sizeof(int));
	int iarray2[] = { 5, 6 };
	vector<int> ivector2(iarray2, iarray2 + sizeof(iarray2) / sizeof(int));
	int iarray3[] = { 0, 1, 2, 3, 4, 5, 7, 7, 7, 9, 7 };
	vector<int> ivector3(iarray3, iarray3 + sizeof(iarray3) / sizeof(int));

	//找出ivector之中相邻元素值相等的第一个元素
	cout << *adjacent_find(ivector.begin(), ivector.end()) << endl; 

	//找出ivector之中小于7的元素个数
	cout << count_if(ivector.begin(), ivector.end(), bind2nd(less<int>(), 7)) << endl; 

	//找出ivector之中大于2的第一个元素所在位置的元素
	cout <<  *find_if(ivector.begin(), ivector.end(), bind2nd(greater<int>(), 2)) << endl; 
	
	//子序列ivector2在ivector中出现的起点位置元素
	cout << *search(ivector.begin(), ivector.end(), ivector2.begin(), ivector2.end()) << endl;

	//查找连续出现36的起点位置元素
	cout << *search_n(ivector.begin(), ivector.end(), 3, 6, equal_to<int>()) << endl;
	
	//判断两个区间ivector和ivector3相等否(0为假,1为真)
	cout << equal(ivector.begin(), ivector.end(), ivector3.begin()) << endl;

	//查找区间ivector3在ivector中不匹配点的位置
	pair<vector<int>::iterator, vector<int>::iterator> result = 
		mismatch(ivector.begin(), ivector.end(), ivector3.begin());
	cout << result.first - ivector.begin() << endl; 
	
	system("pause");
	return 0;
}



  • 示例21:
/*************************************************
**
**Description:  @STL算法实例: 遍历填充、删除、旋转
**
** Author:慕灵阁-wupke
** Time:2021-1-8
** Versions :9-21.cpp
** 
*
***************************************************/

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

class evenByTwo {
private:
	int x;
public:
	evenByTwo() : x(0) { }
	int operator () () { return x += 2; }
};

int main() {
	int iarray1[]= { 0, 1, 2, 3, 4, 4, 5, 5, 6, 6, 6, 6, 6, 7, 8 };
	int iarray2[] = { 0, 1, 2, 3, 4, 5, 6, 6, 6, 7, 8 };
	vector<int> ivector1(iarray1, iarray1 + sizeof(iarray1) / sizeof(int));
	vector<int> ivector2(iarray2, iarray2 + sizeof(iarray2) / sizeof(int));
	vector<int> ivector3(2); 
	ostream_iterator<int> output(cout, " ");  //定义流迭代器用于输出数据
	
	//迭代遍历ivector3区间,每个元素填上-1
	fill(ivector3.begin(), ivector3.end(), -1);
	copy(ivector3.begin(), ivector3.end(), output);	// 使用copy进行输出
	cout << endl;

	//迭代遍历ivector3区间,对每一个元素进行evenByTwo操作
	generate(ivector3.begin(), ivector3.end(), evenByTwo());
	copy(ivector3.begin(), ivector3.end(), output);
	cout << endl; 

	//将删除元素6后的ivector2序列置于另一个容器ivector4之中
	vector<int> ivector4;
	remove_copy(ivector2.begin(), ivector2.end(), back_inserter(ivector4), 6);
	copy(ivector4.begin(), ivector4.end(), output);
	cout << endl; 

	//删除小于6的元素
	ivector2.erase(remove_if(ivector2.begin(), ivector2.end(), bind2nd(less<int>(), 6)), ivector2.end());
	copy(ivector2.begin(), ivector2.end(), output);
	cout << endl; 
	
	//将所有的元素值6,改为元素值3
	replace(ivector2.begin(), ivector2.end(), 6, 3);
	copy(ivector2.begin(), ivector2.end(), output);
	cout << endl; 
	
	//逆向重排每一个元素
	reverse(ivector2.begin(), ivector2.end());
	copy(ivector2.begin(), ivector2.end(), output);
	cout << endl; 
	
	//旋转(互换元素)[first, middle),[middle, end),结果直接输出
	rotate_copy(ivector2.begin(), ivector2.begin() + 3, ivector2.end(), output);
	cout << endl;

    system("pause");
	return 0;
}


  • 示例22:
/*************************************************
**
**Description:  @STL算法实例: 排序、合并
**
** Author:慕灵阁-wupke
** Time:2021-1-8
** Versions :9-22.cpp
** 
*
***************************************************/

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

int main() {
	int iarray[] = { 26, 17, 15, 22, 23, 33, 32, 40 };
	vector<int> ivector(iarray, iarray + sizeof(iarray) / sizeof(int));
	
	// 查找并输出第一个最大值元素及其位置
	vector<int>::iterator p = max_element(ivector.begin(), ivector.end());
	int n = p  - ivector.begin();
	cout << "max element: " << *p << " found at " << n << endl;

	//局部排序并复制到别处
	vector<int> ivector1(5);
	partial_sort_copy(ivector.begin(), ivector.end(), ivector1.begin(), ivector1.end());
	copy(ivector1.begin(), ivector1.end(), ostream_iterator<int>(cout, " "));
	cout << endl; 

	//排序,缺省为递增。
	sort(ivector.begin(), ivector.end());
	copy(ivector.begin(), ivector.end(), ostream_iterator<int>(cout, " "));
	cout << endl; 

	// 返回小于等于24和大于等于24的元素的位置
	cout << *lower_bound(ivector.begin(), ivector.end(), 24) << endl;
	cout << *upper_bound(ivector.begin(), ivector.end(), 24) << endl;

	//对于有序区间,可以用二分查找方法寻找某个元素
    cout << binary_search(ivector.begin(), ivector.end(), 33) << endl;

	//合并两个序列ivector和ivector1,并将结果放到ivector2中
	vector<int> ivector2(13);
	merge(ivector.begin(), ivector.end(), ivector1.begin(), ivector1.end(), ivector2.begin());
	copy(ivector2.begin(), ivector2.end(), ostream_iterator<int>(cout, " "));
	cout << endl; 

	//将小于*(ivector.begin()+5)的元素放置在该元素之左
	//其余置于该元素之右。不保证维持原有的相对位置
	nth_element(ivector2.begin(), ivector2.begin() + 5, ivector2.end());
	copy(ivector2.begin(), ivector2.end(), ostream_iterator<int>(cout, " "));
	cout << endl; 

	//排序,并保持原来相对位置
	stable_sort(ivector2.begin(), ivector2.end());
	copy(ivector2.begin(), ivector2.end(), ostream_iterator<int>(cout, " "));
	cout << endl; 

	//合并两个有序序列,然后就地替换
	int iarray3[] = { 1, 3, 5, 7, 2, 4, 6, 8 };
	vector<int> ivector3(iarray3, iarray3 + sizeof(iarray3) / sizeof(int));
	inplace_merge(ivector3.begin(), ivector3.begin() + 4, ivector3.end());
	copy(ivector3.begin(), ivector3.end(), ostream_iterator<int>(cout, " "));  
	cout<<endl; 
	
	//以字典顺序比较序列ivector3和ivector4
	int iarray4[] = { 1, 3, 5, 7, 1, 5, 9, 3 };
	vector<int> ivector4(iarray4, iarray4 + sizeof(iarray4) / sizeof(int));
	cout<< lexicographical_compare(ivector3.begin(), ivector3.end(), ivector4.begin(), ivector4.end()) << endl;

    system("pause");
	return 0;
}



  • 示例23:
/*************************************************
**
**Description:  @STL算法实例:  数值算法
**
** Author:慕灵阁-wupke
** Time:2021-1-8
** Versions :9-23.cpp
** 
*
***************************************************/

#include <iostream>
#include <numeric>
#include <functional>
#include <iterator>
#include <vector>
using namespace std;

int main() {
	int iarray[] = { 1, 2, 3, 4, 5 };
	vector<int> ivector(iarray, iarray + sizeof(iarray) / sizeof(int));

	//元素的累计
	cout << accumulate(ivector.begin(), ivector.end(), 0) << endl;
	//向量的内积
	cout << inner_product(ivector.begin(), ivector.end(), ivector.begin(), 10) << endl;
	//向量容器中元素局部求和
	partial_sum(ivector.begin(), ivector.end(), ostream_iterator<int>(cout," "));
	cout << endl;
	//向量容器中相邻元素的差值
	adjacent_difference(ivector.begin(), ivector.end(), 
    ostream_iterator<int>(cout," "));
	cout << endl;

    system("pause");
	return 0;
}

  • 示例24:
/*************************************************
**
**Description:  综合实例:个人银行账户管理程序(流类库与输入输出)
        改进: 解决如何在下次启动程序时候可以回复上次的数据
        思路1:程序结束时将每个账户当前的状态和过往的账目列表写入文件,下次运行时再读出来(操作信息繁多,程序复杂,不推荐使用)
        思路2:将各种命令保存下来,在下次程序启动时,将这些命令读出并执行,这样各个账户就可以回复上次退出程序时的状态了
        
        在接受用户输入的命令时,程序 以字符串的形式读入整条命令,将命令写入文件时,只要向文件输出整个命令字符串即可。
        对 Date 重载了 ">>" 运算符

        整个代码分6个文件;

** Author:慕灵阁-wupke
** Time:2021-1-8
** Versions :9-24.cpp
** 
*
***************************************************/


//1-main.cpp
#include "account.h"
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;

struct deleter {
	template <class T> void operator () (T* p) { delete p; }
};

int main() {
	Date date(2008, 11, 1);	//起始日期
	vector<Account *> accounts;	//创建账户数组,元素个数为0
	cout << "(a)add account (d)deposit (w)withdraw (s)show (c)change day (n)next month (q)query (e)exit" << endl;
	char cmd;
	do {
		//显示日期和总金额
		date.show();
		cout << "\tTotal: " << Account::getTotal() << "\tcommand> ";

		char type;
		int index, day;
		double amount, credit, rate, fee;
		string id, desc;
		Account* account;
		Date date1, date2;

		cin >> cmd;
		switch (cmd) {
		case 'a':	//增加账户
			cin >> type >> id;
			if (type == 's') {
				cin >> rate;
				account = new SavingsAccount(date, id, rate);
			} else {
				cin >> credit >> rate >> fee;
				account = new CreditAccount(date, id, credit, rate, fee);
			}
			accounts.push_back(account);
			break;
		case 'd':	//存入现金
			cin >> index >> amount;
			getline(cin, desc);
			accounts[index]->deposit(date, amount, desc);
			break;
		case 'w':	//取出现金
			cin >> index >> amount;
			getline(cin, desc);
			accounts[index]->withdraw(date, amount, desc);
			break;
		case 's':	//查询各账户信息
			for (size_t i = 0; i < accounts.size(); i++) {
				cout << "[" << i << "] ";
				accounts[i]->show();
				cout << endl;
			}
			break;
		case 'c':	//改变日期
			cin >> day;
			if (day < date.getDay())
				cout << "You cannot specify a previous day";
			else if (day > date.getMaxDay())
				cout << "Invalid day";
			else
				date = Date(date.getYear(), date.getMonth(), day);
			break;
		case 'n':	//进入下个月
			if (date.getMonth() == 12)
				date = Date(date.getYear() + 1, 1, 1);
			else
				date = Date(date.getYear(), date.getMonth() + 1, 1);
			for (vector<Account*>::iterator iter = accounts.begin(); iter != accounts.end(); ++iter)
				(*iter)->settle(date);
			break;
		case 'q':	//查询一段时间内的账目
			date1 = Date::read();
			date2 = Date::read();
			Account::query(date1, date2);
			break;
		}
	} while (cmd != 'e');
	for_each(accounts.begin(), accounts.end(), deleter());

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





//2-account.cpp
#include "account.h"
#include <cmath>
#include <iostream>
#include <utility>
using namespace std;
using namespace std::rel_ops;

//AccountRecord类的实现
AccountRecord::AccountRecord(const Date &date, const Account *account, double amount, double balance, const std::string& desc)
	: date(date), account(account), amount(amount), balance(balance), desc(desc) { }

void AccountRecord::show() const {
	date.show();
	cout << "\t#" << account->getId() << "\t" << amount << "\t" << balance << "\t" << desc << endl;
}

//Account类的实现
double Account::total = 0;
RecordMap Account::recordMap;
Account::Account(const Date &date, const string &id)
	: id(id), balance(0) {
	date.show();
	cout << "\t#" << id << " created" << endl;
}

void Account::record(const Date &date, double amount, const string &desc) {
	amount = floor(amount * 100 + 0.5) / 100;	//保留小数点后两位
	balance += amount;
	total += amount;
	AccountRecord record(date, this, amount, balance, desc);
	recordMap.insert(make_pair(date, record));
	record.show();
}

void Account::show() const {
	cout << id << "\tBalance: " << balance;
}

void Account::error(const string &msg) const {
	cout << "Error(#" << id << "): " << msg << endl;
}

void Account::query(const Date& begin, const Date& end) {
	if (begin <= end) {
		RecordMap::iterator iter1 = recordMap.lower_bound(begin);
		RecordMap::iterator iter2 = recordMap.upper_bound(end);
		for (RecordMap::iterator iter = iter1; iter != iter2; ++iter)
			iter->second.show();
	}
}

//SavingsAccount类相关成员函数的实现
SavingsAccount::SavingsAccount(const Date &date, const string &id, double rate)
	: Account(date, id), rate(rate), acc(date, 0) { }

void SavingsAccount::deposit(const Date &date, double amount, const string &desc) {
	record(date, amount, desc);
	acc.change(date, getBalance());
}

void SavingsAccount::withdraw(const Date &date, double amount, const string &desc) {
	if (amount > getBalance()) {
		error("not enough money");
	} else {
		record(date, -amount, desc);
		acc.change(date, getBalance());
	}
}

void SavingsAccount::settle(const Date &date) {
	if (date.getMonth() == 1) {	//每年的一月计算一次利息
		double interest = acc.getSum(date) * rate
			/ (date - Date(date.getYear() - 1, 1, 1));
		if (interest != 0)
			record(date, interest, " interest");
		acc.reset(date, getBalance());
	}
}

//CreditAccount类相关成员函数的实现
CreditAccount::CreditAccount(const Date& date, const string& id, double credit, double rate, double fee)
	: Account(date, id), credit(credit), rate(rate), fee(fee), acc(date, 0) { }

void CreditAccount::deposit(const Date &date, double amount, const string &desc) {
	record(date, amount, desc);
	acc.change(date, getDebt());
}

void CreditAccount::withdraw(const Date &date, double amount, const string &desc) {
	if (amount - getBalance() > credit) {
		error("not enough credit");
	} else {
		record(date, -amount, desc);
		acc.change(date, getDebt());
	}
}

void CreditAccount::settle(const Date &date) {
	double interest = acc.getSum(date) * rate;
	if (interest != 0)
		record(date, interest, " interest");
	if (date.getMonth() == 1)
		record(date, -fee, " annual fee");
	acc.reset(date, getDebt());
}

void CreditAccount::show() const {
	Account::show();
	cout << "\tAvailable credit:" << getAvailableCredit();
}





//3-account.h
#ifndef __ACCOUNT_H__
#define __ACCOUNT_H__
#include "date.h"
#include "accumulator.h"
#include <string>
#include <map>

class Account;	//前置声明

class AccountRecord {	//账目记录
private:
	Date date;				//日期
	const Account *account;	//账户
	double amount;			//金额
	double balance;			//余额
	std::string desc;		//描述
public:
	//构造函数
	AccountRecord(const Date &date, const Account *account, double amount, double balance, const std::string& desc);
	void show() const;	//输出当前记录
};

//定义用来存储账目记录的多重映射类型
typedef std::multimap<Date, AccountRecord> RecordMap;

class Account { //账户类
private:
	std::string id;	//帐号
	double balance;	//余额
	static double total; //所有账户的总金额
	static RecordMap recordMap;	//账目记录
protected:
	//供派生类调用的构造函数,id为账户
	Account(const Date &date, const std::string &id);
	//记录一笔帐,date为日期,amount为金额,desc为说明
	void record(const Date &date, double amount, const std::string &desc);
	//报告错误信息
	void error(const std::string &msg) const;
public:
	const std::string &getId() const { return id; }
	double getBalance() const { return balance; }
	static double getTotal() { return total; }
	//存入现金,date为日期,amount为金额,desc为款项说明
	virtual void deposit(const Date &date, double amount, const std::string &desc) = 0;
	//取出现金,date为日期,amount为金额,desc为款项说明
	virtual void withdraw(const Date &date, double amount, const std::string &desc) = 0;
	//结算(计算利息、年费等),每月结算一次,date为结算日期
	virtual void settle(const Date &date) = 0;
	//显示账户信息
	virtual void show() const;
	//查询指定时间内
	static void query(const Date& begin, const Date& end);
};

class SavingsAccount : public Account { //储蓄账户类
private:
	Accumulator acc;	//辅助计算利息的累加器
	double rate;		//存款的年利率
public:
	//构造函数
	SavingsAccount(const Date &date, const std::string &id, double rate);
	double getRate() const { return rate; }
	virtual void deposit(const Date &date, double amount, const std::string &desc);
	virtual void withdraw(const Date &date, double amount, const std::string &desc);
	virtual void settle(const Date &date);
};

class CreditAccount : public Account { //信用账户类
private:
	Accumulator acc;	//辅助计算利息的累加器
	double credit;		//信用额度
	double rate;		//欠款的日利率
	double fee;			//信用卡年费

	double getDebt() const {	//获得欠款额
		double balance = getBalance();
		return (balance < 0 ? balance : 0);
	}
public:
	//构造函数
	CreditAccount(const Date &date, const std::string &id, double credit, double rate, double fee);
	double getCredit() const { return credit; }
	double getRate() const { return rate; }
	double getFee() const { return fee; }
	double getAvailableCredit() const {	//获得可用信用
		if (getBalance() < 0) 
			return credit + getBalance();
		else
			return credit;
	}
	virtual void deposit(const Date &date, double amount, const std::string &desc);
	virtual void withdraw(const Date &date, double amount, const std::string &desc);
	virtual void settle(const Date &date);
	virtual void show() const;
};

#endif //__ACCOUNT_H__






//4-accumulator.h
#ifndef __ACCUMULATOR_H__
#define __ACCUMULATOR_H__
#include "date.h"

class Accumulator {	//将某个数值按日累加
private:
	Date lastDate;	//上次变更数值的时期
	double value;	//数值的当前值
	double sum;		//数值按日累加之和
public:
	//构造函数,date为开始累加的日期,value为初始值
	Accumulator(const Date &date, double value)
		: lastDate(date), value(value), sum(0) { }

	//获得到日期date的累加结果
	double getSum(const Date &date) const {
		return sum + value * (date - lastDate);
	}

	//在date将数值变更为value
	void change(const Date &date, double value) {
		sum = getSum(date);
		lastDate = date;
		this->value = value;
	}

	//初始化,将日期变为date,数值变为value,累加器清零
	void reset(const Date &date, double value) {
		lastDate = date;
		this->value = value;
		sum = 0;
	}
};

#endif //__ACCUMULATOR_H__





//5-date.cpp
#include "date.h"
#include <iostream>
#include <cstdlib>
using namespace std;

namespace {	//namespace使下面的定义只在当前文件中有效
	//存储平年中某个月1日之前有多少天,为便于getMaxDay函数的实现,该数组多出一项
	const int DAYS_BEFORE_MONTH[] = { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 };
}

Date::Date(int year, int month, int day) : year(year), month(month), day(day) {
	if (day <= 0 || day > getMaxDay()) {
		cout << "Invalid date: ";
		show();
		cout << endl;
		exit(1);
	}
	int years = year - 1;
	totalDays = years * 365 + years / 4 - years / 100 + years / 400
		+ DAYS_BEFORE_MONTH[month - 1] + day;
	if (isLeapYear() && month > 2) totalDays++;
}

Date Date::read() {
	int year, month, day;
	char c1, c2;
	cin >> year >> c1 >> month >> c2 >> day;
	return Date(year, month, day);
}

int Date::getMaxDay() const {
	if (isLeapYear() && month == 2)
		return 29;
	else
		return DAYS_BEFORE_MONTH[month]- DAYS_BEFORE_MONTH[month - 1];
}

void Date::show() const {
	cout << getYear() << "-" << getMonth() << "-" << getDay();
}





//6-date.h
#ifndef __DATE_H__
#define __DATE_H__

class Date {	//日期类
private:
	int year;		//int month;		//int day;		//int totalDays;	//该日期是从公元元年11日开始的第几天

public:
	Date(int year = 1, int month = 1, int day = 1);	//用年、月、日构造日期
	static Date read();
	int getYear() const { return year; }
	int getMonth() const { return month; }
	int getDay() const { return day; }
	int getMaxDay() const;		//获得当月有多少天
	bool isLeapYear() const {	//判断当年是否为闰年
		return year % 4 == 0 && year % 100 != 0 || year % 400 == 0;
	}
	void show() const;			//输出当前日期
	//计算两个日期之间差多少天	
	int operator - (const Date& date) const {
		return totalDays - date.totalDays;
	}
	//判断两个日期的前后顺序
	bool operator < (const Date& date) const {
		return totalDays < date.totalDays;
	}
};

#endif //__DATE_H__


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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值