c++初学者——一个简单的电话簿系统制作

第一次大作业

目的 :

(1)综合运用之前所学知识(选择控制 循环控制,数组,函数,指针,结构体和 文件等)来完成一个简单的信息管理程序的设计。

(2) 充分体现和体会函数在程序设计中的必要性和实用性,并反映主函数main ()在程序设计中的实现思路和方法。

  1. 实训内容和原理

①添加记录:输入联系人的序号、姓名、电话号码等相关信息;(在此基础上我们还添加了加入的时间显示与储存)

②显示记录:显示联系人的序号、姓名、电话号码等相关信息,在此基础上,还增加了录入时间的显示和存储;

③删除记录:根据联系人的任意信息,查找并删除联系人的信息;

④查询记录:根据联系人的序号,查找联系人的其他信息;

⑤修改记录:根据联系人的任意信息,查找并修改联系人的信息;

⑥清空记录:清空电话簿数据;

class CData        //定义数据基类
{
public:
    CData() {};
    virtual int Compare(CData&) = 0;
    virtual void Show() = 0;
    virtual ~CData() {};
};

class CNode
{
private:
    CData* pData; //用于指向数据类的指针
    CNode* pNext; //用于指向链表的后向指针
public:
    CNode()//结点构造函数
    {
        pData = 0;
        pNext = 0;
    }

    CNode(CNode& node)//用于拷贝的构造函数
    {
        pData = node.pData;
        pNext = node.pNext;
    }

    void InputData(CData* pdata)//输入数据
    {
        pData = pdata;
    }

    void ShowNode()
    {
        pData->Show();
    }

    CData* GetData()
    {
        return pData;
    }

    friend class CList;//定义链表类为友元类
};

class CList
{
    CNode* pHead;//链表头结点指针
public:
    CList()
    {
        pHead = 0;
    }

    ~CList()
    {
        DeleteList();
    }

    void AddNode(CNode* pnode);//在首部添加结点
    CNode* DeleteNode(CNode*);//删除一个指定的结点,返回该结点的指针
    CNode* LookUp(CData&);
    //查找一个指定的数据,返回该数据所在的结点在链表中的指针,若未找到返回0
    void ShowList();//打印整个链表
    void DeleteList();//删除整个链表
    CNode* GetListHead()
    {
        return pHead;//返回链表首结点
    }
    CNode* GetListNextNode(CNode* pnode);//返回链表指定结点的下一个结点
}; 

//电话簿类
#include<iostream>
#include<ctime>
#include<string.h>
#include<iomanip>
#include<fstream>
using namespace std; //用命名空间std中的定义
CNode* CList::GetListNextNode(CNode* pnode)//返回链表指定结点的下一个结点
{
    CNode* p1 = pnode;
    return p1->pNext;
};

void CList::AddNode(CNode* pnode)//在首部添加结点
{
    if (pHead == 0)  //如果是空链表,插入的结点是唯一的结点
    {
        pHead = pnode;
        pnode->pNext = 0;
        return;
    }

    else  //否则,插入到链表首部
    {
        pnode->pNext = pHead;
        pHead = pnode;
    }
};

CNode* CList::DeleteNode(CNode* pnode)//删除一个指定的结点,返回该结点的指针
{
    CNode* p1, *p2;
    p1 = pHead;//指向首结点
    while (p1 != pnode && p1->pNext != 0)//寻找要删除的结点
    {
        p2 = p1;//结点指针p2始终在p1的后面
        p1 = p1->pNext;
    }
    if (p1 == pHead) //如果要删除的是首结点
    {
        pHead = pHead->pNext;//将首结点后移
        return pnode;
    }
    p2->pNext = p1->pNext;//p1指向被删除的结点,将p2结点与p1后面的结点连接起来
    return pnode;
}

CNode* CList::LookUp(CData& data)
//查找一个指定的数据,返回该数据所在结点在链表中的指针,若未找到返回0
{
    CNode* p1 = pHead;
    while (p1) //从头结点开始查找
    {
        if (p1->pData->Compare(data) == 0)
            return p1;   //找到返回结点指针
        p1 = p1->pNext;
    }
    return 0;//搜索完整个链表之后,如果找不到,返回空指针0
}

