学习STL,先看看这篇STL的总结与应用吧

早前学习数据结构的时候,看到别人都能够熟练地使用STL的内容,心想什么时候自己也能够做到,就现在来说,掌握下面这些还是远远不够的,想要充分的理解STL,还是得从源码来看。

STL组件

  • 容器(Container)——管理某类对象的集合
  • 迭代器(Iterator)——在对象集合上进行遍历
  • 算法(Algorithm)——处理集合内的元素
  • 容器适配器(container adaptor)
  • 函数对象(functor)
    在这里插入图片描述

STL容器

STL容器元素的条件
  • 必须能够通过拷贝构造函数进行复制
  • 必须可以通过赋值运算符完成赋值操作
  • 必须可以通过析构函数完成销毁动作
  • 序列式容器元素的默认构造函数必须可用
  • 某些动作必须定义operator==,例如搜寻操作
  • 关联式容器必须定义出排序准则,默认情况是重载operator <
STL容器的共同操作
  • 与大小相关的操作(size operator)
    size()——返回当前容器的元素数量
    empty()——判断容器是否为空
    max_size()——返回容器能容纳的最大元素数量
  • 比较(comparison)
    ==,!=,<,<=,>,>=
    比较操作两端的容器必须属于 同一类型
    两个容器内的所有元素按序相等,则容器相等
    采用字典式顺序判断某个容器是否小于另一个容器
  • 赋值(assignment)和交换(swap)
    swap用于提高赋值操作效率
  • 与迭代器(iterator)相关的操作
    begin()——返回一个迭代器,指向第一个元素
    end()——返回一个迭代器,指向最后一个元素之后
    rbegin()——返回一个逆向迭代器,指向逆向遍历的第一个元素
    rend()——返回一个逆向迭代器,指向逆向遍历的最后一个元素之后
  • 元素操作
    insert(pos,e)——将元素e的拷贝安插于迭代器pos所指的位置
    erase(beg,end)——移除[beg,end]区间内的所有元素
    clear()——移除所有元素

STL迭代器

首先要说明一下,迭代器和指针是不完全一样的,迭代器可以完成指针的操作,但也可以完成指针完成不了的操作,之前刚刚学习的时候,以为在C语言中,叫做指针;在C++中,就该名成了迭代器,其实不是这样的。
但是在使用迭代器的时候,发现有时会报错,原因是因为迭代器 失效 了。

失效的情况
  1. 在vector等序列式容器(数组式容器)中,由于内存是连续分配的,删除当前的iterator会使后面所有元素的iterator都失效,所以不能使用erase(it++) 的方式。
    迭代器在使用后就释放了,不能再继续使用,但是指针可以!!!

例如下面情况:

#include<bits/stdc++.h>
using namespace std;
void test1()
{
    vector<int> v;
    for (int i = 0; i < 10; i++)
    {
        v.push_back(i);
    }

    vector<int>::iterator it;
    for (it = v.begin(); it != v.end(); it++)
    {
        if (*it > 3)
            v.erase(it);
    }

    for (it = v.begin(); it != v.end(); it++)
    {
        cout<<*it<<" ";
    }
}
void test2()
{
    vector<int> v;
    for (int i = 0; i < 10; i++)
    {
        v.push_back(i);
    }
    vector<int>::iterator it;
    for (it = v.begin(); it != v.end();)
    {
        if (*it > 3) {
            it = v.erase(it);
        }
        else {
            it ++;
        }
    }
    for (it = v.begin(); it != v.end(); it++)
    {
        cout<<*it<<" ";
    }
}
int  main()
{
    test1();
    cout<<endl;
    test2();
}

test1()的运行结果是错误的,test2()的运行结果是正确的。
但庆幸的是,erase()返回的对象是一个迭代器。 所以 it = v.erase(it);
,具体的上面代码已经给出。

运行结果如下:
在这里插入图片描述

  1. 关联式容器(如map、set、multimap、multiset),删除当前的iterator,仅仅会使当前的iterator失效。

指针能指向函数而迭代器不行,迭代器只能指向容器。

  • 可遍历STL容器内全部或部分元素的对象
  • 指出容器中的一个特定位置
  • 迭代器的基本操作
操作效果
*返回当前位置上的元素值。如果该元素有成员,可以通过迭代器以operator ->取用
++将迭代器前进至下一元素
==和!=判断两个迭代器是否指向同一位置
=为迭代器赋值(将所指元素的位置赋值过去)
  • 所有容器都提供两种迭代器
    container::iterator以“读/写”模式遍历元素
    container::const_iterator以“只读”模式遍历元素
  • 所有容器都提供获得迭代器的函数
    begin()——返回一个迭代器,指向第一个元素
    end()——返回一个迭代器,指向最后一个元素之后

vector的使用

操作效果
vector< T > c(n)利用类型T的默认构造函数和拷贝构造函数生成一个大小为n的vector
vector< T > c(beg,end)产生一个vector,以区间[beg,end]为元素初值
~vector< T >()销毁所有元素并释放内存
c.capacity()返回重新分配空间前可容纳的最大元素数量
c.reserve(n)扩大容量为n
c.max_size()返回元素最大可能数量(固定值)
c.assign(n,e)将元素e的n个拷贝赋值给c
at(idx)返回索引idx所标识的元素的引用,进行越界检查
operator【】(idx)返回索引idx所标识的元素的引用,不进行越界检查
c.push_back(e)在尾部添加一个元素e的副本
c.pop_back()移除最后一个元素但不返回最后一个元素
c.erase(pos)删除pos位置的元素,返回下一个元素的位置
c.clear()移除所有元素,清空容器
c.resize(num)将元素数量改为num(增加的元素用defalut构造函数产生,多余的元素被删除)
添加元素
  1. 向向量a中直接添加元素
vector<int> a;
for(int i=0;i<10;i++)
	a.push_back(i);
  1. 从数组中向向量添加元素
int a[6]={1,2,3,4,5,6};
vector<int> b;
for(int i=1;i<=4;i++)
	b.push_back(a[i]);
  1. 从数组中添加元素到向量中
int a[6]={1,2,3,4,5,6};
vector<int> b;
vector<int> c(a,a+4);
for(vector<int>::iterator it=c.begin();it<c.end();it++)
	b.push_back(*it);
  1. 从文件中读取元素向向量中添加
ifstream in("data.txt");
vector<int> a;
for(int i; in>>i)
    a.push_back(i);

【误区】:不可v[i]=i;赋值。下标只能用于获取已存在的元素

一定一定注意重载运算符
例如下面就是没有重载运算符导致的报错。
在这里插入图片描述

读取元素
  1. 通过下标
int a[6]={1,2,3,4,5,6};
vector<int> b(a,a+4);
for(int i=0;i<=b.size()-1;i++)
    cout<<b[i]<<" ";
  1. 遍历器方式
int a[6]={1,2,3,4,5,6};
vector<int> b(a,a+4);
for(vector<int>::iterator it=b.begin();it!=b.end();it++)
    cout<<*it<<" ";

map/multimap的使用

count(key)返回”键值等于key”的元素个数
find(key)返回”键值等于key”的第一个元素,找不到返回end
lower_bound(key)返回”键值大于等于key”的第一个元素
upper_bound(key)返回”键值大于key”的第一个元素
equal_range(key)返回”键值等于key”的元素区间
c.erase(pos)删除迭代器pos所指位置的元素,无返回值
c.erase(val)移除所有值为val的元素,返回移除元素个数
c.erase(beg,end)删除区间[beg,end]内所有元素,无返回值
c.clear()移除所有元素,清空容器
插入数据
  1. 使用insert()函数
#include<bits/stdc++.h>
using namespace std;
int main()
{
    map<int,string> mapStudent;
    mapStudent.insert(pair<int,string>(1, "student_one"));
    mapStudent.insert(pair<int,string>(2, "student_two"));
    mapStudent.insert(pair<int,string>(3, "student_three"));
    map<int,string>::iterator iter;
    for(iter = mapStudent.begin(); iter != mapStudent.end(); iter++)
       cout<<iter->first<<' '<<iter->second<<endl;
}
#include<bits/stdc++.h>
using namespace std;
int main()
{
    map<int, string> mapStudent;
    mapStudent.insert(map<int, string>::value_type (1, "student_one"));
    mapStudent.insert(map<int, string>::value_type (2, "student_two"));
    mapStudent.insert(map<int, string>::value_type (3, "student_three"));
    map<int, string>::iterator iter;
    for(iter = mapStudent.begin(); iter != mapStudent.end(); iter++)
       cout<<iter->first<<' '<<iter->second<<endl;
}
  1. 使用数组
#include<bits/stdc++.h>
using namespace std;
int main()
{
    map<int, string> mapStudent;
    mapStudent[1] = "student_one";
    mapStudent[2] = "student_two";
    mapStudent[3] = "student_three";
    map<int, string>::iterator iter;
    for(iter = mapStudent.begin(); iter != mapStudent.end(); iter++)
        cout<<iter->first<<' '<<iter->second<<endl;
}
查找数据
  1. 使用count()函数
    其缺点是无法定位数据出现位置,返回值0或1
  2. 使用find()函数
    返回数据所在位置的迭代器
#include<bits/stdc++.h>
using namespace std;
int main()
{
    map<int, string> mapStudent;
    mapStudent.insert(pair<int, string>(1, "student_one"));
    mapStudent.insert(pair<int, string>(2, "student_two"));
    mapStudent.insert(pair<int, string>(3, "student_three"));
    map<int, string>::iterator iter;
    iter = mapStudent.find(1);
    if(iter != mapStudent.end())
       cout<<"Find, the value is "<<iter->second<<endl;
    else
       cout<<"Do not Find"<<endl;
}
重载运算符

map默认是 < 排序,如果是复杂数据类型,一定一定得重载运算符

