图书馆管理系统用户端心得

最近终于写了一个让自己满意的系统,我在这里分享一下,顺便总结一下自己的学习心得。

1.需求分析
听的好像是要做项目一样,但是无论写什么程序,些什么系统,都是要知道自己要干什么,要完成什么工作,实现那些功能,在这前列出一个表格,或是思维导图,给自己一个方向,先规划好再写,不然会拉下很多东西,在我写这个系统之前,我在图书馆的借书页面,看了将近两个小时,中途又看了好多次,这次代码不能说是一个完美可以当作工程性的使用,其中还有很多测试环节,还有部分功能没有实现,比如二次检索,三次检索功能,数据少得可怜,肯定还有一些未知的错误,所以我在这里真是分享我写代码,及调试代码的方法跟过程。
2.写代码+调试代码
写代码的时候一定要写一个功能调试一个功能,所谓的一个功能不是一个类,而是一个类的一个函数,如果一个函数会影响到其他函数的运行,不调好之前的函数,现在的函数也没法运行,当代码随着项目的增大,代码长度几何增长是,再找错误就很难的了,所以顺着调试下去,以便你写完的代码是可以运行的,是正确的,而具体能否实现功能在另说。
数据类与操作类的分离,面向对象要的是封装性,操作抽象+数据抽象,继承,写代码写完能够复用最好,乱糟糟的写完不能复用的类扔在那里,以后再也不会用到,浪费时间,完全可以写一些代码条理清晰,更重要的是,下次相似的代码不用再继续写,这应该是应该具备的素养。
以下是我调试代码的过程,最后代码还是有一点错误,这里是我的明明还是不好的原因,补充一下我认为明明一定要有意义,可以将学生的每科学分定义为a b c d. …也可以定义为数学 英语 物理 c++…这样可以增加代码的可读性。
引以为戒:
下文中这两个MAP混用导致了一些问题,以至于我交代码的时候是错误的还有没有发现

map<string,int>idtorea;  //读者id对应读者数据下标
map<string ,int> idtoob; //图书id对应图书数据下标

时间类
在这里插入图片描述
时间类第一次调试运行,测试有参无参,重载<< ,>>和+
在这里插入图片描述

写到后边发现,自己重载的+错了,而且还需要计算两个时间类相差的时间,回头从新写的重载+,跟-

图书类
在这里插入图片描述
这里调试很多遍,开始留了一个应还时间Time类,后来发现,没有用。
在这里插入图片描述
后来想到,可能查询归还时间,所以写了get函数,但是函数不能反回局部类对象,只好写成static。
在这里插入图片描述
因为后边的时候需要输出,但是有些数据只有管理员能够看到,所以写完后边的回来写的print函数。
读者类
在这里插入图片描述
这里学生能做的事情不多,修改密码,查询个人信息,别的都做不了。

在这里插入图片描述
在后边实现借书就要在数据类中实现更改,所以在这里加了一条进行测试所添加的操作。
操作数据类
在这里插入图片描述
每一条新数据都必须,拥有参初始化,除了文件读取除外。
在这里插入图片描述
操作类也面临着不能直接输出的尴尬境界,所以回来,再写一个print。
在这里插入图片描述
终于看到自己的程序成功运行,也试了几组错误情况。基本无问题。

