/*                      ContactsManagement System -By Leo
*1.  创建文本文件,记录联系人的信息(需要创建两个文本文件,分别存储手机和手机卡上的存储的联系人的信息)。class file//文件类
*2.  以菜单方式工作(字符界面即可) Class Menu
*3.  存储在手机上的联系人的信息包括:姓名和电话号码;存储在手机卡上的联系人的信息包括姓名,籍贯,电话号码,QQ号等信息
*    可以同时存储在两个位置 class Data//通讯录数据类
*     1.Sdcard  1000容量只包含用户名和电话号码两项信息
*     2.Sim 1000容量  用户名 电话号码籍贯 QQ等
*4.  管理系统的功能包括:class operate//操作类 -Manage System -管理系统
*   a)  新建联系人:添加新的联系人(添加时确定是添加到手机上还是手机卡中)
*   b)  删除:删除一个联系人(输入电话号码,删除该联系人。说明,如果两个存储位置上都存在该联系人的话,需要在两个存储位置上都要进行删除操作)
*   c)  修改:修改某个联系人的信息(输入电话号码,查询到联系人之后进行信息的修改。说明,如果两个存储位置上都存在该联系人的话,需要在两个存储位置上都要进行修改操作)
*   d)  查询:根据名字查询联系人信息(查询结果不唯一)
*   e)  浏览:显示所有联系人的信息
*   f)  将联系人的信息从手机转存到手机卡上(同时要避免重复数据的存在。并且在转存是要检查容量是否受限。下同。)
*   g)  将联系人的信息从手机卡上转存到手机上(同时要避免重复数据的存在)
*5.  要支持继承、多态、重载(运算符重载、函数重载)等面向对象的基本特点
*6.  提交程序源码和课程设计报告。
*7.  课程设计评分说明:实现功能:通过;使用了继承技术:中;实现了运算符的重载:良;支持多态:优
*8.  程序目录下 Sim.txt && Sdcard.txt
*/
/*
*Contacts Management System -By Leo
*    Copyright © 2018.5.17 - 2018.6
*       Leo.All Rights Reserved.
*               Ver 1.0
*/
#include<bits/stdc++.h>
using namespace std;
class sdcardData//[姓名 电话号码]
{
public:
    string name;//姓名
    string phone;//电话号码
    string getName()
    {
        return name;
    }
    string getPhone()
    {
        return phone;
    }
    void setName(string x)
    {
        name=x;
    }
    void setPhone(string x)
    {
        phone=x;
    }
    //重载输入运算符
    friend istream &operator>>(istream  & in,  sdcardData &x)
    {
        in>>x.name>>x.phone;
        return in;
    }
    //重载输出运算符
    friend ostream &operator<<(ostream &out, const sdcardData &x )
    {
        out<<x.name<<" "<<x.phone;
        return out;
    }
    //重载赋值运算符
    void operator=(const sdcardData &x)
    {
        name=x.name;
        phone=x.phone;
    }
};
class simData:public sdcardData//继承 class sdcardData [姓名 电话号码 籍贯 QQ]
{
private:
    int no;//序号
    string qq;//QQ号码
    string origin;//籍贯
public:
    //无参构造函数
    simData()
    {
        setName("Null");
        setPhone("Null");
        qq="Null";
        origin="Null";
    }
    //含参构造函数
    simData(string a,string b,string c,string d)
    {
        setName(a);
        setPhone(b);
        qq=c;
        origin=d;
    }
    //Get函数
    int getNo()
    {
        return no;
    }
    string getQQ()
    {
        return qq;
    }
    string getOrigin()
    {
        return origin;
    }
    //Set函数
    void setNo(int x)
    {
        no=x;
    }
    void setQQ(string x)
    {
        qq=x;
    }
    void setOrigin(string x)
    {
        origin=x;
    }
    //显示用户信息
    void display(bool x)
    {
        if(x)
        {
            cout<<"姓名"<<setw(10)<<"电话"<<setw(15)<<"QQ"<<setw(15)<<"籍贯"<<endl;
            cout<<getName()<<setw(15)<<getPhone()<<setw(13)<<qq<<setw(12)<<origin<<endl;
        }
        else
            cout<<setw(6)<<getName()<<setw(15)<<getPhone()<<setw(13)<<qq<<setw(12)<<origin<<endl;
    }
    //重载输入运算符
    friend istream &operator>>(istream  & in,  simData &x)
    {
        in>>x.name>>x.phone>>x.qq>>x.origin;
        return in;
    }
    //重载输出运算符
    friend ostream &operator<<(ostream &out, const simData &x )
    {
        out<<x.name<<" "<<x.phone<<" "<<x.qq<<" "<<x.origin;
        return out;
    }
    //重载赋值运算符
    void operator=(const simData &x)
    {
        name=x.name;
        phone=x.phone;
        qq=x.qq;
        origin=x.origin;
    }
};
struct cmp1
{
    string str;
    cmp1(string s)
    {
        str=s;   //构造函数
    }
    //重载()操作符
    bool operator()(sdcardData &x)
    {
//        return(x.getName().find(str)!=string::npos);
          return(x.getName()==str);//名字
    }
};
struct cmp2
{
    string str;
    cmp2(string s)
    {
        str=s;   //构造函数
    }
    //重载()操作符
    bool operator()(sdcardData &x)
    {
          return(x.getPhone()==str);//手机号
    }
};
struct cmp3
{
    string str;
    cmp3(string s)
    {
        str=s;   //构造函数
    }
    //重载()操作符
    bool operator()(simData &x)
    {
          return(x.getName()==str);//名字
    }
};
struct cmp4
{
    string str;
    cmp4(string s)
    {
        str=s;   //构造函数
    }
    //重载()操作符
    bool operator()(simData &x)
    {
          return(x.getPhone()==str);//手机号
    }
};
class operate//操作类 -Manage System -管理系统
{
public:
    vector<sdcardData> sd;//[姓名 电话号码]
    vector<sdcardData>::iterator s1;
    vector<simData> sim;//[姓名 电话号码 籍贯 QQ]
    vector<simData>::iterator s2;
    multimap<string,string>m;//根据名字查询联系人信息 first->name second->phone
    multimap<string,string>::iterator m1;
    operate() {} //无参构造函数
    //读sdcard文件
    sdload()
    {
        sd.clear();
        m.clear();
        ifstream infile;//只读模式打开Sdcard.txt
        infile.open("Sdcard.txt",ios::in);
        sdcardData temp;
        if (!infile)
        {
            cout<<"Error! 读取文件失败!\n";
        }
        else
        {
            while(infile>>temp)
            {
                sd.push_back(temp);
                m.insert(make_pair(temp.getName(),temp.getPhone()));
            }
        }
        infile.close();
    }
    //读sim文件
    simload()
    {
        sim.clear();
        ifstream infile;//只读模式打开Sim.txt
        infile.open("Sim.txt",ios::in);
        simData temp;
        if (!infile)
        {
            cout<<"Error! 读取文件失败!\n";
        }
        else
        {
            while(infile>>temp)
            {
                sim.push_back(temp);
            }
        }
        infile.close();
    }
    //保存sd文件
    sdsave()
    {
        ofstream outfile;
        outfile.open("Sdcard.txt",ios::out);
        if (!outfile)
        {
            cout<<"Error!保存文件失败!\n";
        }
        else
        {
            for(s1=sd.begin(); s1!=sd.end(); s1++)
            {
                outfile<<*s1<<endl;
            }
        }
        outfile.close();
        sd.clear();
        m.clear();
    }
    //保存sim文件
    simsave()
    {
        ofstream outfile;
        outfile.open("Sim.txt",ios::out);
        if (!outfile)
        {
            cout<<"Error!保存文件失败!\n";
        }
        else
        {
            for(s2=sim.begin(); s2!=sim.end(); s2++)
            {
                outfile<<*s2<<endl;
            }
        }
        outfile.close();
        sim.clear();
    }
    //新建联系人 添加新的联系人(添加时确定是添加到手机上还是手机卡中)
    void add()
    {
        int x;
        cout<<"[1]Sdcard\n";
        cout<<"[2]Sim\n";
        cout<<"请输入你要添加的位置:\n";
add :
        cin>>x;
        if(x==1)
        {
            cout<<"请输***系人信息:    [姓名 电话号码]\n";
            sdcardData x;
            cin>>x;
            sd.push_back(x);
            m.insert(make_pair(x.getName(),x.getPhone()));
            cout<<"\n保存到Sdcard成功 !\n";
        }
        else if(x==2)
        {
            cout<<"请输***系人信息:    [姓名 电话号码 籍贯 QQ]\n";
            simData x;
            cin>>x;
            sim.push_back(x);
            cout<<"\n保存到Sim成功 !\n";
        }
        else
        {
            cout<<"输入错误!请重新输入!\n";
            goto add;
        }
    }
    //删除:删除一个联系人(输入电话号码,删除该联系人。说明,如果两个存储位置上都存在该联系人的话,需要在两个存储位置上都要进行删除操作)
    void del()
    {
        cout<<"请输入要删除的手机号码: \n";
        string x;
        cin>>x;
        s1=find_if(sd.begin(),sd.end(),cmp2(x));//查找
        sd.erase(s1);//删除sd卡上的该用户
        s2=find_if(sim.begin(),sim.end(),cmp4(x));//查找
        sim.erase(s2);//删除sim卡上的该用户
        cout<<"删除  "<<x<<"  成功!\n";
    }
    //修改:修改某个联系人的信息(输入电话号码,查询到联系人之后进行信息的修改。
    //说明,如果两个存储位置上都存在该联系人的话,需要在两个存储位置上都要进行修改操作)
    void modify()
    {
        cout<<"请输入要修改的手机号码: \n";
        string x;
        cin>>x;
        s1=find_if(sd.begin(),sd.end(),cmp2(x));//查找
        s2=find_if(sim.begin(),sim.end(),cmp4(x));//查找
        cout<<"\n请确认您要修改的联系人: \n";
        s2->display(1);
        cout<<endl;
        system("pause");
        system("cls");
        sd.erase(s1);//删除sd卡上的该用户
        sim.erase(s2);//删除sim卡上的该用户
        cout<<"\n请输入修改后的联系人信息:  [姓名 电话号码 籍贯 QQ]\n";
        string a,b,c,d;
        cin>>a>>b>>c>>d;//输入信息
        sdcardData x1;
        x1.setName(a);
        x1.setPhone(b);
        simData x2(a,b,c,d);
        sd.push_back(x1);//压入sd
        sim.push_back(x2);//压入sim
        cout<<"\n修改联系人成功!\n";
        cout<<"\n修改后的联系人信息:\n";
        x2.display(1);
        cout<<endl;
    }
    //根据名字查询联系人信息(查询结果不唯一)
    void query()
    {
        cout<<"请输入要查找的联系人姓名: \n";
        string x;
        cin>>x;
        s2=find_if(sim.begin(),sim.end(),cmp1(x));//查找
        cout<<"\n\n";
        //cout<<*s2<<endl;
        s2->display(1);
    }
    //浏览:显示所有联系人的信息
    void display()
    {
        cout<<"姓名"<<setw(10)<<"电话"<<setw(15)<<"QQ"<<setw(15)<<"籍贯"<<endl;
        for(s2=sim.begin(); s2!=sim.end(); s2++)
        {
            //cout<<*s2<<endl;
            s2->display(0);
        }
    }
    //将联系人的信息从手机转存到手机卡上(同时要避免重复数据的存在。并且在转存是要检查容量是否受限。下同。)
    //将联系人的信息从手机卡上转存到手机上(同时要避免重复数据的存在)
};
class menu//菜单类(字符界面)主菜单+子菜单
{
public:
    operate o;
    void useroperator() //用户菜单
    {
umenu:
        cout << "■■■■■■■■■■■■■通讯录■■■■■■■■■■■■■■\n";
        cout << "■                  ┏━━━━━━━━━━━━━━┓                      ■\n";
        cout << "■                  ┃ [0] 退出系统 ┃                      ■\n";
        cout << "■                  ┣━━━━━━━━━━━━━━┫                      ■\n";
        cout << "■                  ┃ [1]  增加    ┃                      ■\n";
        cout << "■                  ┣━━━━━━━━━━━━━━┫                      ■\n";
        cout << "■                  ┃ [2]  删除    ┃                      ■\n";
        cout << "■                  ┣━━━━━━━━━━━━━━┫                      ■\n";
        cout << "■                  ┃ [3]  修改    ┃                      ■\n";
        cout << "■                  ┣━━━━━━━━━━━━━━┫                      ■\n";
        cout << "■                  ┃ [4]  查询    ┃                      ■\n";
        cout << "■                  ┣━━━━━━━━━━━━━━┫                      ■\n";
        cout << "■                  ┃ [5] 显示所有 ┃                      ■\n";
        cout << "■                  ┗━━━━━━━━━━━━━━┛                      ■\n";
        cout << "■■■■■■■■■■■■By-Leo■■■■■■■■■■■■■■■\n";
        cout << "输入要进行的操作:\n" ;
        if(o.sd.empty()&&o.sim.empty()){//如果容器为空 则读文件
            o.sdload();
            o.simload();
        }
        int command;
        cin >> command;//输入命令
        switch (command)
        {
        case 0: //退出系统
        {
            //o.sdcard();
            //o.simsave();
            cout<<"         -     感谢使用  -  正在退出系统   -   \n";
            system("pause");
            system("cls");
            exit(0); //exit(1)是异常退出 exit(0)是正常退出
            break;
        }
        case 1://增加
        {
            o.add();
            system("pause");
            system("cls");
            goto umenu;
            break;
        }
        case 2://删除
        {
            o.del();
            system("pause");
            system("cls");
            goto umenu;
            break;
        }
        case 3://修改
        {
            o.modify();
            system("pause");
            system("cls");
            goto umenu;
            break;
        }
        case 4://查询
        {
            o.query();
            system("pause");
            system("cls");
            goto umenu;
            break;
        }
        case 5://显示所有
        {
            o.display();
            system("pause");
            system("cls");
            goto umenu;
            break;
        }
      }
    }
};
int main()
{
    menu x;//菜单类
    x.useroperator();//菜单操作
}