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

2023-04-28,,

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

用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; }

C++课程设计 通讯录管理系统 原码及解析的相关教程结束。

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

下载本文的Word格式文档,以方便收藏与打印。