C++课程设计 通讯录管理系统

 

  1. 题目分析

  建立一个手机通讯录系统。手机通讯录中的联系人的信息既可以存储在手机中,也可以存储在手机卡中,也可以同时存储在两个位置上。存储在手机卡的联系人的信息只包含用户名和电话号码两项信息。存储在手机上的联系人的信息包括姓名、电话号码,QQ号码、籍贯。根据题目要求实现功能。

  手机卡联系人文件和手机联系人文件事先已经写好,名字分别是PhoneCard和Phone,格式为文本文件。

  我做的通讯录管理系统一共包括七个类。

  前两个类是信息类,分别是手机卡上联系人和手机联系人的信息,第二个类继承第三个类。

  第三个类是一个虚基类,包含增、删、查、改、浏览的虚函数。

  第四个类继承第三个虚基类,是手机卡上联系人的操作类。数据成员是第一个类的动态对象数组,一个映照容器将联系人名字和该联系人在动态数组的位置联系起来。成员函数包括增、删、查、改、浏览,动态数组相对普通的对象数组操作简单,可直接调用STL的vector类中的函数,映照容器的应用使查找元素进行操作变得相对简单。这个类中的构造函数和析构函数包括了文件的读出和写入。这个类中的Delete函数,实际上并未从对象数组中真正删除,只是设立了一个bool型数组vis[1001],将要删除元素数组的vis值设立为true(已访问)在写入文件时只写入vis值为false的数组,以此实现删除。

  第五个类与第四个类操作完全类似,是对手机联系人的操作类。

  第六个类是一个用户类,在这个类中第三个类得到利用,实现了多态。数据成员是第四个类和第五个类的对象。在类中进行选择操作,确定对手机卡联系人进行操作还是对手机联系人进行操作。除了前两个类的增、删、查、改、浏览操作,这里还包括了从手机卡和手机联系人的双向移动和双向复制操作函数。

  第七个类是菜单类,显示用户界面进行操作。

二、实现代码

//PhoneCard.h

//在codeblocks建立的工程include文件夹下的PhoneCard.h

//第一个类的头文件

#ifndef PHONECARD_H

#define PHONECARD_H

#include

#include



using namespace std;





class PhoneCard

{

    protected:

        string Name;

        string PhoneNumber;



    public:

        void setName(string name);

        void setPhoneNumber(string phonenumber);



        string getName();

        string getPhoneNumber();



        PhoneCard();

        PhoneCard(string name,string phonenumber);



        friend istream&operator>>(istream&input,PhoneCard&phoneC);

        friend ostream&operator<<(ostream&output,PhoneCard&phoneC);

};



#endif // PHONECARD_H



//Phone.cpp

//工程中src文件夹下的P hone.cpp文件

//第一个类的cpp文件

#include "PhoneCard.h"



void PhoneCard::setName(string name){Name=name;}

void PhoneCard::setPhoneNumber(string phonenumber){PhoneNumber=phonenumber;}



string PhoneCard::getName(){return Name;}

string PhoneCard::getPhoneNumber(){return PhoneNumber;}



PhoneCard::PhoneCard(){}

PhoneCard::PhoneCard(string name,string phonenumber):

Name(name),PhoneNumber(phonenumber){}



istream&operator>>(istream&input,PhoneCard&phoneC)

{

    input>>phoneC.Name>>phoneC.PhoneNumber;

    return input;

}

ostream&operator<<(ostream&output,PhoneCard&phoneC)