void CList::ShowList()//打印整个链表数据
{
    CNode* p1 = pHead;
    while (p1)
    {
        p1->pData->Show();
        p1 = p1->pNext;
    }
}

void CList::DeleteList() //删除整个链表结点
{
    CNode* p1, *p2;
    p1 = pHead;
    while (p1)
    {
        delete p1->pData;
        p2 = p1;
        p1 = p1->pNext;
        delete p2;
    }
    pHead=NULL; 
}

class CTelRecord :public CData//电话簿记录,为数据基类的公有派生类
{
private:
    char szName[20];//电话簿的数据:姓名和电话号码
    char szNumber[20];
    time_t etime;
    
public:
    CTelRecord()//构造函数
    {
        strcpy(szName, "\0");
        strcpy(szNumber, "\0");
        time(&etime);
    }
    CTelRecord(char* name, char* number)//构造函数
    {
        strcpy(szName, name);
        strcpy(szNumber, number);
        time(&etime);
    }
    void SetRecord(char* name, char* number)//输入数据函数
    {
        strcpy(szName, name);
        strcpy(szNumber, number);
        time(&etime);
    }
    int Compare(CData&);//比较函数,比较姓名
    void Show();
    //打印数据函数
};


int CTelRecord::Compare(CData& data) //比较姓名,供查找用,比较结果为1、0、-1
{
    CTelRecord& temp = (CTelRecord&)data;
    return strcmp(szName, temp.szName);
}

void CTelRecord::Show()//打印一个结点的数据
{
    cout << setw(15) << szName << setw(15) << szNumber<< setw(30)<<ctime(&etime) << endl;
}

void AddRecord(CList& TelList) //将记录添加到链表中
{
    CNode* pNode;
    CTelRecord* pTel;
    char szName[20], szNumber[20];
    cout << "输入名字(输入0结束):";
    cin.getline(szName, 20);
    while (strcmp(szName, "0"))
    {
        cout << "输入电话号码:";
        cin.getline(szNumber, 20);
        pTel = new CTelRecord;//生成新的数据类对象
        pTel->SetRecord(szName, szNumber);//数据类对象赋值
        pNode = new CNode;//生成新的结点
        pNode->InputData(pTel);//结点赋值
        TelList.AddNode(pNode);//结点加入链表
        cout << "输入姓名(输入0结束):";
        cin.getline(szName, 20);
    
    }
    cout << endl << endl;
}

