文章目錄
早前學習數據結構的時候,看到別人都能夠熟練地使用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();
}