C++课程设计 通讯录管理系统 原码及解析

设计题目:通信录管理系统

用C++设计出模拟手机通信录管理系统,实现对手机中的通信录进行管理。(一)功能要求

  • 查看功能:选择此功能时,列出下列三类选择。
    A 办公类B 个人类C 商务类,当选中某类时,显示出此类所有数据中的姓名和电话号码)
  • 增加功能: 能录入新数据(一个结点包括:姓名、电话号码、分类(可选项有:A 办公类B 个
    人类C 商务类)、电子邮件)。例如
    杨春13589664454 商务类chuny@126.com
    当录入了重复的姓名和电话号码时,则提示数据录入重复并取消录入;当通信录中超过15 条信息时,存储空间已满,不能再录入新数据;录入的新数据能按递增的顺序自动进行条目编号。
  • 拔号功能: 能显示出通信录中所有人的姓名,当选中某个姓名时,屏幕上模拟 打字机 的效果依次显示
    出此人的电话号码中的各个数字,并伴随相应的拔号声音
  • 修改功能: 选中某个人的姓名时,可对此人的相应数据进行修改
    +删除功能: 选中某个人的姓名时,可对此人的相应数据进行删除,并自动调整后续条目的编号。(二)其它要求:
  • 只能使用C++语言,源程序要有适当的注释,使程序容易阅读
  • 至少采用文本菜单界面(如果能采用图形菜单界面更好)
  • 建议使用结构和链表等数据结构
  • 学生可自动增加新功能模块(视情况可另外加分)

乱码请跳转 本人原博客

1.功能介绍

graph LR V0[通讯录管理系统]-->V(int main) V -->A(选择0至6) A -->B[1.查看联系人] A -->D[2.添加联系人] A -->E[3.拨号] A -->F[4.修改] A -->G[5.删除] A -->H[6.history通话记录] A -->I[0.退出] B -->1(void Show_Link) D -->D1(void Add_Link) E -->E1(void Call_Link) F -->F2(void Edi_Link) G -->G1(void Del_Link) H -->H1(void history) I -->I1(void Log_Out) D1 -->a(姓名 手机号 邮箱) D1 -->c(选择0至3分类) D1 -->d2{是否继续添加?} d2 -->|yes|d21(void Add_Link) d2 -->|no|d22(int main) c -->c1(1.个人类) c -->c2(2.办公类) c -->c3(3.商务类) c -->c0(0.返回) F2 -->F1(选择0至4) F1 -->f1(1.修改姓名) F1 -->f2(2.修改手机号) F1 -->f3(3.修改分类) F1 -->f4(4.修改邮箱) F1 -->f0(0.返回)
  • 提示:退出时务必按 0.退出 否则操作数据不会保存到txt

2.关键功能实现原理

打字机效果
把字符串赋值给字符数组,字符逐一输出。在两个字符输出中间用Sleep()函数延迟时间。

示例:
#include<iostream>
#include<windows.h>
using namespace std;
int main()
{
    string ch = {'H','U','G','B','O','Y'};
    for(int i = 0; i < ch.length() ; i++)
    {
        cout<<ch[i];
        Sleep(500);//毫秒
    }
    return 0;
}

拨号音效
调用Beep()系统函数发声,可以修改频率HZ和延时。
~~网上搜到有人用这个写了一首《天空之城》https://www.cnblogs.com/zhcs/p/6832228.html?utm_source=itdadao&utm_medium=referral ~~

示例:
#include<stdio.h>
#include<windows.h>
int main()
{
	
	
	float time_s[13]={261.6,293.7,349.2,493.9,392,440,392,293.7,329.6,392,293.7,261.6,0};//持续时间
	
	int hz[13]={500,500,500,700,500,500,500,500,500,500,500,500,1000};//赫兹频率

	int i=0;
	while(1)
	{
		while(time_s[i]!=0)
		{
			// Beep函数是系统函数,驱动PC-Speaker发声的。
			Beep(time_s[i],hz[i]);
			i++;
		}
		i=0;
	}	return 0;
}
打字机和音效合并-->原码对应函数:
void AddressBook::pout(string str,int t,int music)//str:字符串t:间隔的时间music:是否播放音乐
{

    float hz[11]= {261.6,293.7,349.2,493.9,392,440,392,293.7,329.6,392,293.7}; //beep频率
    int time_s[11]= {500,500,500,700,500,500,500,500,500,500,500}; //beep延时

    for(int i=0; i<str.length(); i++)
    {
        if( music == 1 )//限定
        {
            Beep(hz[i],time_s[i]);
        }
        cout<<str[i];
        Sleep(t);
    }
    return;
}