{

    output<

#include

#include"PhoneCard.h"



using namespace std;





class Phone : public PhoneCard

{

    private:

        string QQnumber;

        string Address;



    public:

        void setQQnumber(string qq);

        void setAddress(string address);



        string getQQnumber();

        string getAddress();



        Phone();

        Phone(string name,string phonenumber,string qq,string address);



        friend istream&operator>>(istream&input,Phone&p);

        friend ostream&operator<<(ostream&output,Phone&p);

};



#endif





 // PHONE_H

//Phone.cpp

//src文件夹的Phone.cpp

//第二个类的cpp文件



#include "Phone.h"



void Phone::setQQnumber(string qq){QQnumber=qq;}

void Phone::setAddress(string address){Address=address;}



string Phone::getQQnumber(){return QQnumber;}

string Phone::getAddress(){return Address;}



Phone::Phone(){}

Phone::Phone(string name,string phonenumber,string qq,string address):

PhoneCard(name,phonenumber),QQnumber(qq),Address(address){}



istream&operator>>(istream&input,Phone&p)

{

    input>>p.Name>>p.PhoneNumber>>p.QQnumber>>p.Address;

    return input;

}

ostream&operator<<(ostream&output,Phone&p)

{

    output<

#include"PhoneCard.h"

#include

#include

#include

#include

#include

#include



using namespace std;





class PhoneCardUser : public Use

{

    private:

        vectorusers;//动态数组存放第一个类的对象

        bool vis[1001];//判断某一位置的数组对象是否访问过

        multimapMap;//映照容器连接对象的名字和该对象在动态数组中的位置

        multimap::iterator it;//迭代器,便于查找元素



    public:

        PhoneCardUser();

        ~PhoneCardUser();



        void Add();

        void Delete();

        void Change();

        void Query();

        void Read();

        void Zero();

        void Set(PhoneCard &p);



};



#endif // PHONECARDUSER_H





//PhoneCardUser.cpp

//src文件夹下的PhoneCardUser.cpp

//第四个类的cpp文件

#include "PhoneCardUser.h"





PhoneCardUser::PhoneCardUser()//构造函数,读文件

{

    string Name,PhoneNumber;

    memset(vis,false,sizeof(vis));//将数组vis内所有元素赋值为0,设为未访问过

    cout<<"Reading the file is PhoneCard.txt"<>Name)

    {

        if(Name=="0")

            break;

        ist>>PhoneNumber;

        PhoneCard p(Name,PhoneNumber);//将文件读到一个对象中

        users.push_back(p);//将该对象压入动态数组中

        Map.insert(pair(Name,users.size()-1));//设置动态数组与Map中Name的联系

    }

    ist.close();

}

PhoneCardUser::~PhoneCardUser()//析构函数  将对象数组内对象写入文件

{

    cout<<"Writing the file is PhoneCard.txt"<1000)

    {

        cout<<"Not add!"<>p;

    users.push_back(p);//将新加入压入对象数组

    Map.insert(pair(p.getName(),users.size()-1));//更新map中的键值和实值

}

void PhoneCardUser::Delete()

{

    cout<<"Please input the name you want to delete:"<>name;

    it=Map.find(name);//查找

    if(it!=Map.end())

    {

        vis[it->second]=true;//更改为已访问过,在写文件时不会写入

    }

    else

        cout<<"No People!"<>name;

    it=Map.find(name);

    if(it!=Map.end()&&!vis[it->second])

    {

        cout<<"Please input the new message:"<>p;

            users[it->second]=p;//将要改位置的元素更新为改后的元素

        }

    }

    else

        cout<<"No People!"<>name;

    it=Map.find(name);

    if(it!=Map.end()&&!vis[it->second])

    {

        cout<second]<(p.getName(),users.size()-1));

}//为了第六个类的移动和复制操作



/*

对手机卡进行操作的类

数据成员包括手机卡类的动态数组users、多重映照容器Map,Map连接联系人名字和该联系人在动态数组中的位置,multimap迭代器便于查找

构造函数用于读入文件信息,将信息放入动态数组;析构函数在对象消亡前将数组内信息写入文件

操作函数增、删、查、改、浏览、Set向数组中压入元素、Zero清空数组

*/



//第五个类所有操作与第四个类相同

// Phone.h

//include文件夹下的Phone.h

//第五个类的头文件

#ifndef PHONEUSER_H

#define PHONEUSER_H



#include 

#include

#include

#include

#include

#include

#include

#include

#include"Phone.h"



using namespace std;





class PhoneUser : public Use

{

    private:

        vectorusers;

        bool vis[1001];

        multimapMap;

        multimap::iterator it;



    public:

        PhoneUser();

        ~PhoneUser();

        void Add();

        void Delete();

        void Change();

        void Query();

        void Read();

        void Zero();

        void Set(Phone&p);

};



#endif // PHONEUSER_H





// PhoneUser.cpp

//src文件夹下的PhoneUser.cpp

//第五个类的cpp文件

#include "PhoneUser.h"







PhoneUser::PhoneUser()

{

    memset(vis,false,sizeof(vis));

    cout<<"Reading file is Phone.txt."<>Name)

    {

        if(Name=="0")  break;

        ist>>PhoneNumber>>QQnumber>>Address;

        Phone p(Name,PhoneNumber,QQnumber,Address);

        users.push_back(p);

        Map.insert(pair(Name,users.size()-1));

    }

    ist.close();

}

PhoneUser::~PhoneUser()

{

    cout<<"Writing the file is Phone.txt"<>p;

    users.push_back(p);

    Map.insert(pair(p.getName(),Map.size()-1));

}

void PhoneUser::Delete()

