文章目录
早前学习数据结构的时候,看到别人都能够熟练地使用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++中,就该名成了迭代器,其实不是这样的。
但是在使用迭代器的时候,发现有时会报错,原因是因为迭代器 失效 了。
失效的情况
- 在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);
,具体的上面代码已经给出。
运行结果如下:
- 关联式容器(如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构造函数产生,多余的元素被删除) |
添加元素
- 向向量a中直接添加元素
vector<int> a;
for(int i=0;i<10;i++)
a.push_back(i);
- 从数组中向向量添加元素
int a[6]={1,2,3,4,5,6};
vector<int> b;
for(int i=1;i<=4;i++)
b.push_back(a[i]);
- 从数组中添加元素到向量中
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);
- 从文件中读取元素向向量中添加
ifstream in("data.txt");
vector<int> a;
for(int i; in>>i)
a.push_back(i);
【误区】:不可v[i]=i;
赋值。下标只能用于获取已存在的元素
一定一定注意重载运算符
例如下面就是没有重载运算符导致的报错。
读取元素
- 通过下标
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]<<" ";
- 遍历器方式
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() | 移除所有元素,清空容器 |
插入数据
- 使用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;
}
- 使用数组
#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;
}
查找数据
- 使用count()函数
其缺点是无法定位数据出现位置,返回值0或1 - 使用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();
}