从TXT文件读数据到链表
在网上搜了很多教程,实现过程比较繁琐。二进制存储什么的,还要考虑字符分割问题。
下面的思路是小编很久才想出来的比较简单直接 可能有投机取巧之嫌但效果是真香,效果很好。

思路:
1.
在主函数`int main()`里
程序运行前:
把txt全部读入链表
程序运行后:
以 覆盖 的方式重新写入txt---这样在调用需要读取txt的函数时就不用来回读写了,也省去了删除和修改功能无法在txt实现的尴尬
2.
用`getline()`函数按行读取数据,替代常规的读取。存入变量时,每个变量占一行;
读取时按行读取后赋值给节点里的单个变量

3.原码

C++课程设计 通讯录管理系统
#include <iostream>
#include <cstring>
#include <cassert>//按行读取
#include <fstream>//读写文件
#include <iomanip>
#include <windows.h>//打字机效果
#include <stdlib.h>
using namespace std;
class person
{
protected:
    char name[60];        //姓名
    char telnb[20];       //电话
    char type[60];        //职业类型
    char email[60];       //邮箱
    int id;               //编号
    person *Mynext;       //指向下一个对象
public:
    person();             //初始化变量
    person(char pname[],char ptelnb[],char ptype[],char pemail[],int pid);
    person(char pname[],char ptelnb[],char ptype[],char pemail[],int pid,person *next);
    char *getname();
    char *gettelnb();
    char *gettype();
    char *getemail();
    int   getid();
    person *getnext();
    void  setnext(person *next);
    void updatid();//id自减

};
person::person()
{
    strcpy(name,"");
    strcpy(telnb,"");
    strcpy(type,"");
    strcpy(email,"");
    Mynext = NULL;
    id = 0;
}
person::person(char pname[],char ptelnb[],char ptype[],char pemail[],int pid)
{
    strcpy(name,pname);
    strcpy(telnb,ptelnb);
    strcpy(type,ptype);
    strcpy(email,pemail);
    Mynext = NULL;
    id = pid;
}
person::person(char pname[],char ptelnb[],char ptype[],char pemail[],int pid,person *next)
{
    strcpy(name,pname);
    strcpy(telnb,ptelnb);
    strcpy(type,ptype);
    strcpy(email,pemail);
    Mynext = next;
    id = pid;
}
char *person::getname()
{
    return name;
}
char *person::gettelnb()
{
    return telnb;
}
char *person::gettype()
{
    return type;
}
char *person::getemail()
{
    return email;
}
person *person::getnext()
{
    return Mynext;
}
void person::setnext(person *next)
{
    Mynext = next;
}
int person::getid()
{
    return id;
}
void person::updatid()
{
    //cout<<"自减函数已经被调用!"<<endl;
    //cout<<id<<endl;
    id = id - 1;
    //cout<<id<<endl;
}
class AddressBook
{
private:
    person *myfirst;
public:
    AddressBook();//初始化
    AddressBook(char npname[],char nptelnb[],char nptype[],char npemail[],int npid);//创建对象
    ~AddressBook();
    void Show_Link();//查看
    void Add_Link();//添加
    void Call_Link();//拨号
    void Edi_Link();//修改
    void Del_Link();//删除
    void Log_Out();//退出
    void output(char seltype[60]);//按类打印
    //void pout(string str,int t);//打字机效果
    void pout(string str,int t,int music);//打字机效果
    void outall();//打印当前所有数据
    void history();//查看通话记录
    void read_txt();//从txt文件读入数据
    void write_txt();//把数据写回txt文件

};
AddressBook::AddressBook()
{
    myfirst = NULL;
}
AddressBook::AddressBook(char npname[],char nptelnb[],char nptype[],char npemail[],int npid)
{
    myfirst = new person(npname,nptelnb,nptype,npemail,npid);
}
AddressBook::~AddressBook()
{
    person *next = myfirst,*temp;
    while(next != NULL)
    {
        temp = next;
        next = next->getnext();
        delete temp;

    }
    myfirst = NULL;
}
void AddressBook::read_txt()//从txt文件读入数据
{
    int i = 0;
    int rid = 0;//ID
    char rname[60],rtelnb[20],rtype[60],remail[60];
    ifstream read("AddressBook_data.txt");
    string line;
    while(getline(read,line))
    {
        i++;
        if(i % 4 == 1)//第一行为姓名
        {
            strcpy(rname,line.c_str());//string类型不能直接赋值给char,要用c_str()转换一下
        }
        if(i % 4 == 2)//第二行为手机号
        {
            strcpy(rtelnb,line.c_str());
        }
        if(i % 4 == 3)//第三行为分类
        {
            strcpy(rtype,line.c_str());
        }
        if(i % 4 == 0)//第四行为E-mail
        {
            rid++;
            strcpy(remail,line.c_str());
            //读到完整的一组数据,开始赋值给链表
            person *p = myfirst;
            if(p == NULL)
            {
                myfirst = new person(rname,rtelnb,rtype,remail,rid);
            }
            else
            {
                while(p->getnext() != NULL)
                {
                    p = p->getnext();
                }
                p ->  setnext(new person(rname,rtelnb,rtype,remail,rid,p->getnext())) ;

            }

        }
    }

}