{

    cout<<"Please input the name whose message you want to delete."<>name;

    it=Map.find(name);

    if(it!=Map.end())

    {

        vis[it->second]=true;

    }

    else

        cout<<"No people!"<>Name;

    it=Map.find(Name);

    if(it!=Map.end()&&!vis[it->second])

    {

        cout<<"Please input the new message."<>p;

        users[it->second]=p;

    }

    else

        cout<<"No people!"<>name;

    it=Map.find(name);

    if(it!=Map.end()&&!vis[it->second])

    {

        cout<second]<(p.getName(),users.size()-1));

}



/*

对手机的操作类,与对手机卡的操作相似

*/



//第六个类实现多态

//Manager.h

//include文件夹下的Manager.h

//第六个类的头文件

#ifndef MANAGER_H

#define MANAGER_H



#include"PhoneCardUser.h"

#include"PhoneUser.h"

#include

#include

#include

#include

#include



using namespace std;



class Manager

{

    private:

        PhoneCardUser PCU;//第四个类的对象

        PhoneUser PU;//第五个类的对象

    public:

        Manager();

        void Add();

        void Delete();

        void Change();

        void Query();

        void Read();

        void MovePhoneToPhoneCard();

        void MovePhoneCardToPhone();

        void CopyPhoneToPhoneCard();

        void CopyPhoneCardToPhone();



};







#endif // MANAGER_H



//Manager.cpp

//src文件夹下的Manager.cpp

//第六个类的cpp文件

#include "Manager.h"





Manager::Manager(){}

void Manager::Add()//选择对手机卡联系人进行操作还是对手机联系人进行操作

{

    Use*u;

    int num;

    cout<<"Please input your choice:1.PhoneCard  2.Phone"<>num;

    if(num==1)

    {

        u=&PCU;//子类对象赋给父类指针,实现多态

        u->Add();

    }

    else

    {

        u=&PU;

        u->Add();

    }

}

void Manager::Delete()

{

    Use*u;

    int num;

    cout<<"Please input your choice:1.PhoneCard  2.Phone"<>num;

    if(num==1)

    {

        u=&PCU;

        u->Delete();

    }

    else

    {

        u=&PU;

        u->Delete();

    }

}

void Manager::Change()

{

    Use*u;

    int num;

    cout<<"Please input your choice:1.PhoneCard  2.Phone"<>num;

    if(num==1)

    {

        u=&PCU;

        u->Change();

    }

    else

    {

        u=&PU;

        u->Change();

    }

}

void Manager::Query()

{

    Use*u;

    int num;

    cout<<"Please input your choice:1.PhoneCard  2.Phone"<>num;

    if(num==1)

    {

        u=&PCU;

        u->Query();

    }

    else

    {

        u=&PU;

        u->Query();

    }

}

void Manager::Read()

{

    Use*u;

    int num;

    cout<<"Please input your choice:1.PhoneCard  2.Phone"<>num;

    if(num==1)

    {

        cout<<"Show PhoneCard"<Read();

    }

    if(num==2)

    {

        cout<<"Show Phone"<Read();

    }

}

void Manager::MovePhoneToPhoneCard()//移动是剪切粘贴,最后有清空步骤

{

    string name,PhoneNumber,QQnumber,Address;

    ifstream ist("Phone.txt",ios::in);

    if(!ist)

    {

        cout<<"The file could not be open."<>name)

    {

        if(name=="0")  break;

        ist>>name>>PhoneNumber>>QQnumber>>Address;

        PhoneCard p(name,PhoneNumber);

        PCU.Set(p);//读进数组中

    }

    PU.Zero();

    ist.close();

}

void Manager::MovePhoneCardToPhone()

{

    string name,PhoneNumber;

    ifstream ist("PhoneCard.txt",ios::in);

    if(!ist)

    {

        cout<<"The file could not be open."<>name)

    {

        if(name=="0") break;

        ist>>PhoneNumber;

        Phone p(name,PhoneNumber,"","");

        PU.Set(p);

    }

    PCU.Zero();

    ist.close();

}

void Manager::CopyPhoneToPhoneCard()//复制粘贴,最后无清空步骤

{

    string name,PhoneNumber,QQnumber,Address;

    cout<<"Please input the name of file:(The name is Phone.txt)"<>name)

    {

        if(name=="0")  break;

        ist>>name>>PhoneNumber>>QQnumber>>Address;

        PhoneCard p(name,PhoneNumber);

        PCU.Set(p);

    }

    ist.close();

}

void Manager::CopyPhoneCardToPhone()

