學習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();
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章