void AddressBook::outall()
{
    int i=0;
    person *head = myfirst;
    if(head == NULL)
    {
        cout<<"[目前暂无数据]"<<endl;
        cout<<endl;
        return;
    }
    cout<<setw(10)<<"ID"<<setw(20)<<"姓名"<<setw(20)<<"电话"<<setw(20)<<"分类"<<setw(20)<<"E-mail"<<endl;
    cout<<"______________________________________________________________________________"<<endl;
    while(head)
    {
        i++;
        cout<<setw(10)<<head->getid()<<setw(20)<<head->getname()<<setw(20)<<head->gettelnb()<<setw(20)<<head->gettype()<<setw(20)<<head->getemail()<<endl;
        head = head -> getnext();
    }
    cout<<"____________"<<endl;
    cout<<"总计"<<"-"<<i<<"-"<<"人"<<endl;
    cout<<endl;

    return;
}

void AddressBook::Add_Link()
{

    outall();//输出所有数据
    int adid,tpcode;


    char adname[60],adtelnb[20],adtype[60],ademail[60],flag[5];


    strcpy(flag,"y\0");
    while(strcmp(flag,"y\0") == 0)
    {
        //统计数据,给新添加数据编排序的ID
        int i = 0;
        ifstream in("AddressBook_data.txt");
        string aline;
        while(getline(in,aline))
        {
            i++;
            if(i == 60)//四行数据为一个人
            {
                cout<<"储存空间已满!"<<endl;
                return;
            }
        }
        //开始添加
        person *p = myfirst;
        person *rpeat = myfirst;//判断录入是否重复
        cout<<"联系人姓名:"<<endl;
        cin>>adname;
        cout<<"电话:"<<endl;
        cin>>adtelnb;
        while(rpeat)
        {
            if(strcmp(adname,rpeat->getname()) == 0 || strcmp(adtelnb,rpeat->gettelnb()) == 0)
            {
                cout<<"联系人Name:"<<adname<<"/Tel:"<<adtelnb<<"已存在!"<<endl;
                return;
            }
            rpeat = rpeat -> getnext();
        }
        while(1)
        {

            cout<<"选择分类[1]办公类[2]个人类[3]商务类:"<<endl;
            cin>>tpcode;
            if(tpcode > 3 || tpcode < 1)
            {
                cout<<"输入错误!重新输入..."<<endl;
                continue;
            }
            switch(tpcode)
            {
            case 1:
                strcpy(adtype,"办公类");
                break;
            case 2:
                strcpy(adtype,"个人类");
                break;
            case 3:
                strcpy(adtype,"商务类");
                break;
            }
            break;

        }
        cout<<"E-mail:"<<endl;
        cin>>ademail;
        adid = i/4 + 1;
        if(p == NULL)
        {
            myfirst = new person(adname,adtelnb,adtype,ademail,adid);
        }
        else
        {
            while(p->getnext() != NULL)
            {
                p = p->getnext();
            }
            p ->  setnext(new person(adname,adtelnb,adtype,ademail,adid,p->getnext())) ;

        }
        //保存
        //person *psave = myfirst;
        std::ofstream fout("AddressBook_data.txt",ios::app);//在文件末尾追加
        fout<<adname<<"\n"<<adtelnb<<"\n"<<adtype<<"\n"<<ademail<<"\n";
        //psave = psave->getnext();
        /*while(psave)
        {
            fout<<psave->getname()<<"\n"<<psave->gettelnb()<<"\n"<<psave->gettype()<<"\n"<<psave->getemail()<<"\n";
            psave = psave->getnext();
        }*/
        fout.close();
        cout<<"保存成功!"<<endl;
        cout<<"是【y】否【n】继续添加联系人?"<<endl;
        cin>>flag;

    }



}
void AddressBook::output(char seltype[60])
{
    person *head;
    head = myfirst;
    int i = 0;
    cout<<setw(10)<<"ID"<<setw(20)<<"姓名"<<setw(20)<<"电话"<<setw(20)<<"分类"<<setw(20)<<"E-mail"<<endl;
    cout<<"______________________________________________________________________________"<<endl;
    cout<<endl;
    while(head)
    {
        if(strcmp(head->gettype(), seltype)==0)
        {
            cout<<setw(10)<<head->getid()<<setw(20)<<head->getname()<<setw(20)<<head->gettelnb()<<setw(20)<<head->gettype()<<setw(20)<<head->getemail()<<endl;
            //cout<<head->getid()<<head->getname()<<head->gettelnb()<<head->gettype()<<head->getemail()<<endl;
            i = i+1;
        }
        head = head -> getnext();
    }
    if(i == 0)
    {
        cout<<seltype<<"暂无数据!"<<endl;
    }
    else
    {
        cout<<"__________"<<endl;
        cout<<seltype<<"-"<<i<<"-"<<"人"<<endl;
    }


}
void AddressBook::Show_Link()
{
    while(1)
    {
        //分类菜单
        cout<<"     +-----------------------------------+"<<endl;
        cout<<"     |              [菜单]               |"<<endl;
        cout<<"     |                                   |"<<endl;
        cout<<"     |              - 1.办公类           |"<<endl;
        cout<<"     |              - 2.个人类           |"<<endl;
        cout<<"     |              - 3.商务类           |"<<endl;
        cout<<"     |              - 0.退出             |"<<endl;
        cout<<"     +-----------------------------------+"<<endl;
        int i;
        char stype[60];
        cout<<".";
        cin>>i;

        switch(i)
        {
        case 1:
            strcpy(stype,"办公类");
            output(stype);
            break;
        case 2:
            strcpy(stype,"个人类");
            output(stype);
            break;
        case 3:
            strcpy(stype,"商务类");
            output(stype);
            break;

        case(0):
            return;
        default:
            cout<<"输入有误!请重新输入..."<<endl;
            continue;
        }
    }


}
void AddressBook::pout(string str,int t,int music)//str:字符串t:间隔的时间music:是否播放音乐
{

    float hz[11]= {261.6,293.7,349.2,493.9,392,440,392,293.7,329.6,392,293.7}; //beep频率
    int time_s[11]= {500,500,500,700,500,500,500,500,500,500,500}; //beep延时

    for(int i=0; i<str.length(); i++)
    {
        if( music == 1 )//限定
        {
            Beep(hz[i],time_s[i]);
        }
        cout<<str[i];
        Sleep(t);
    }
    return;
}

