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;

}





免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM