設計題目:通信錄管理系統
用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;
}