void AddressBook::Call_Link()
{

    outall();//显示所有联系人及编号

    int cid;
    cout<<"请输入ID:"<<endl;
    cin>>cid;
    if(cid>15||cid<1)
    {
        cout<<"输入错误!"<<endl;
        return;
    }
    person *head;
    head = myfirst;
    while(head)
    {
        if(head->getid() == cid)
        {
            char nb[20],w1[200],w2[200];
            //system("cls");
            system("color 1F");
            strcpy(nb,head->gettelnb());//获得ID对应的号码
            strcpy(w1,"您所拨打的电话正在通话中,请稍后在拨...");
            strcpy(w2,"Sorry! The number you dialed is busy now,please redial later...");
            cout<<"已选择联系人"<<head->getname()<<endl;
            cout<<"正在拨号..."<<endl;
            pout(nb,500,1);
            //system("cls");
            cout<<endl;
            pout(w1,50,0);
            cout<<endl;
            pout(w2,50,0);
            cout<<endl;
            //system("cls");
            system("color 0F");

            //获取当前时间
            time_t t = time(0);
            char tim[64];
            strftime( tim, sizeof(tim), "%Y年-%m月-%d日 %X  ",localtime(&t) );
            //puts( tim );
            //写入通话记录
            std::ofstream fout("CallLog.txt",ios::app);//在文件末尾追加
            fout<<tim<<"呼叫"<<head->gettelnb()<<"("<<head->getname()<<")"<< "\n";
            fout.close();
            break;
        }
        head = head -> getnext();
    }
    return;



}
void AddressBook::Edi_Link()
{
    char ename[60];
    outall();//输出所有联系人
    cout<<"请输入要编辑的联系人的姓名:"<<endl;
    cin>>ename;
    person *head = myfirst;
    int flag = 0;
    while(head)
    {
        if(flag == 2)//修改完成已无需再遍历
        {
            break;
        }

        if(strcmp(head->getname(), ename)==0)
        {

            cout<<"Old-Data:"<<endl;
            cout<<setw(10)<<head->getid()<<setw(20)<<head->getname()<<setw(20)<<head->gettelnb()<<setw(20)<<head->gettype()<<setw(20)<<head->getemail()<<endl;

            while(1)
            {
                int i;
                char enew[60];
                cout<<"     +-----------------------------------+"<<endl;
                cout<<"     |     [请选择您要修改的内容/退出]   |"<<endl;
                cout<<"     |                                   |"<<endl;
                cout<<"     |              - 1.姓名             |"<<endl;
                cout<<"     |              - 2.手机号           |"<<endl;
                cout<<"     |              - 3.分类             |"<<endl;
                cout<<"     |              - 4.E-mail           |"<<endl;
                cout<<"     |              - 0.退出             |"<<endl;
                cout<<"     +-----------------------------------+"<<endl;
                cout<<".";
                cin>>i;
                if(i > 4 || i < 0)
                {
                    cout<<"输入错误!重新输入..."<<endl;
                    continue;
                }
                if(i == 0)
                {
                    break;
                }
                switch(i)
                {
                case 1:
                    cout<<"姓名修改为:"<<endl;
                    cin>>enew;
                    strcpy(head->getname(),enew);
                    break;
                case 2:
                    cout<<"新手机号:"<<endl;
                    cin>>enew;
                    strcpy(head->gettelnb(),enew);
                    break;
                case 3:
                    cout<<"新分类:"<<endl;
                    cin>>enew;
                    strcpy(head->gettype(),enew);
                    break;
                case 4:
                    cout<<"新E-mail:"<<endl;
                    cin>>enew;
                    strcpy(head->getemail(),enew);
                    break;
                }
                //当修改的为第一个人时
                if(flag == 0)
                {
                    myfirst = head;
                }
                flag = 2;//此状态代表修改操作完成
            }


        }
        else
        {
            flag = 1;//代表head已经不是第一个节点了
            head = head -> getnext();
        }

    }
    if(flag != 2)
    {
        cout<<"你还未添加该联系人!"<<endl;
    }
    else
    {
        cout<<"New-Data:"<<endl;
        cout<<setw(10)<<head->getid()<<setw(20)<<head->getname()<<setw(20)<<head->gettelnb()<<setw(20)<<head->gettype()<<setw(20)<<head->getemail()<<endl;
        cout<<"__________"<<endl;
        cout<<ename<<"修改成功!"<<endl;
    }


    return;
}
void AddressBook::history()//查看通话记录
{
    int i;
    ifstream in("CallLog.txt");
    string line;
    cout<<"______________________|通话记录|______________________"<<endl;
    while(getline(in,line))
    {
        i++;
        cout<<line<<endl;
    }
    cout<<"____________"<<endl;
    cout<<"总计"<<"-"<<i<<"-"<<"条通话记录。"<<endl;
    cout<<endl;
}
void AddressBook::Del_Link()
{
    char dname[60];
    outall();//输出所有联系人
    cout<<"请输入要拉黑的联系人的姓名:"<<endl;
    cin>>dname;
    person *head = myfirst;
    person *fhead = myfirst;//fhead用于一会指代head的前一个
    int flag = 0;

    while(head)
    {

        if(strcmp(head->getname(), dname)==0)
        {
            cout<<setw(10)<<head->getid()<<setw(20)<<head->getname()<<setw(20)<<head->gettelnb()<<setw(20)<<head->gettype()<<setw(20)<<head->getemail()<<endl;

            fhead->setnext(head->getnext());//让head的前一个节点指向head的后一个节点;
            head = NULL;

            fhead = fhead->getnext();//从fhead开始ID自减一

            while(fhead)
            {
                //cout<<"进入循环-自减"<<endl;
                fhead->updatid();
                fhead = fhead->getnext();
            }
            //当删除的为第一个联系人时
            if(flag == 0)
            {
                myfirst = myfirst -> getnext();
                cout<<"__________"<<endl;
                cout<<dname<<"已被拉黑!"<<endl;
                return;
            }
        }
        else
        {
            flag = 1;
            fhead = head;
            head = head -> getnext();

        }

    }
    if(flag == 0)
    {
        cout<<"暂无数据!"<<endl;
    }
    else
    {
        cout<<"__________"<<endl;
        cout<<dname<<"已被拉黑!"<<endl;
    }


    return;
}
void AddressBook::write_txt()
{

    person *p = myfirst;
    std::ofstream write("AddressBook_data.txt");//以覆盖写的方式
    while(p)
    {
        write<<p->getname()<<"\n"<<p->gettelnb()<<"\n"<<p->gettype()<<"\n"<<p->getemail()<<"\n";
        p = p->getnext();
    }
    write.close();
    //cout<<"保存成功!"<<endl;
}











