基于C語(yǔ)言實(shí)現(xiàn)個(gè)人通訊錄管理系統(tǒng)
之前利用C語(yǔ)言完成了一個(gè)關(guān)于個(gè)人通訊錄管理系統(tǒng)的課題,主要是關(guān)于聯(lián)系人的添加、查找、刪除、修改、輸出以及文件的寫入與讀出,還有一個(gè)甜點(diǎn)功能—模擬通話,它的實(shí)現(xiàn)原理也很容易理解,文章末尾會(huì)介紹到。
主框架:
1、函數(shù)聲明
關(guān)于這里的函數(shù)聲明,主要是為了可以清楚的了解整個(gè)系統(tǒng)的功能,這里不做過(guò)多介紹。還有結(jié)構(gòu)體鏈表的創(chuàng)建,貫穿了各個(gè)功能代碼部分,必不可少。
2、聯(lián)系人的添加
這部分主要涉及聯(lián)系人的姓名、地址、電話、QQ號(hào)和郵箱(當(dāng)然需要其他功能可自行添加),考慮到數(shù)組操作不便前提下,使用鏈表的尾插法,通過(guò)不斷開(kāi)創(chuàng)新的結(jié)點(diǎn),然后不斷將新的結(jié)點(diǎn)的地址指向尾結(jié)點(diǎn),使尾結(jié)點(diǎn)不斷后移,而新創(chuàng)的結(jié)點(diǎn)時(shí)按照添加的先后順序進(jìn)行連接(參考下圖可快速理解,此圖片來(lái)源于網(wǎng)絡(luò)),當(dāng)然其中某些項(xiàng)的條件限制也是必不可少的。比如:電話、QQ號(hào)、郵箱
int Addpeo() //添加聯(lián)系人 { int t,n,a; char flag='y'; //僅作為第一次執(zhí)行條件 ptcs p=head,q; while(flag!='n'&&flag!='N') //判斷是否繼續(xù)添加 { q=(ptcs)malloc(sizeof(pcs)); //申請(qǐng)內(nèi)存 p->next=q; //賦予下一個(gè)節(jié)點(diǎn) p=q; q->next=NULL; //尾結(jié)點(diǎn)地址賦空值 ,尾插法 printf("\n\t請(qǐng)輸入:\n"); printf("\t\t姓名:"); scanf("\t\t%s",q->chat.name); printf("\t\t地址:"); scanf("\t\t%s",q->chat.add); printf("\t\t手機(jī)號(hào):"); scanf("\t\t%s",q->chat.tel); do { n=0; //僅做記錄 if(strlen(q->chat.tel)!=11) //計(jì)算手機(jī)號(hào)的長(zhǎng)度 ,判斷是否輸入規(guī)范 { n=1; printf("\t\t您輸入的手機(jī)號(hào)格式不存在,請(qǐng)重新輸入:"); scanf("\t\t%s",q->chat.tel); } else { for(t=0;t<11;t++) { if(q->chat.tel[t]<'0'||q->chat.tel[t]>'9') { n=1; printf("\t\t您輸入的手機(jī)號(hào)格式不合理,請(qǐng)重新輸入:"); scanf("\t\t%s",q->chat.tel); break; } } } }while(n); //輸入QQ號(hào) printf("\t\tQQ號(hào):"); scanf("\t\t%s",q->chat.tecent); do { n=0; if(strlen(q->chat.tecent)>10) //以10位QQ號(hào)為準(zhǔn),判斷是否符合規(guī)范 { n=1; printf("\t\t您輸入的QQ號(hào)格式不存在,請(qǐng)重新輸入:"); scanf("\t\t%s",q->chat.tecent); } else { for(t=0;t<10;t++) { if(q->chat.tecent[t]<'0'||q->chat.tecent[t]>'9') { n=1; printf("\t\t您輸入的QQ號(hào)格式不合理,請(qǐng)重新輸入:"); scanf("\t\t%s",q->chat.tecent); break; } } } }while(n); //輸入郵箱 printf("\t\tEmail:"); scanf("\t\t%s",q->chat.email); do { //判斷郵箱 @符號(hào)輸入規(guī)范(這里不限定郵箱號(hào)碼位數(shù)) a=0; for(t=0;q->chat.email[t]!='\0';t++) { if(q->chat.email[t]=='@') a++; //@數(shù)為1 } if(a!=1) { printf("\t\t輸入的郵箱格式不合理,請(qǐng)重新輸入:"); scanf("\t\t%s",q->chat.email); } }while(a!=1); //是否輸入@ ,為1則終止循環(huán) printf("\n\t是否繼續(xù)添加?(Y/N)"); scanf("\t%c",&flag); } return 0; }
3、聯(lián)系人的查詢
這步使用的是遍歷查詢,共設(shè)置了三種方式,在定義鏈表指針的前提下,通過(guò)遍歷鏈表進(jìn)行信息的對(duì)比,從而判斷聯(lián)系人是否存在,如果存在就直接顯示給用戶,不存在就直接退回功能選項(xiàng)。
int Query() { int m,n; //m記錄選項(xiàng) char flag='y'; ptcs p=head->next; while(flag!='n'&&flag!='N') //是否繼續(xù)查詢 { printf("\n"); printf("\t*************查詢方式**************\n"); printf("\t-----------------------------------\n"); printf("\t 1.按姓名查找 \n"); printf("\t 2.手機(jī)號(hào)查找 \n"); printf("\t 3.按QQ號(hào)碼查找 \n"); printf("\t 4.返回 \n"); printf("\t-----------------------------------\n"); printf("\n\t請(qǐng)選擇查詢方式:"); scanf("\t%d",&m); do { n=0; if(m!=1&&m!=2&&m!=3&&m!=4) { n=1; printf("\t您輸入的查詢方式不存在,請(qǐng)重新輸入:"); scanf("\t%d",&m); } }while(n); //是否輸入正確 if(!p) //判斷鏈表是否為空 { printf("\t該通訊錄為空!\n"); return 0; } if(m==1) { char nm[15]; //要查詢的聯(lián)系人 printf("\t請(qǐng)輸入您要查詢的聯(lián)系人姓名:"); scanf("\t%s",nm); //若鏈表不為空,且聯(lián)系人不相符,則繼續(xù)往后遍歷 while(p!=NULL&&strcmp(p->chat.name,nm)!=0) p=p->next; //遍歷鏈表 if(!p) { printf("\t您要查詢的聯(lián)系人不存在!\n"); return 0; } printf("\t地址:%s\n",p->chat.add); printf("\t手機(jī)號(hào):%s\n",p->chat.tel); printf("\tQQ號(hào):%s\n",p->chat.tecent); printf("\tEmail:%s\n",p->chat.email); } if(m==2) { char te[20]; //要查詢的手機(jī)號(hào)碼 printf("\t請(qǐng)輸入您要查詢的手機(jī)號(hào):"); scanf("\t%s",te); while(p!=NULL&&strcmp(p->chat.tel,te)!=0) p=p->next; if(!p) { printf("\t您要查詢的聯(lián)系人不存在!\n"); return 0; } printf("\t姓名:%s\n",p->chat.name); printf("\t地址:%s\n",p->chat.add); printf("\tQQ號(hào):%s\n",p->chat.tecent); printf("\tEmail:%s\n",p->chat.email); } if(m==3) { char qq[15]; //要查詢的qq號(hào) printf("\t請(qǐng)輸入您要查詢的QQ號(hào):"); scanf("\t%s",qq); while(p!=NULL&&strcmp(p->chat.tecent,qq)!=0) p=p->next; if(!p) { printf("\t您要查詢的聯(lián)系人不存在!\n"); return 0; } printf("\t姓名:%s\n",p->chat.name); printf("\t地址:%s\n",p->chat.add); printf("\t手機(jī)號(hào):%s\n",p->chat.tecent); printf("\tEmail:%s\n",p->chat.email); } if(m==4) return 0; printf("\t是否繼續(xù)查詢?(Y/N)"); //Y則繼續(xù)執(zhí)行while循環(huán),否則退出 scanf("\t%c",&flag); } return 0; }
4、聯(lián)系人的刪除
這部分提供按姓名刪除,通過(guò)遍歷鏈表查詢到指定節(jié)點(diǎn),使用指針使該節(jié)點(diǎn)的上一個(gè)節(jié)點(diǎn)直接指向下一個(gè)節(jié)點(diǎn),以此來(lái)實(shí)現(xiàn)對(duì)聯(lián)系人的刪除操作。詳解圖奉上
int Delete() { char nm[20]; //要?jiǎng)h除的聯(lián)系人姓名 char flag='y'; ptcs p=head->next,bh,pre; //bh,pre均為過(guò)度節(jié)點(diǎn)指針 if(!p) //判斷鏈表是否為空 { printf("\t該通訊錄為空!\n"); return 0; } while(flag!='n'&&flag!='N') { p=head->next; printf("\t請(qǐng)輸入您要?jiǎng)h除的聯(lián)系人姓名:"); scanf("\t%s",nm); while(p!=NULL&&strcmp(p->chat.name,nm)!=0) //比較輸入的聯(lián)系人是否正確 { pre=p; p=p->next; //往后遍歷鏈表,直至找到聯(lián)系人,并賦給p } if(!p) { printf("\t該聯(lián)系人不存在!\n"); return 0; } bh=p->next; //將next值賦給bh,指向要?jiǎng)h除的聯(lián)系人的下一個(gè)地址 if(p==head->next) head->next=bh; else pre->next=bh; //使當(dāng)前聯(lián)系人的上一個(gè)地址,直接指向聯(lián)系人的下一個(gè)地址 printf("\t該聯(lián)系人已刪除!\n"); printf("\t是否繼續(xù)刪除?(Y/N)"); scanf("\t%c",&flag); } return 0; }
5、聯(lián)系人信息的修改
關(guān)于聯(lián)系人的修改,它其實(shí)是對(duì)鏈表的某一節(jié)點(diǎn)進(jìn)行修改,通過(guò)遍歷鏈表查詢到指定節(jié)點(diǎn)并直接進(jìn)行修改,修改過(guò)程中依舊沿用部分格式限定條件,若輸入某項(xiàng)不符合要求,則一直重復(fù)輸入,直到該項(xiàng)輸入符合要求為止。話不多說(shuō),上代碼
//修改姓名 int changename(ptcs p) { scanf("\t%s",p->chat.name); printf("\t修改成功!\n"); return 0; } //修改地址 int changeadd(ptcs p) { scanf("\t%s",p->chat.add); printf("\t修改成功!\n"); return 0; } //修改手機(jī)號(hào)內(nèi)容 int changetel(ptcs p) { int n,t; scanf("\t%s",p->chat.tel); do { n=0; if(strlen(p->chat.tel)!=11) { n=1; printf("\t您輸入的手機(jī)號(hào)格式不存在,請(qǐng)重新輸入:"); scanf("\t%s",p->chat.tel); } else { for(t=0;t<11;t++) { if(p->chat.tel[t]<'0'||p->chat.tel[t]>'9') { n=1; printf("\t您輸入的手機(jī)號(hào)格式不合理,請(qǐng)重新輸入:"); scanf("\t%s",p->chat.tel); break; } } } } while(n); printf("\t修改成功!\n"); return 0; } //修改QQ號(hào)碼 int changeQQ(ptcs p) { int n,t; scanf("%s",p->chat.tecent); do { n=0; if(strlen(p->chat.tecent)!=10) { n=1; printf("\t您輸入的QQ號(hào)格式不存在,請(qǐng)重新輸入:"); scanf("\t%s",p->chat.tecent); } else { for(t=0;t<10;t++) { if(p->chat.tecent[t]<'0'||p->chat.tecent[t]>'9') { n=1; printf("\t您輸入的QQ號(hào)格式不合理,請(qǐng)重新輸入:"); scanf("\t%s",p->chat.tecent); break; } } } } while(n); printf("\t修改成功!\n"); return 0; } //修改電子郵箱 int changeEmail(ptcs p) { int t,a; scanf("\t%s",p->chat.email); do { a=0; for(t=0;p->chat.email[t]!='\0';t++) { if(p->chat.email[t]=='@') a++; } if(a!=1) { printf("\t輸入的郵箱格式不合理,請(qǐng)重新輸入:"); scanf("\t%s",p->chat.email); } } while(a); printf("\t修改成功!\n"); return 0; }
6、聯(lián)系人的輸出
關(guān)于輸出就是按照輸入的順序依次將聯(lián)系人輸出
//輸出通訊錄列表 int Display() { ptcs p=head->next; if(!p) //判斷鏈表是否為空 { printf("\t該通訊錄為空!\n"); return 0; } printf("\n\t**********************************通訊錄列表*************************************\n\n"); printf("\t姓名\t地址\t\t\t手機(jī)號(hào)\t\tQQ號(hào)\t\tEmail\n"); printf("\t---------------------------------------------------------------------------------\n"); while(p) { printf("\t%-8s%-24s%-16s%-16s%-20s\n",p->chat.name,p->chat.add,p->chat.tel,p->chat.tecent,p->chat.email); p=p->next; //繼續(xù)往后遍歷輸出 printf("\t---------------------------------------------------------------------------------\n"); } return 0; }
7、文件的寫入與讀出
通過(guò)新建一個(gè)文件并且指定文件的權(quán)限,將數(shù)據(jù)寫入到指定文件中,以此實(shí)現(xiàn)對(duì)文件的整體寫入操作。它的讀出操作是通過(guò)訪問(wèn)已建立的文件,使用fgets函數(shù)獲取文件中的信息并保存在指定的字符數(shù)組中,之后逐個(gè)進(jìn)行輸出。
//將數(shù)據(jù)寫入文件 int fwrite() { ptcs p=head->next; FILE* fp; char filename[30]; if(!p) { printf("\t該通訊錄為空!"); return 0; } printf("\t請(qǐng)輸入所寫入的文件名:"); scanf("\t%s",filename); if((fp=fopen(filename,"a+"))==NULL) { printf("\t無(wú)法打開(kāi)文件!\n"); system("pause"); //暫停 return 0; } fprintf(fp,"**********************************通訊錄列表*************************************\n\n"); fprintf(fp,"姓名\t地址\t\t\t手機(jī)號(hào)\t\tQQ號(hào)\t\tEmail\n"); fprintf(fp,"---------------------------------------------------------------------------------\n"); while(p) { fprintf(fp,"%-8s%-24s%-16s%-16s%-20s\n",p->chat.name,p->chat.add,p->chat.tel,p->chat.tecent,p->chat.email); p=p->next; fprintf(fp,"---------------------------------------------------------------------------------\n"); } fprintf(fp,"\n**********************************共%d個(gè)聯(lián)系人************************************\n",cacu(head->next)); fclose(fp); //關(guān)閉文件 printf("\t寫入成功!\n"); return 0; } //讀取文件 int fread() { char str[100]; char filename[30]; FILE* fp; //定義文件指針 printf("\t請(qǐng)輸入要讀出的文件名:"); scanf("\t%s",filename); if((fp=fopen(filename,"a+"))==NULL) { printf("\t無(wú)法打開(kāi)文件!\n"); system("pause"); return 0; } while((fgets(str,100,fp))!=NULL) //fgets獲取文件中的信息 ,存入str中 { printf("\t%s",str); //輸出文件中的信息 } return 0; }
8、模擬通話
通過(guò)調(diào)用time函數(shù)來(lái)獲取隨機(jī)數(shù)(從1970.1.1算起),根據(jù)當(dāng)前系統(tǒng)時(shí)間,利用相關(guān)函數(shù)產(chǎn)生一個(gè)隨機(jī)數(shù)的種子,再利用對(duì)應(yīng)函數(shù)產(chǎn)生一個(gè)隨機(jī)數(shù),隨后判斷是否與通訊錄中聯(lián)系人的項(xiàng)數(shù)相符,若相符,則直接將該聯(lián)系人的信息寫入指定文件中,若不相符,則在該文件中寫入未知聯(lián)系人。
//呼叫或被呼叫 int call() { int n; ptcs p=head->next; //用時(shí)間做種,每次產(chǎn)生隨機(jī)數(shù)不一樣,隨著系統(tǒng)時(shí)間的改變而改變 srand((unsigned) time(NULL)); n=rand()%(cacu(p)+5)+1; //產(chǎn)生一個(gè)從1到聯(lián)系人總數(shù)+5之間的一個(gè)隨機(jī)數(shù) return n; } int save(int n,char *filename)//保存通話記錄 { FILE* fp; ptcs p=head->next; int i=1; if((fp=fopen(filename,"a+"))==NULL) { printf("\t通話記錄將失去!\n"); system("pause"); return 0; } if(n<=cacu(p)) { while(i<n) { p=p->next; i++; } //輸出對(duì)應(yīng)聯(lián)系人信息 fprintf(fp,"%-16s%-16s%-16s%-20s\n",p->chat.name,p->chat.tel,p->chat.tecent,p->chat.email); fprintf(fp,"----------------------------------------------------------------------\n"); } else fprintf(fp,"未知號(hào)碼\n"); fclose(fp); //關(guān)閉文件 return 0; }
附上系統(tǒng)功能運(yùn)行圖:
說(shuō)明:為什么選擇使用鏈表結(jié)構(gòu)呢?主要是因?yàn)樵谔砑勇?lián)系人之前并不會(huì)指定添加的個(gè)數(shù),因此它是一個(gè)動(dòng)態(tài)添加的過(guò)程,鏈表大小可變,擴(kuò)展性強(qiáng),并且針對(duì)于聯(lián)系人的刪除操作,使用鏈表不需要改變內(nèi)存地址,只需要修改節(jié)點(diǎn)指針的指向以及節(jié)點(diǎn)的值即可,而數(shù)組大小固定,不適合于動(dòng)態(tài)的存儲(chǔ),并且在對(duì)數(shù)組元素進(jìn)行操作的過(guò)程中,這個(gè)元素以后的所有元素的內(nèi)存地址都要移動(dòng),操作起來(lái)比較麻煩。
整體源碼可參考:C語(yǔ)言實(shí)現(xiàn)個(gè)人通訊錄管理系統(tǒng)
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
- C語(yǔ)言通訊錄管理系統(tǒng)完整版
- C語(yǔ)言通訊錄管理系統(tǒng)課程設(shè)計(jì)
- C語(yǔ)言實(shí)現(xiàn)個(gè)人通訊錄管理系統(tǒng)
- C語(yǔ)言實(shí)現(xiàn)通訊錄管理系統(tǒng)
- C語(yǔ)言通訊錄管理系統(tǒng)完整代碼
- C語(yǔ)言單鏈表實(shí)現(xiàn)通訊錄管理系統(tǒng)
- C語(yǔ)言實(shí)現(xiàn)簡(jiǎn)單的通訊錄管理系統(tǒng)
- C語(yǔ)言代碼實(shí)現(xiàn)通訊錄管理系統(tǒng)
- C語(yǔ)言實(shí)現(xiàn)簡(jiǎn)單通訊錄管理系統(tǒng)
- c語(yǔ)言實(shí)現(xiàn)通訊錄管理系統(tǒng)詳細(xì)實(shí)例
相關(guān)文章
c++ rtti判斷基類指針指向的真實(shí)對(duì)象類型
這篇文章主要為大家介紹了c++ 判斷基類指針指向的真實(shí)對(duì)象類型示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-08-08Visual?C++?6.0新建一個(gè)C語(yǔ)言文件的圖文教程
本教程適用于C語(yǔ)言初學(xué)者,本文主要介紹了Visual?C++?6.0新建一個(gè)C語(yǔ)言文件的圖文教程,具有一定的參考價(jià)值,感興趣的可以了解一下2024-06-06詳解C++ 臨時(shí)量與臨時(shí)對(duì)象及程序的相關(guān)優(yōu)化
這篇文章主要介紹了C++ 臨時(shí)量與臨時(shí)對(duì)象及程序的相關(guān)優(yōu)化,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2019-04-04C++設(shè)計(jì)模式之Static Factory模式詳解
這篇文章主要為大家詳細(xì)介紹了C++設(shè)計(jì)模式之Static Factory模式的相關(guān)資料,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2018-07-07C++中vector和數(shù)組之間的轉(zhuǎn)換及其效率問(wèn)題詳解
c++?vector轉(zhuǎn)數(shù)組是一種將vector容器的元素轉(zhuǎn)換為數(shù)組的方法,主要能幫助提高程序的性能和效率,下面這篇文章主要給大家介紹了關(guān)于C++中vector和數(shù)組之間的轉(zhuǎn)換及其效率問(wèn)題的相關(guān)資料,需要的朋友可以參考下2023-03-03C語(yǔ)言實(shí)現(xiàn)學(xué)生宿舍信息管理系統(tǒng)
這篇文章主要為大家詳細(xì)介紹了C語(yǔ)言實(shí)現(xiàn)學(xué)生宿舍信息管理系統(tǒng),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-03-03C語(yǔ)言實(shí)現(xiàn)簡(jiǎn)單掃雷源碼
這篇文章主要為大家詳細(xì)介紹了C語(yǔ)言實(shí)現(xiàn)簡(jiǎn)單掃雷源碼,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-04-04