struct T1
{
    int v;
    bool operator<(const T1 &a)const{
        return (v < a.v);
    }
};
struct T2
{
    int v;
};
struct cmp
{
    const bool operator()(const T2 &a, const T2 &b)
    {
        return (a.v < b.v);
    }
};
int main(){
    multimap<string, int> mm1;
    multimap<string, int>::iterator mm1i, p1, p2;
    mm1.insert(make_pair("b", 3));
    mm1.insert(make_pair("a", 0));
    mm1.insert(make_pair("b", 5));
    mm1.insert(make_pair("c", 4));
    mm1.insert(make_pair("b", 2));
    cout << mm1.size() << endl;
    for(mm1i = mm1.begin(); mm1i != mm1.end(); mm1i++){
        cout << mm1i->first << ": " << mm1i->second << endl;
    }
	cout << "COUNT: " << mm1.count("b") << endl;
    cout << "Bound: " << endl;
    p1 = mm1.lower_bound("b");
    p2 = mm1.upper_bound("b");
    for(mm1i = p1; mm1i != p2; mm1i++){
        cout << mm1i->first << ": " << mm1i->second << endl;
    }
    return 0;
}

set/multiset的使用

这里不做介绍了,和map、vector大相径庭

pair模板

pair实例化出来的类都有两个成员变量,一个是 first, 一个是 second。

make_pair<T1,T2> 函数模板是一个辅助函数,可以生成并返回一个pair<T1,T2> 对象。

make_pair源码如下:

template <class T1, class T2>
pair<T1, T2 > make_pair(T1 x, T2 y)
{
  return ( pair<T1, T2> (x, y) );
}

简单应用如下:

#include <iostream>
#include <map>
using namespace std;
ostream & operator <<( ostream & o,const pair<  int,double> & p)
{
	o << "(" << p.first  << "," << p.second << ")";
	return o;
}
int main()  {
	typedef map<int,double,less<int> > mmid;
	mmid pairs;
	cout << "1) " << pairs.count(15) << endl;
	pairs.insert(mmid::value_type(15,2.7));
	pairs.insert(make_pair(15,99.3)); //make_pair生成一个pair对象
	cout << "2) " << pairs.count(15) << endl;
	pairs.insert(mmid::value_type(20,9.3));
	mmid::iterator i;
	cout << "3) ";
	for( i = pairs.begin(); i != pairs.end();i ++ )
		cout << * i  << ",";
	cout << endl;
	cout << "4) ";
	int n =  pairs[40];//如果没有关键字为40的元素,则插入一个
	for( i = pairs.begin(); i != pairs.end();i ++ )
		cout << * i  << ",";
	cout << endl;
	cout << "5) ";
	pairs[15] = 6.28; //把关键字为15的元素值改成6.28
	for( i = pairs.begin(); i != pairs.end();i ++ )
		cout << * i  << ",";
}

算法

copy()复制
copy_backward()逆向复制
find()搜寻
find_if()在特定条件下搜寻
find_end()搜寻某子序列最近一次出现的位置
find_first_of()搜寻某些元素首次出现位置
max()最大值
max_element()最大值所在位置
min()最小值
min_element()最小值所在位置
replace()取代某种元素
replace_copy()取代某种元素,并将结果复制到另一容器
replace_if()有条件取代
replace_copy_if()有条件取代,并将结果复制到另一容器
count()
size_t count(InIt first, InIt last, const T& val); 
计算[first,last) 中等于val的元素个数

count_if()
size_t count_if(InIt first, InIt last, Pred pr); 
计算[first,last) 中符合pr(e) == true 的元素 e的个数

min_element()
template<class FwdIt> 
FwdIt min_element(FwdIt first, FwdIt last); 
返回[first,last) 中最小元素的迭代器,以 “< ”作比较器

max_element()
template<class FwdIt> 
FwdIt max_element(FwdIt first, FwdIt last); 
返回[first,last) 中最大(不小)元素的迭代器,以 “< ”作比较器

for_each()
template<class InIt, class Fun> 
Fun for_each(InIt first, InIt last, Fun f); 
对[first,last)中的每个元素 e ,执行 f(e) , 要求 f(e)不能改变e

upper_bound()
template<class FwdIt, class T>
 FwdIt upper_bound(FwdIt first, FwdIt last, const T& val); 
要求[first,last)是有序的,查找大于val的最小位置

sort()
template<class RanIt, class Pred>
void sort(RanIt first, RanIt last, Pred pr);
按升序排序。判断x是否应比y靠前,就看 pr(x,y) 是否为true

reverse()
template<class BidIt> 
void reverse(BidIt first, BidIt last);
颠倒区间[first,last)顺序

find()函数:

#include <vector>
#include <algorithm>
#include <iostream>
using namespace std;
int main()
{
    int num_to_find = 6;
    vector<int> v1;
    for( int i = 0; i < 10; i++ )
        v1.push_back(2*i);
    vector<int>::iterator it;
    it = find( v1.begin(), v1.end(), num_to_find );
    if( it == v1.end() )
        cout << "未找到任何元素匹配 " << num_to_find << endl;
    else
        cout << "匹配元素的索引值是 " << it-v1.begin() << endl;
}

search()函数:

#include <vector>
#include <algorithm>
#include <iostream>
using namespace std;
int main()
{
    vector<int> v1;
    cout<<"v1:";
    for(int i=0;i<5;i++)
    {
        v1.push_back(i+5);
        cout<<v1[i]<<' ';
    }
    cout<<endl;
    vector<int> v2;
    cout<<"v2:";
    for(int i=0;i<2;i++)
    {
        v2.push_back(i+7);
        cout<<v2[i]<<' ';
    }
    cout<<endl;
    vector<int>::iterator ilocation;
    ilocation=search(v1.begin(),v1.end(),v2.begin(),v2.end());
    if(ilocation!=v1.end())
        cout<<"v2的元素包含在v1中,起始元素为"<<"v1["<<ilocation-v1.begin()<<']'<<endl;
    else
        cout<<"v2的元素不包含在v1中"<<endl;
}

find_if()函数:
模糊查询中会用到,因此在此做下说明
源码如下:

template<class InputIterator, class Predicate>  
InputIterator find_if ( InputIterator first, InputIterator last, Predicate pred )  
{  
	for ( ; first!=last ; first++ ) if ( pred(*first) ) break;  
	return first;  
}  

它在区间[first,end)中搜寻使一元判断式pred为true的第一个元素。如果没找到,返回end。

npos的用法:
npos可以表示string的结束位子,是string::type_size 类型的,也就是find()返回的类型。find函数在找不到指定值得情况下会返回string::npos。

int pos=name.find("Anna");  
if(pos==string::npos)       
cout<<"Anna not found!\n";  
else  cout<<"Anna found at pos:"<<pos<<endl;  
#include <iostream>  
#include <string>  
using namespace std;  
int main()  
{  
    string b;  
    getline(cin,b);  
    int count=0;  
    for(int i=0;i<=127;i++)  
        if(b.find(i)!=string::npos)  
        count++;  
    cout<<count;  
} 

因为 string::size_type (由字符串配置器 allocator 定义) 描述的是 size,故需为无符号整数型别。因为缺省配置器以型别 size_t 作为 size_type,于是 -1 被转换为无符号整数型别,npos 也就成了该型别的最大无符号值。不过实际数值还是取决于型别 size_type 的实际定义。

学习感受

STL的应用在上面的内容中介绍的差不多了,下面简单谈谈学习STL以来的感受!

STL的设计思想是泛型的程序设计,泛型之前在数据结构接受过,直白的讲,就是模板,可供任何类型使用。

学习STL主要就是为了敲代码方便的,所以在大部分的自定义数据类型肯定会用到STL,因此,一定一定一定重载运算符,仿佛就变成了一种流程。

STL的容器感觉就是一种套路,但是遇到真正的实例,却又会感觉无从下手,就拿这次的图书管理系统来说,第一次交作业的时候,用的STL的知识并不是太多,因为有些东西就没想到去用STL。所以,以后选择存放数据的容器的时候,必须考虑STL,在STL当中,首先考虑vector,它毕竟还是比较好使的;关联式容器使用map。

对于STL的迭代器,本来以为就是指针,后来才发现大有不同,循环遍历的套路又多了一种,对迭代器的理解以及失效的情况上文中也已经详细的写到过,在这就不一一列举了。

STL的算法很多,想要记得那么一清二楚实属不易,但是重要的必须得记住。几个简单的例子,写个排序的代码以前得写好多行,如果使用了sort()函数,一行代码就可以解决。

在这段学习STL的过程中,有收获,当然也有迷茫,感觉学的还是太少,知道的太少,这也许就是学习的动力了吧!

另附图书管理系统代码:

#include<bits/stdc++.h>
using namespace std;
class Base
{
private:
    static int borrowNumMax;
    static int borrowTime;
    static int borrowAgainMax;
public:
    static void setBorrowNumMax(int input)
    {
        borrowNumMax=input;
    }
    static void setBorrowTime(int input)
    {
        borrowTime=input;
    }
    static void setBorrowAgainMax(int input)
    {
        borrowAgainMax=input;
    }
    static int getBorrowNumMax()
    {
        return borrowNumMax;
    }
    static int getBorrowTime()
    {
        return borrowTime;
    }
    static int getBorrowAgainMax()
    {
        return borrowAgainMax;
    }
    static void display()
    {
        cout<<borrowNumMax<<" "<<borrowTime<<" "<<endl;
    }
};
int Base::borrowAgainMax=1;
int Base::borrowTime=30;
int Base::borrowNumMax=10;
/*int main()
{
    int num;
    cin>>num;
    Base::setBorrowNumMax(num);
    int date;
    cin>>date;
    Base::setBorrowTime(date);
    Base::display();
    Base base;
    cout<<base.getBorrowAgainMax()<<" "<<base.getBorrowNumMax()<<" "<<base.getBorrowTime();
}*/
class Date
{
private:
    int year;
    int month;
    int day;
    int m[12]={31,28,31,30,31,30,31,31,30,31,30,31};
public:
    Date(){}
    Date(int year,int month,int day);
    void setYear(int a)
    {
        year=a;
    }
    void setMonth(int a)
    {
        month=a;
    }
    void setDay(int a)
    {
        day=a;
    }
    int getYear()
    {
        return year;
    }
    int getMonth()
    {
        return month;
    }
    int getDay()
    {
        return day;
    }
    bool isYear(int year);
    bool operator<(const Date &d)const
    {
        return year!=d.year?year<d.year:month!=d.month?month<d.month:day<d.day;
    }
    friend ostream & operator <<(ostream &ost,Date &obj);
    friend istream & operator >>(istream &ist,Date &obj);
    Date operator +(int x);
};
Date::Date(int year,int month,int day)
{
    this->year=year;
    this->month=month;
    this->day=day;
}
bool Date::isYear(int yaer)
{
    if(year%4==0&& year%100!=0 || year%400==0)
        return true;
    else
        return false;
}
istream &operator >>(istream &ist,Date &obj)
{
    while(1)
    {
        ist>>obj.year>>obj.month>>obj.day;
        if(obj.getYear()>=2020&&obj.getMonth()<=12&&obj.getMonth()>0&&obj.getDay()<=obj.m[obj.getMonth()-1]&&obj.getDay()>0)
           break;
    }
    return ist;
}
ostream &operator <<(ostream &ost,Date &obj)
{
    ost<<obj.getYear()<<"/"<<obj.getMonth()<<"/"<<obj.getDay()<<endl;
    return ost;
}
Date Date:: operator +(int x)
{
    int i,day1;
    int month1=0;
    if(isYear(year))
    {
        m[1]=29;
    }
    else
        m[1]=28;
    day1=day+x;
    if(day1>m[month-1])
    {
        i=month-1;
        while(day1>m[i])
        {
            day1-=m[i];
            month1++;
            ++i%=12;
        }
        month+=month1;
        if(month>12)
        {
            year++;
            month%=12;
            if(month==0)
                month++;
        }
    }
    day=day1;
    return *this;
}
/*int main()
{
    Base base;
    Date obj;
    cin>>obj;
    obj=obj+base.getBorrowTime();
    cout<<obj;
}*/

class Book
{
private:
    const string bookID;
    string bookName;
    string writer;
    string press;
    string type;
    int total;
    int num;
public:
    Book()
    {
        total=0;
        num=0;
    }
    Book(string n,string bookName1,string writer1,string press1,string type1):bookID(n),bookName(bookName1),writer(writer1),press(press1),type(type1)
    {
        total=0;
        num=0;
    }
    string getBookID()
    {
        return bookID;
    }
    string getBookName()
    {
        return bookName;
    }
    string getWriter()
    {
        return writer;
    }
    string getPress()
    {
        return press;
    }
    string getType()
    {
        return type;
    }
    void setBookName(string str)
    {
        bookName=str;
    }
    void setWriter(string str)
    {
        writer=str;
    }
    void setPress(string str)
    {
        press=str;
    }
    void setType(string str)
    {
        type=str;
    }
    void setTotal(int n)
    {
        total=n;
    }
    void setNum(int n)
    {
        num=n;
    }
    int getTotal()
    {
        return total;
    }
    int getNum()
    {
        return num;
    }
    void display()
    {
        cout<<bookID<<" "<<bookName<<" "<<writer<<" "<<press<<" "<<type<<" "<<total<<" "<<num<<endl;
    }
    friend ostream & operator <<(ostream &ost,Book &obj);
    friend istream & operator >>(istream &ist,Book &obj);
    Book & operator =(const Book &book)
	{
	    string *temp1=const_cast<string*>(&bookID);
        *temp1=book.bookID;
        bookName=book.bookName;
        writer=book.writer;
        press=book.press;
        type=book.type;
        total=book.total;
        num=book.num;
        return *this;
	}
};

istream & operator >>(istream &ist,Book &obj)
{
    //int m;
    //ist>>m;
    string* temp=const_cast<string*>(&obj.bookID);
    string input;
    ist>>input;
    *temp=input;
    ist>>obj.bookName>>obj.writer>>obj.press>>obj.type;
    return ist;
}
ostream &operator <<(ostream &ost,Book &obj)
{
    ost<<obj.bookID<<" "<<obj.bookName<<" "<<obj.writer<<" "<<obj.press<<" "<<obj.type<<" "<<obj.total<<" "<<obj.num<<endl;;
    return ost;
}
/*int main()
{

    Book book1("845612322","《计算机组成原理》","唐朔飞","高等教育出版社","专业");
    cout<<book1;
}*/

class Reader
{
private:
	const string id;
	string name;
	string major;
	string ban;
	int borrowNum;
	vector<Date>d1;
	vector<Date>d2;
	vector<Book>b1;
	vector<int>borrowAgain;
public:
	Reader()
	{
		borrowNum = 0;
	}
	Reader(string no, string name1, string major1, string ban1) :id(no), name(name1), major(major1), ban(ban1)
	{
		borrowNum = 0;
	}
	string getId()
	{
		return id;
	}
	string getName()
	{
		return name;
	}
	string getMajor()
	{
		return major;
	}
	string getBan()
	{
		return ban;
	}
	int getBorrowNum()
	{
		return borrowNum;
	}
	void setName(string str)
	{
		name = str;
	}
	void setMajor(string str)
	{
		major = str;
	}
	void setBan(string str)
	{
		ban = str;
	}
	/*void display()
	{
		cout << id << " " << name << " " << major << " " << ban << " " << borrowNum << endl;
	}*/
	friend istream& operator>>(istream& is, Reader& r);
	friend ostream& operator<<(ostream& os, Reader& r);
	Reader& operator =(const Reader& reader)
	{
		string* temp = const_cast<string*>(&id);
		*temp = reader.id;
		name = reader.name;
		major = reader.major;
		ban = reader.ban;
		borrowNum = reader.borrowNum;
		return *this;
	}
	void borrowBook(Book &bb,Date &dd);
    void backBook(string str,Date &dd);
    void borrow2(string str,Date &dd);
    void overDue(string str,Date &dd);
};
istream& operator>>(istream& in, Reader& reader)
{
	string* temp = const_cast<string*>(&reader.id);
	string input;
	in >> input;
	*temp = input;
	in >> reader.name >> reader.major >> reader.ban;
	return in;
}
ostream& operator<<(ostream& out, Reader& reader)
{
	out << reader.id << " " << reader.name << " " << reader.major << " " << reader.ban << " " << reader.borrowNum << endl;
	return out;
}

void Reader::borrowBook(Book &bb,Date &dd)
{
    borrowNum++;
    d1.push_back(dd);
    b1.push_back(bb);
    Base ba;
    Date dd2=dd+ba.getBorrowTime();
    d2.push_back(dd2);
    int again=0;
    borrowAgain.push_back(again);
}
void Reader::backBook(string str,Date &dd)
{
    vector<Book>::iterator it;
    int i=0;
    for(it=b1.begin();it!=b1.end();it++)
    {
        if(b1[i].getBookID()==str)
        {
            b1.erase(it);
            borrowNum--;
            d1.erase(d1.begin()+i);
            d2.erase(d2.begin()+i);
        }
        i++;
    }
}
void Reader::borrow2(string str,Date &dd)
{
    int i=0;
    vector<Book>::iterator it;
    for(it=b1.begin();it!=b1.end();it++)
    {
        if(b1[i].getBookID()==str)
        {
            if(borrowAgain[i]==1)
                cout<<"not,ok!"<<endl;
            else
            {
                d1[i]=dd;
                d2[i]=dd+30;
                borrowAgain[i]++;
            }
            break;
        }
        i++;
    }
}
void Reader::overDue(string str,Date &dd)
{
    for(int i=0;i<b1.size();i++)
    {
        if(b1[i].getBookID()==str)
        {
            if(d2[i]<dd)
                cout<<"overdue"<<endl;
            else
                cout<<"ok"<<endl;
        }
    }
}

/*int main()
{
    Reader test1("2018212449","刘大伟","计算机科学与技术",4);
    cout<<test1;
}*/

class Record
{
private:
	Date date1;
	Date date2;
	Date date3;
	string bookID;
	string id;
	string operate;
	string type;
    //Book book;
    //Reader reader;

public:
    Record(){}
    Record(string bookID2,string id2,string operate2);
    void setDate1()
    {
        cin>>date1;
    }
    void setBookId(string str)
    {
        bookID=str;
    }
    void setDate3()
    {
        cin>>date3;
    }
    void setId(string str)
    {
        id=str;
    }
    void setOperate(string str)
    {
        operate=str;
    }
    void setType(string str)
    {
        type=str;
    }
    Date getDate1()
    {
        return date1;
    }
    Date getDate2()
    {
        Base b;
        return date1+b.getBorrowTime();
    }
    Date getDate3()
    {
        return date3;
    }
    string getId()
    {
        return id;
    }
    string getBookID()
    {
        return bookID;
    }
    string getOperate()
    {
        return operate;
    }
    string getType()
    {
        return type;
    }
    void show();
    friend istream & operator>>(istream &ist,Record &obj);
    friend ostream & operator<<(istream &ist,Record &obj);
};
Record::Record(string bookID2,string id2,string operate2)
{
    this->bookID=bookID2;
    this->id=id2;
    this->operate=operate2;
}
istream & operator >>(istream &ist,Record &obj)
{
    ist>>obj.bookID>>obj.id>>obj.operate;
    return ist;
}
void Record::show()
{
    Record re;
    re.setDate1();
    cin>>re;
    if(re.getOperate()=="借")
    {

        Date dd;
        dd=re.getDate2();
        cout<<dd<<endl;
    }
    if(re.getOperate()=="还")
    {
        re.setDate3();
        if(re.getDate3()<re.getDate2())
            cout<<"ok!"<<endl;
    }

}
/*int main()
{
    Record rr;
    rr.show();
}*/
class Finder
{
private:
    const std::string& str;
public:
    Finder(const string& cmp_string):str(cmp_string) {}
    bool operator ()(const multimap<string,int>::value_type& pair)
    {
        int loc;
        loc=pair.first.find(str);
        if (loc != pair.first.npos)
            return true;
        return false;
    }
};
class Operation
{
private:
	vector<Book> book;
	vector<Reader> reader;
	multimap<string, int>bookname;
	multimap<string, int>readername;
	multimap<string, int>bookid;
	multimap<string, int>readerid;

public:
	Operation()
	{
		loadBook();
		loadReader();
	}
	~Operation()
	{
		saveBook();
		saveReader();
	}

	void loadBook();
	void loadReader();
	void saveBook();
	void saveReader();
	void addBook();
	void addReader();
	void delReader(string id);
	void delBook(string id);
	void findBookByName(string name);
	void findBookById(string id);
	void findReaderByName(string name);
	void findReaderById(string id);
	void modifyReader(string id);
	void modifyBook(string id);
	void fuzzyFindBname(string str);
};
void Operation::fuzzyFindBname(string str)
{
	multimap<string, int>::iterator it,p1,p2,p;
	p1 = bookname.begin();
	it = find_if(p1, bookname.end(), Finder(str));
	if (it == bookname.end())
		return;
	else
		cout << book[it->second];
	it++;
	for (p = it; p !=bookname.end(); p++)
	{
		it = find_if(p, bookname.end(), Finder(str));
		if (it == bookname.end())
			return;
		else
			cout << book[it->second];
	}
}
void Operation::loadBook()
{
	Book a;

	ifstream in("E:\\book.txt");
	if (!in)
		return;
	while (!in.eof())
	{
		in >> a;
		int temp1, temp2;
		in >> temp1 >> temp2;
		a.setTotal(temp1);
		a.setNum(temp2);
		book.push_back(a);
		bookname.insert(make_pair(a.getBookName(), book.size() - 1));
		bookid.insert(make_pair(a.getBookID(), book.size() - 1));
	}
	in.close();
}

void Operation::loadReader()
{
	Reader a;

	ifstream in("E:\\readers.txt");
	if (!in)
		return;
	while (!in.eof())
	{
		in >> a;
		reader.push_back(a);
		readername.insert(make_pair(a.getName(), reader.size() - 1));
		readerid.insert(make_pair(a.getId(), reader.size() - 1));
	}
	in.close();
}
void Operation::saveBook()
{
	ofstream out("E:\\outbook.txt");
	vector<Book>::iterator it;
	for (it = book.begin(); it != book.end(); it++)
	{
		out << *it;
	}
	out.close();
}
void Operation::saveReader()
{
	ofstream out("E:\\outreader.txt");
	vector<Reader>::iterator it;
	for (it = reader.begin(); it != reader.end(); it++)
	{
		out << *it;
	}
	out.close();
}
void Operation::addBook()
{
	Book b;
	cin >> b;
	multimap<string, int>::iterator it;
	it = bookid.find(b.getBookID());
	if (it == bookid.end())
	{
		b.setTotal(b.getTotal() + 1);
		b.setNum(b.getNum() + 1);
		book.push_back(b);
		bookname.insert(make_pair(b.getBookName(), book.size() - 1));
		bookid.insert(make_pair(b.getBookID(), book.size() - 1));
	}
	else
	{
		b.setTotal(book[it->second].getTotal() + 1);
		b.setNum(book[it->second].getNum() + 1);
		book[it->second] = b;
	}

}
void Operation::addReader()
{
	Reader r;
	cin >> r;
	reader.push_back(r);
	readername.insert(make_pair(r.getName(), reader.size() - 1));
	readerid.insert(make_pair(r.getId(), reader.size() - 1));
}
void Operation::delBook(string id)
{
	multimap<string, int>::iterator it;
	vector<Book>::iterator p = book.begin();
	it = bookid.find(id);

	if (it != bookid.end())
	{
		int index = it->second;
		//*p = book.at(index);
		book.erase(p + index);
	}
	else
		return;
}
void Operation::delReader(string id)
{
	multimap<string, int>::iterator it;
	vector<Reader>::iterator p = reader.begin();
	it = readerid.find(id);
	if (it != readerid.end())
	{
		int index = it->second;
		//*p = reader.at(index);
		reader.erase(p + index);
	}
	else
		return;
}

void Operation::findBookByName(string name)
{
	multimap<string, int>::iterator it, p1, p2, p;
	it = bookname.find(name);
	if (it == bookname.end())
		return;
	else {
		p1 = bookname.lower_bound(name);
		p2 = bookname.upper_bound(name);
		for (p = p1; p != p2; p++) {
			cout << book[p->second] << endl;
		}
	}
}

void Operation::findBookById(string id)
{
	multimap<string, int>::iterator it;
	it = bookid.find(id);
	if (it == bookid.end())
		return;
	else
		cout << book[it->second];
}

void Operation::findReaderByName(string name)
{
	multimap<string, int>::iterator it, p1, p2, p;

	it = readername.find(name);
	if (it == readername.end())
		return;
	else {
		p1 = readername.lower_bound(name);
		p2 = readername.upper_bound(name);
		for (p = p1; p != p2; p++) {
			cout << reader[p->second] << endl;
		}
	}
}
void Operation::findReaderById(string id)
{
	multimap<string, int>::iterator it;
	it = readerid.find(id);
	if (it == readerid.end())
		return;
	else
		cout << reader[it->second];
}

void Operation::modifyBook(string id)
{
	multimap<string, int>::iterator it;
	it = bookid.find(id);
	if (it == bookid.end())
		return;
	else
	{
		cin >> book[it->second];
		cout << book[it->second];
	}

}
void Operation::modifyReader(string id)
{
	multimap<string,int>::iterator it;
	it = readerid.find(id);
	if (it == readerid.end())
		return;
	else
	{
		cin >> reader[it->second];
		cout << reader[it->second];
	}
}

/*int main()
{
	//768456495  《活着》  余华  作家出版社  文学
    //2018212449  刘大伟 计算机科学与技术 4
    //846486416  《算法设计与分析》    左伍衡 清华大学出版社  专业
    //2018212423  张帆  计算机科学与技术  5
    Operation op;
    op.addBook();
    op.addReader();
    op.findBookById("846486416");
    op.findBookByName("《计算机组成原理》");
    op.findReaderByName("刘大伟");
    op.findReaderById("2018212449");
    op.modifyBook("846486416");
    op.modifyReader("2018212423");
    op.delBook("756542155");
    op.delReader("2018212449");
}*/
class Message
{
	Book book;
	Date btime,backtime;
	Reader read;
	string type;
	int num,rest;
	public:
	Message()
	{
		Book a;
		book=a;
		Date b,c;
		btime = b;
		backtime = c;
		Reader d;
		read = d;
		type="";
		num = 0;
		rest = num;
	}
	Message(Book a,Date b,Date e,Reader f,string c,int g):book(a),btime(b),backtime(e),read(f),type(c)
	{
		rest = num;
	}
	void setbook(Book a)
	{
		book=a;
	}
	void setReader(Reader a)
	{
		read=a;
	}
	void setbtime(Date a)
	{
		btime = a;
	}
	void setbacktime(Date a)
	{
		backtime = a;
	}
	void settype(string a)
	{
		type = a;
	}
	Book getbook()
	{
		return book;
	}
	string getbookName()
	{
		return book.getBookName();
	}
	Date getDate()
	{
		return btime;
	}
	Date getbacktime()
	{
		return backtime;
	}
	Reader getreader()
	{
		return read;
	}
	string gettype()
	{
	    return type;
	}
	string getname()
	{
		return read.getName();
	}
	friend ostream&operator<<(ostream&out,Message&a);
	friend istream&operator>>(istream&in,Message&a);
};
istream&operator>>(istream&in,Message&a)
{
	in>>a.book;
	in>>a.btime;
	//int d;
	//in>>d;
	//a.btime.setDay(d);
	in>>a.backtime;
	//int e;
	//in>>e;
	//a.backtime.setDay(e);
	in>>a.type;
	return in;
}
ostream&operator<<(ostream&out,Message&a)
{
	//out<<a.type<<" "<<a.book<<" "<<a.btime<<" "<<a.btime.getDay()<<" "<<a.backtime<<" "<<a.backtime.getDay();
    out<<a.type<<" "<<a.book<<" "<<a.btime<<" "<<a.backtime;
    return out;
}
/*int main()
{
    Message a;
    cin>>a;
    cout<<a;
}*/
class Manger
{
private:
    int num;
    Reader read;
    vector<Message> mess;
    multimap<string,int>mess_name;
    vector<Book>book;
    vector<Reader>rea;
    multimap<string,int>book_id;

public:
    Manger()
    {
        num=0;
    }
    int getnum()
    {
        return num;
    }
    void setnum(int a)
    {
        num=a;
    }
    string come();
    void generate();
    void out();
};
string Manger::come()
{
    Reader obj;
    cin>>obj;
    rea.push_back(obj);
    mess_name.insert(make_pair(obj.getName(), mess.size() - 1));
	book_id.insert(make_pair(obj.getId(), mess.size() - 1));
	return obj.getId();
}
void Manger::generate()
{
    Base base;
    if(num<base.getBorrowNumMax())
    {
        num++;
        Message a;
        cin>>a;
        mess.push_back(a);
    }
}
void Manger::out()
{
    string temp=come();
    int i=0;
    vector<Reader>::iterator it;
    for(it=rea.begin();it!=rea.end();it++)
    {
        if(rea[i].getId()==temp)
        {
            cout<<rea[i].getId()<<" "<<rea[i].getName()<<" "<<mess[i];
            break;
        }
        i++;
    }
}
int main()
{
    Manger ma;
    ma.come();
    ma.generate();
    ma.out();
}
  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

莫余

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值