int main()
{
    AddressBook call;
    cout<<setiosflags(ios::left);//输出左对齐
    call.read_txt();//从文件读入数据
    while(1)
    {
        //主菜单
        cout<<"     +--------------------------------------------------+"<<endl;
        cout<<"     |              [通讯录管理系统]                    |"<<endl;
        cout<<"     |                                                  |"<<endl;
        cout<<"     |              * 1.查看联系人                      |"<<endl;
        cout<<"     |              * 2.添加联系人                      |"<<endl;
        cout<<"     |              * 3.拨号                            |"<<endl;
        cout<<"     |              * 4.修改                            |"<<endl;
        cout<<"     |              * 5.删除                            |"<<endl;
        cout<<"     |              * 6.history                         |"<<endl;
        cout<<"     |              * 0.退出                            |"<<endl;
        cout<<"     +--------------------------------------------------+"<<endl;
        int i;
        cout<<".";
        cin>>i;
        switch(i)
        {
        case(1):
            call.Show_Link();
            break;
        case(2):
            call.Add_Link();
            break;
        case(3):
            call.Call_Link();
            break;
        case(4):
            call.Edi_Link();
            break;
        case(5):
            call.Del_Link();
            break;
        case(6):
            call.history();
            break;
        case(0):
            //保存数据
            call.write_txt();
            return 0;
        default:
            cout<<"输入有误!请重新输入..."<<endl;
            continue;
        }
    }
    return 0;

}
  • 7
    点赞
  • 39
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 4
    评论
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

JFLEARN

CSDN这么拉会有人打赏?

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值