#include<bits/stdc++.h.>
using namespace std;
class Time
{
    int  year,month,day;
public:
    Time(){loadtime();}
    Time(int y,int m,int d):year(y),month(m),day(d){};    //用与图书出版日期等已知数据的对象的初始化;
    //不能创建图书对象,有参初始化就没意义。
  //  Time(Time & a){year=a.year,month=a.month,day=a.day;}    //用一个时间类初始化一个时间类,为后续操作准备;
    //这句不注释就没法运行,不得解
    void loadtime();    //定义时间获取函数,学生借书的时间不可更改,直接从系统读入;
    friend istream & operator>>(istream &in,Time & a);  //不设置set函数,时间直接一次性全部修改即可;
    friend stringstream & operator>>(stringstream &in,Time & a);
    friend ostream & operator<<(ostream &out,Time & a);
    bool operator <(const Time &d)const{    //重载小于号,用于数据时间排序,不需要修改数据const;
        return year!=d.year?year<d.year:month!=d.month?month<d.month:day<d.day;
    }
    int judge() const;  //判断是否为闰年,用于续借日期的变化;
    int judge(int year) const ;//写一个有参的判断函数;
    Time operator +(int  a) ;   //重载加号,用于续借日期的变化;
    friend int operator -(Time a,Time b);  //计算两段时间间隔;
};
Time Time::operator +(int  a)
{
    int m[] = {0,31,28,31,30,31,30,31,31,30,31,30,31};
    day+=a;
    int flag=1;
   while(day>m[month]){
        if(month==2){
            if(day>m[month]+judge()){
                day-=m[month]+judge();
                month++;
            }
        }
        else {
            day=day-m[month];
            month++;
        }//因为一对大括号跑了好几遍,敲ACM也一样,不要偷懒
        if(month>12){
        month-=12;
        year++;
    }
   }
}
int operator -(Time a,Time b)
{
    int monthdays[2][12] = { { 31,28,31,30,31,30,31,31,30,31,30,31 },{ 31,29,31,30,31,30,31,31,30,31,30,31 } };
    int yeardays[2] = { 365,366 };
    int sumdays=0;
   if (a.year == b.year&& a.month == b.month){
        sumdays = b.day - a.day;
    }
    else
        if (a.year == b.year){
            sumdays += monthdays[a.judge(a.year)][a.month-1] - a.day;
            for (int i = a.month; i < b.month-1; i++)
                sumdays += monthdays[a.judge(a.year)][i];
            sumdays += b.day;
        }
        else{
            sumdays += monthdays[a.judge(a.year)][a.month-1] - a.day;
            for (int i = a.month; i < 12; i++)
                sumdays += monthdays[a.judge(a.year)][i];
            for (int i = a.year + 1; i < b.year; i++)
                sumdays += yeardays[a.judge(i)];
            for (int i = 0; i < b.month - 1; i++)
                sumdays += monthdays[a.judge(b.year)][i];
            sumdays += b.day;
        }
    return sumdays;
}
int Time::judge() const{
        if(year % 4 == 0 && year %100 != 0 ||year % 400 == 0) return 1;
        else return 0;
}
int Time::judge(int year) const{
    if (year % 4 == 0 && year % 100 != 0 || year % 400 == 0)return 1;
    else  return 0;
}
void Time::loadtime(){
    time_t rawtime;
    struct tm *ptminfo;
    time(&rawtime);
    ptminfo = localtime(&rawtime);
    year=ptminfo->tm_year + 1900;
    month=ptminfo->tm_mon + 1;
    day=ptminfo->tm_mday;
}
istream & operator>>(istream &in,Time & a){
    in>>a.year>>a.month>>a.day;
    return in;
}
ostream & operator<<(ostream &out,Time & a)
{
    out<<a.year<<" "<<a.month<<" "<<a.day<<" ";
    return out;
}
stringstream & operator>>(stringstream &in,Time & a){
    in>>a.year>>a.month>>a.day;
    return in;
}
/*
int main()
{
    Time  demo1;//无参初始化对象
    cout<<demo1<<endl;
    Time demo2(demo1);//有参初始化对象,便于不同时间定义对象,时间不同;
    cout<<demo2<<endl;
    demo2+60;//为续借,即还书时间做准备;
    cout<<demo2;
    Time demo3(2000,03,19);
    cout<<demo3<<endl;
}
*/
/*
int main()
{
    Time demo1,demo2;
    cin>>demo1>>demo2;
    int d=demo1-demo2;
    demo1+d;
    cout<<demo1<<endl;
    cout<<d<<endl;
}*/
class Book
{
    string name;
    string  press;                                                             //出版社
    string pubtime;                                                     //出版时间通常在图书馆只有年份
    string author;                                                      //作者
    string suoshu;                                                     //索书号
    string id;          //每本书都有唯一的条形码,两本完全一样的书,在这里应该看作两本书
    string locate;
    string jsr;            //指向借书人数据在的位置的下标(-1),代表可借
    int fk;       //每本书都有自己的罚款,不会影响其他书籍,定义在这里比定义在读者类要合适
    bool xj;   //比起写入记录中查询,写在图书中,无论是还书,还是续借,都更加便捷
    Time jy;
 //   Time rebac;
public:
    Book():name(""),press(""),author(""),id(""),suoshu(""),locate(""),jsr("-1"),fk(0){}
    //学生端不能创建书籍对象,只写一个无参初始化,用于读取文件数据;
    string getname ()const{return name;}
    string getpress ()const{return press;}
    string getauthor ( )const{return author;}
    string getpubtime ( )const{return pubtime;}
    string getid ( )const{return id;}
    string getsuoshu ( )const{return suoshu;} //通过上述get函数为下面的查询做准备;
    int getfk(){jsfk();return fk;}
    void xxj(){
        /*if(fk<=0)xj=!xj;
        else cout<<"请先缴清罚款"<<endl;*/ //改为在读者类判断,不只是一本书的罚款,会影响借书;
        xj=!xj;
    }
    bool getxj(){  return xj;}
    void js(string idcard){jsr=idcard;}             //学号跟图书的条形码是唯一的,由此来对应;
    Time& getreback();
    void jsfk();
    void print();
    friend istream & operator>>(istream &in,Book & a);
    friend ostream & operator<<(ostream &out,Book & a);
};
void Book::jsfk()
{
    int brr;
    if(xj) brr=120;
    else brr=60;
    Time tem;
    fk=tem-jy-brr;
    if(fk<0) fk=0;
}
void Book::print()
{
    cout<<name<<" "<<press<<" "<<author<<" "<<id<<" "<<suoshu<<" "<<locate<<" ";
    if(jsr!="-1") cout<<"已借出  归还时间:"<<getreback()<<endl;
    else cout<<endl;
}
Time& Book::getreback(){
   static Time tem(jy);
    tem+60*(1+getxj());
    return tem;
}
istream & operator>>(istream &in,Book & a){
    in>>a.name>>a.press>>a.pubtime>>a.author>>a.suoshu>>a.id>>a.jsr>>a.locate>>a.jy>>a.xj;
    return in;
}
ostream & operator<<(ostream &out,Book & a){
    out<<a.name<<" "<<a.press<<" "<<a.pubtime<<" "<<a.author<<" "<<a.suoshu<<" "<<a.id<<" "<<a.jsr<<"  "<<a.locate<<" "<<a.jy<<" "<<a.xj;
    return out;
}
//记 北京机械工业出版社 2016 胡凡 TP301.6/H569 01664298  123456 -1 采编部在编 2018 5 16  1
/*
int main()
{
        Book demo;
        cin>>demo;
        cout<<demo;
        cout<<demo.getname()<<endl;
        cout<<demo.getpress()<<endl;
        cout<<demo.getauthor()<<endl;
        cout<<demo.getsuoshu()<<endl;
        cout<<demo.getpubtime()<<endl;
        cout<<demo.getfk()<<endl;
       int jsr;
        cin>>jsr;
        demo.js(jsr);
        cout<<demo.getxj()<<endl;
        demo.xxj();
        cout<<demo.getxj()<<endl;
        cout<<demo<<endl;
} //算法笔记 北京机械工业出版社 2016 胡凡 TP301.6/H569 01664298  123 采编部在编 2018 5 16  1
*/
/*
int main()
{
    Book demo;
    cin>>demo;
    cout<<demo.getreback();
}*/
/*
int main()
{
        Book  demo1;//无参初始化对象
       cin>>demo1;
        demo1.print();
}
*/
class Student
{
    string name;
    string id;
    string key;
    string mail;
    vector<string> jy;/*按时间先后借的书,则为有序,int是图书数据的ID;
                                                通过下标联通了图书与读者。*/
    int yj;//已借图书
public:
    Student() :name(""),id(""),key(""),mail(""){jy.clear();}
    //void printxx() 想写打印信息的功能,但是目前这个类看不到图书数据,无法关联。转而写get函数;
    vector<string> getjy() const{return jy;}         //先返回一个vector对象,目前看不到图书数据,所以返回后,在操作类中使用
    string getname(){return name;}
    string getid(){return id;}
    string getkey(){return key;}
    string getmail(){return mail;}
    int getyj()const {return yj;}
    void setkey(string tem) ;           //修改密码
    void  jieyue(string obid);     //借阅图书,图书馆的借阅最后都是按照书的唯一的条码来借阅
    void reback(string obid);      //归还同上。
                                                                /*现在看不到图书数据,只能写出部分借阅,归还操作,在操作类中应判断是否具有罚款,
                                                                此函数仅用于修改学生,作为子函数使用*/
    friend istream & operator>>(istream &in,Student & a);
    friend ostream & operator<<(ostream &out,Student & a);
} ;
istream & operator>>(istream &in,Student & a)
{
    in>>a.name>>a.id>>a.key>>a.mail>>a.yj;
    string tem;
    for(int i=0;i<a.yj;i++) {
            in>>tem;
            a.jy.push_back(tem);
    }
    return in;
}
ostream & operator<<(ostream &out,Student & a)
{
    out<<a.name<<" "<<a.id<<" "<<a.key<<" "<<a.mail<<" "<<a.yj<<" ";
    for(int i=0;i<a.yj;i++) cout<<a.jy[i]<<" ";
    return out;
}
void Student::jieyue(string obid)
{
    if(yj>=10) cout<<"借阅数量已达上限"<<endl;
    else jy.push_back(obid);
    yj=jy.size();
}
void Student::reback(string obid)    //归还操作很宽泛,甚至都不需要登陆账号,但是根据图书找到人,最后还是要根据id在这人身上去掉
{
    //不需要容错,如果系统不崩溃,从书籍查借人一定是唯一的
    auto po=find(jy.begin(),jy.end(),obid);
    if(po==jy.end()) cout<<"还书失败,请联系管理员"<<endl;
    else jy.erase(po);
    yj=jy.size();
}
void Student::setkey(string tem)
{
    while(tem!=key)
    {
        cout<<"密码错误,请重试"<<endl;
        cin>>tem;
    }
    cin>>tem;
    key=tem;
}
/*
int main()
{
    Student demo;
    cin>>demo;
    cout<<demo.getname()<<endl;
    cout<<demo.getid()<<endl;
    cout<<demo.getkey()<<endl;
    cout<<demo.getmail()<<endl;
    cout<<demo.getyj()<<endl;
    cout<<demo;
}*/
//张俊浩  2018212513 123456 529934209@qq.com  1  203
/*
int main()
{
    string tem;
    Student demo;
    cin>>demo>>tem;
    demo.jieyue(tem);
    cout<<demo<<endl;
    cin>>tem;
    demo.reback(tem);
    cout<<demo;
}
*/