void DisplayRecord(CList& TelList) //显示全部链表数据
{
    cout << setw(15) << "姓名" << setw(15) << "电话号码" << setw(15) << "录入时间" << endl;
    TelList.ShowList();
    cout << endl << endl;
}
void LookUpRecord(CList& TelList) //按照姓名查找电话簿数据
{
    CNode* pLook;
    char szName[20];
    cout << "输入您需要查找的姓名(输入0结束):";
    cin.getline(szName, 20);
    while (strcmp(szName, "0"))
    {
        CTelRecord tele(szName, "0");//生成结点
        pLook = TelList.LookUp(tele);//查找指定结点的数据
        if (pLook)
        {
            cout << "在电话簿中找到" << szName << ",内容是" << endl;
            pLook->ShowNode();

        }
        else
            cout << "在电话簿中查找不到" << szName << "." << endl;
        cout << "输入您需要查找的姓名(输入0结束):";
        cin.getline(szName, 20);
    }
    cout << endl << endl;
    system("pause");
}
void ModifyRecord(CList& TelList) //按照姓名查找电话簿数据
{
    CNode* pLook;
    char szName[20]="hello";
    char tel[20];
    while (strcmp(szName, "0"))
    {
        cout << "输入您需要修改的姓名(输入0结束):";
        cin.getline(szName, 20);
        if(!strcmp(szName, "0"))break;
        CTelRecord tele(szName, "0");//生成结点
        pLook = TelList.LookUp(tele);//查找指定结点的数据
        if (pLook)
        {
            cout << "在电话簿中找到" << szName << ",内容是:" << endl;
            pLook->ShowNode();
            printf("输入新的姓名:\n");
            cin.getline(szName, 20);
            printf("输入电话号码:\n");
            cin.getline(tel, 20);
            CData*tmp = new CTelRecord(szName, tel);//创建更新数据 
            pLook->InputData(tmp);
            cin.getline(tel, 20);
            cout << "修改成功!\n";
        }
        else
        {
            cout << "在电话簿中查找不到" << szName << "." << endl;
        }
    }
    cout << endl << endl;
    system("pause");
}
void DeleteRecord(CList& TelList) //在链表中删除指定节点的数据
{
    CNode* pLook;
    char szName[20];
    cout << "输入您需要删除的姓名(输入0结束):";
    cin.getline(szName, 20);
    while (strcmp(szName, "0"))
    {
        CTelRecord tele(szName, "0");
        pLook = TelList.LookUp(tele);
        if (pLook)        //删除时应先查找出结点
        {
            cout << "在电话簿中找到" << szName << ",内容是:" << endl;
            pLook->ShowNode();
            TelList.DeleteNode(pLook);
            cout << szName << "的资料已删除" << endl;
            delete pLook;
        }
        else
            cout << "在电话簿中查找不到" << szName << "." << endl;
        cout << "输入您需要删除的名字(输入0结束):";
        cin.getline(szName, 20);
    }
    cout << endl << endl;
}
void DestoryRecord(CList& TelList) //在清除链表数据
{
    TelList.DeleteList();
    fstream ifs("TELEPHONE.txt", ios::trunc);//删除文件重新创建 
    ifs.close();
    cout << "清除成功!\n";
}
void StoreFile(CList& TelList)//将链表中的数据保存在文件中
{
    ofstream outfile("TELEPHONE.txt", ios::binary);
    if (!outfile)
    {
        cout << "数据文件打开错误,没有将数据存入文件!\n";
        return;
    }
    CNode* pnode;
    CTelRecord* pTel;
    string strName, strNumber;
    pnode = TelList.GetListHead();//取出链表首结点指针
    while (pnode)
    {
        pTel = (CTelRecord*)pnode->GetData();//返回结点指向的数据域指针
        outfile.write((char*)pTel, sizeof(CTelRecord));//将数据域写入文件
        pnode = TelList.GetListNextNode(pnode);//去下一节点的指针
    }
    outfile.close();
}

void Operate(string& strChoice, CList& TelList)//根据主菜单选项进行操作
{
    if (strChoice == "1")
        AddRecord(TelList);
    else if (strChoice == "2")
        DisplayRecord(TelList);
    else if (strChoice == "3")
        LookUpRecord(TelList);
    else if (strChoice == "4")
        DeleteRecord(TelList);
    else if (strChoice == "0")
        StoreFile(TelList);
    else if (strChoice == "5")
        ModifyRecord(TelList);
    else if (strChoice == "6")
        DestoryRecord(TelList);
    else
        cout << "输入错误,请重新输入您的选择:";
}

void LoadFile(CList& TelList)//在程序开始首先查找有无数据文件,找到后读取文件数据
{
    ifstream infile("TELEPHONE.txt", ios::binary);
    if (!infile)
    {
        cout << "没有数据文件!\n\n";

    }return;
    CNode* pNode;
    CTelRecord* pTel;
    while (!infile.eof())
    {
        pTel = new CTelRecord; //定义数据域对象
        infile.read((char*)pTel, sizeof(CTelRecord));
        pNode = new CNode;
        pNode->InputData(pTel);//数据域对象内容生成结点
        TelList.AddNode(pNode);//将结点加入链表
    }
    TelList.DeleteNode(pNode);//由于文件的关系,多读了一次,所以将首结点删除
    infile.close();
}

int main(void)
{
    CList TelList;    //定义链表类的对象
    system("cls");
    cout << "\t欢迎进入电话簿数据系统\n";
    LoadFile(TelList);    //从文件中输入数据
    string strChoice; //接受主菜单选项
    do
    {
        cout << "\t1.添加电话簿记录\n";
        cout << "\t2.显示电话簿内容\n";
        cout << "\t3.根据姓名查询电话簿数据\n";
        cout << "\t4.根据姓名删除电话簿数据\n";
        cout << "\t5.根据姓名修改电话簿数据\n";
        cout << "\t6.清空电话簿数据\n";
        cout << "\t0.退出系统\n";
        cout << "请输入您的选择:";
        cin >> strChoice;
        cin.ignore();
        Operate(strChoice, TelList);
    } while (strChoice != "0");
    cout << "\n\n\t欢迎再次使用电话簿数据系统\n\n";
    return 0;
}

  • 3
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值