{

    string name,PhoneNumber;

    ifstream ist("PhoneCard.txt",ios::in);

    if(!ist)

    {

        cout<<"The file could not be open."<>name)

    {

        if(name=="0") break;

        ist>>PhoneNumber;

        Phone p(name,PhoneNumber,"","");

        PU.Set(p);

    }

    ist.close();

}





/*

一个用户类,数据成员包括对手机和对手机卡的操作类

用户操作时具体选择手机还是手机卡对信息进行操作

还包含移动信息的函数,复制信息的函数

*/





//Terminal.h

//include文件夹下的Terminal.h

//第七个菜单类的头文件

#ifndef TERMINAL_H

#define TERMINAL_H



#include



class Terminal

{

    public:

        int choice;

        Manager M;



        void start();

        void Menue();



};





#endif // TERMINAL_H



//Terminal.cpp

//src文件夹下的Terminal.cpp

//第七个类的cpp文件

#include "Terminal.h"





int choice;

Manager M;//第六个类的对象



void Terminal::start()

{

    while(1)

    {

        Menue();

        cout<>choice;

        if(choice==10)   return;

        switch(choice)

        {

        case 1:

            M.Add();

            break;

        case 2:

            M.Delete();

            break;

        case 3:

            M.Change();

            break;

        case 4:

            M.Query();

            break;

        case 5:

            M.Read();

            break;

        case 6:

            M.MovePhoneToPhoneCard();

            break;

        case 7:

            M.MovePhoneCardToPhone();

            break;

        case 8:

            M.CopyPhoneToPhoneCard();

            break;

        case 9:

            M.CopyPhoneCardToPhone();

            break;

        default:

            break;

        }

        system("pause");

        system("cls");

    }

}

void Terminal::Menue()

{

    cout<<"-------------------Menue---------------------"<

三、总结

大一时写的C++课程设计,当时写了两天左右,还是很锻炼人的。

  在课程设计周之前的周末,我就大概看了一下题,构建了一下具体思路。在没有看后面老师写的思路之前,我想的是建立两个信息类,一个总的操作类(未实现,操作太繁),终端菜单类,至于多态的要求,我想了好久也没想到咋实现。然后看了题后的实现过程分析,把我想的总操作类分为了四个类,思路清晰,自然而然地也实现了多态。个人感觉实现系统最难的就是实现过程分析,分析具体过程已知,这个程序的难度已经降了一半。

  之前朋友写的选课系统,用到了vector和map。想到我自从学了STL,好像已经很久没用里面的模板了。除了sort排序和vector偶尔用到,map和queue等等已经快忘记它们是什么了。我参考她的multimap用法,回顾了一下这部分知识。vector在添加删除元素很有优势,而且节省内存空间。multimap设置迭代器后查找元素十分快捷方便。所以我想在课程设计中用上vector和map。

  思路和应用方法已经确定,我在周一时开始写程序。周一上午时写到第四个类和第五个类时,类的成员函数具体应用map和vector时还是卡住了一段时间,把map和vector具体应用多看了几遍,便会用了。主要是不想用for循环遍历,太麻烦,尤其是删元素时,太麻烦,很容易出错。STL这个省时省力的模板不用白不用。

  周一下午大概是敲完了程序,编译过了,具体运行有问题。在顺思路时,发现我神奇地略过了第三个类,好像并没有用过它,说好的多态貌似没有。所幸加上个子类对象赋给父类指针并没有很麻烦。晚上时挨个功能运行了一下,调了几个小的错误。增删查改浏览操作没问题,在控制台上输出没问题,数据但读不到文件中去。

  周二上午改了一上午文件写入操作,反复看了几遍,就是找不出错来,耐心耗尽,几乎崩溃。也把程序略读了几遍,顺便还挑出了几个cout输出提示的单词拼写错误,然而文件依然读不出来。中午回去找人帮忙看了一下,事实证明我看了那么多遍的读文件部分程序的确没错,之前的出了点小问题,比如判断==写成了赋值=,小错误不断。在别人帮助下,总算是调好了程序。实在不容易,心累。

  后来帮忙调了几个程序,发现大部分是操作类时出错。自己写程序和帮别人调程序的感觉真不一样,调比写要累得多。帮忙解决了几个问题,但是读文件的错误没有调出来,感觉跟我写的差不多,就是弄不出来,对象数组中有新建立的对象,程序和文件的连接也没问题。但不能写在文件中。猜测可能是运算符运用有问题。

  这次课程设计收获还是很大的,极大地锻炼了耐心。类的具体应用能力也得到了很大的提高,获益匪浅。

 

你可能感兴趣的:(C++)