class Operate //记录只能生成不能修改
{
    Time time;
    string oper; //操作
    string peo; //操作人id
    string boo; //图书对象ID
    int fk;    //当操作为还书时有真实罚款,其余为-1
public:
    Operate( ):oper(""),peo(""),boo(""),fk(-1){}   //仅用于文件读写
    Operate(string o,string p,string b,int c):oper(o),peo(p),boo(b),fk(c){time.loadtime();}  //操作无论管理员,学生都无法改变时间;
    string getname(){return peo;}
    string getbook(){return boo;}
    string getoper(){return oper;}
    int getfk(){return fk;}          // 用于后续查询操作
    void print() ;
    friend istream & operator>>(istream &in,Operate & a);
    friend ostream & operator<<(ostream &out,Operate & a);
} ;
void Operate::print()
{
    cout<<time<<" "<<peo<<" "<<oper<<" "<<boo<<" ";
    if(fk!=-1) cout<<"缴纳罚款:"<<fk<<endl;
}
istream & operator>>(istream &in,Operate  & a)
{
    in>>a.time>>a.peo>>a.oper>>a.boo>>a.fk;
    return in;
}
ostream & operator<<(ostream &out,Operate  & a)
{
    out<<a.time<<" "<<a.peo<<" "<<a.oper<<" "<<a.boo<<" "<<a.fk<<" ";
    return out;
}
/*
int main()
{
    Operate demo;
    cin>>demo;
    cout<<demo.getname()<<" "<<demo.getoper()<<" "<<demo.getbook()<<" "<<demo.getfk()<<endl;
    cout<<demo<<endl;
    string name,op,ob;
    int fk;
    cin>>name>>op>>ob>>fk;
    Operate demo2(name,op,ob,fk);
    cout<<demo2<<endl;
}
*/
/*
int main()
{
    Operate demo;
    cin>>demo;
    demo.print();
}*/
class  Library
{
    string account;
    string password;      //每次登入图书馆进行操作都要有账号密码
    vector<Book>  book;
    vector<Student> reader;
    vector<Operate> record;   //三个基础数据;
    //图书查询操作所需数据
   multimap<string,int> pubtimque;   //出版时间
   multimap<string,int> suoshuque;   // 索书号
   multimap<string,int> pressque;   //出版社
   //书名与作者都需要模糊查询
   //数据查询
    map<string,int>idtorea;  //读者id对应读者数据下标
    map<string ,int> idtoob; //图书id对应图书数据下标
    multimap<string,int> ridtorec; //读者Id对应操作数据下标
    multimap<string,int> bidtorec; //图书 id对应操作数据下标
public:
    Library(string ac,string pass): account(ac),password(pass){load();login();cout<<book.size();}
    void login();
    //书籍查询操作
    void querysm(string name) ;//书名查询
    void queryss(string suoshu) ; //索书号查询
    void queryath(string ath); //作者查询
    void querypres(string pre); //出版社查询
    void querytim(string pub);//出版时间查询
    //个人信息操作
    void quepers();  //查询读者身份信息
    void quebrro();//查询借阅信息
    void queop(); //查询读者操作记录(仅个人)
    //基础操作
    int cxkj(); //查询课可借书的数量
    void jieshu(string id) ;
    void huanshu(string id);
    void xujie(string id);   //图书馆虽然不用输入书的条码,但是现在也是通过书的磁获取
                                            //也应该看是输入,比如某些地方仍用扫码,甚至手输
    void load();
    void save();
    ~Library(){save();}
};
//有些map是给管理端用的,这里只写不读;
void Library::login()
{
        while(1){
            auto po=idtorea.find(account);
            if(po!=idtorea.end()&&reader[po->second].getkey()==password) break;
            cout<<"账号密码不匹配\n请重新输入\n";    //可以在分个账号不存在,但看很多网站,
                                                                                                //都不会报不存在,为了提高一点安全性;
            cin>>account>>password;
        }
        cout<<"登陆成功\n";
}
void Library:: querysm(string name)
{
    for(auto po=book.begin();po!=book.end();po++)
    {
       auto m=po->getname().find(name);
        if(m!=-1) po->print();
    }
}
void Library::  queryss(string suoshu)
{
    auto beg=suoshuque.lower_bound(suoshu);
    auto en=suoshuque.upper_bound(suoshu);
    for(auto po=beg;po!=en;po++)book[po->second].print();
}
void Library::  queryath(string ath){
    for(auto po=book.begin();po!=book.end();po++)
    {
        auto m=po->getauthor().find(ath);
        if(m!=-1) po->print();
    }
}
void Library::  querypres(string pre)
{
    auto beg=pressque.lower_bound(pre);
    auto en=pressque.upper_bound(pre);
    for(auto po=beg;po!=en;po++)  book[po->second].print();
}
void Library::  querytim(string pub)
{
    auto beg=pubtimque.lower_bound(pub);
    auto en=pubtimque.upper_bound(pub);
    for(auto po=beg;po!=en;po++)book[po->second].print();
}
void Library::  quepers(){
    cout<<reader[idtoob[account]].getname()<<" ";
    cout<<reader[idtoob[account]].getid()<<" ";
    cout<<reader[idtoob[account]].getmail()<<" ";
    cout<<reader[idtoob[account]].getyj()<<" ";
    cout<<cxkj()<<endl;
}
void Library::  quebrro()
{
    for(auto po=reader[idtoob[account]].getjy().begin();
        po!=reader[idtoob[account]].getjy().end();po++)
       book[idtoob[ *po]].print();
}
void Library::  queop()
{
        auto beg=ridtorec.lower_bound(account);
        auto en=ridtorec.upper_bound(account);
         for(auto po=beg;po!=en;po++)record[po->second].print();
}
int Library:: cxkj()
{
        int ans=0;
        for(auto po=reader[idtoob[account]].getjy().begin();
        po!=reader[idtoob[account]].getjy().end();po++)
        ans+=book[idtoob[ *po]].getfk();
        if(ans>0) return -1;
        else return 10-reader[idtoob[account]].getjy().size();
}
void Library:: jieshu(string id)
{
    if(cxkj()==-1){  cout<<"归还逾期,请先归还\n"; return ;}
    else if(cxkj()==0) {  cout<<"达到借书上限\n"; return ;}
    reader[idtorea[account]].jieyue(id);
    book[idtoob[id]].js(account);
    Operate tem("借书",account,id,-1);
    record.push_back(tem);
    ridtorec.insert(make_pair(account,record.size()-1));
    bidtorec.insert(make_pair(id,record.size()-1));
}
void Library:: huanshu(string id)
{
     reader[idtorea[account]].reback(id);//异常在 reback抛出
    book[idtoob[id]].js("-1");
    int money=book[idtoob[id]].getfk();
    Operate www("还书",account,id,money);
    record.push_back(www);
    ridtorec.insert(make_pair(account,record.size()-1));
    bidtorec.insert(make_pair(id,record.size()-1));
}
void Library:: xujie(string id)
{
    if(cxkj()==-1){  cout<<"归还逾期,请先归还\n"; return ;}
    else if(cxkj()==0) {  cout<<"达到借书上限\n"; return ;}
    book[idtoob[id]].xxj();
    Operate tem("续借",account,id,-1);
    record.push_back(tem);
    ridtorec.insert(make_pair(account,record.size()-1));
    bidtorec.insert(make_pair(id,record.size()-1));
}
void Library::save()
{
    ofstream out1("d:\\book.txt",ios::out);
    for(auto po=book.begin(); po!=book.end(); po++)
        out1<<*po<<endl;
    out1.close();
    ofstream out2("d:\\reader.txt",ios::out);
    for(auto po=reader.begin(); po!=reader.end(); po++)
            out2<<*po<<endl;
    out2.close();
    ofstream out3("d:\\record.txt",ios::out);
    for(auto po=record.begin(); po!=record.end(); po++)
        out3<<*po<<endl;
    out3.close();
}
void Library:: load()
{
    ifstream in1("d:\\book.txt",ios::in);
    if(in1)
    {
        Book tem1;
        book.clear();
        while(in1>>tem1)
        {
            book.push_back(tem1);
            idtorea.insert(make_pair(tem1.getid(),book.size()-1));
            pubtimque.insert(make_pair(tem1.getpubtime(),book.size()-1));
            suoshuque.insert(make_pair(tem1.getsuoshu(),book.size()-1));
            pressque.insert(make_pair(tem1.getpress(),book.size()-1));
        }
        in1.close();
    }
    ifstream in2("d:\\reader.txt",ios::in);
    if(in2)
    {
        reader.clear();
        Student tem2;
        while(in2>>tem2)
        {
            reader.push_back(tem2);
            idtorea.insert(make_pair(tem2.getid(),reader.size()-1));
        }
        in2.close();
    }
    ifstream in3("d:\\record.txt",ios::in);
    if(in3)
    {
        record.clear();
        Operate tem3;
        while( in3>>tem3)
        {
            record.push_back(tem3);
            ridtorec.insert(make_pair(tem3.getname(),record.size()-1));
            bidtorec.insert(make_pair(tem3.getbook(),record.size()-1));
        }
        in3.close();
    }
}
int main()
{
    string account,key,name,suoshu,ath,pre,pub,id;
    cin>>account>>key;
    Library demo(account,key);
    cin>>name;
   demo. querysm( name) ;//测试书名查询
    cin>>suoshu;
  demo.   queryss( suoshu) ; //测试索书号查询
    cin>>ath;
    demo. queryath( ath); //测试作者查询
    cin>>pre;
  demo.   querypres( pre); //测试出版社查询
    cin>>pub;
    demo. querytim( pub);//测试出版时间查询
    //测试个人信息操作
    demo. quepers();  //测试查询读者身份信息
    demo.   quebrro();//测试查询借阅信息
   demo.  queop(); //测试查询读者操作记录(仅个人)
    //测试基础操作
  demo. cxkj(); //测试查询课可借书的数量
    cin>>id;
  demo.   jieshu( id) ;
    cin>>id;
  demo.   huanshu( id);
    cin>>id;
  demo.   xujie( id);
    return 0;
}

posted @ 2019-06-04 23:12  风骨散人  阅读(108)  评论(0编辑  收藏  举报