摘要:本篇文章將用語言代碼實(shí)現(xiàn)一個(gè)通訊錄管理系統(tǒng),本片文章博主將會(huì)運(yùn)用到架構(gòu)提,枚舉,動(dòng)態(tài)內(nèi)存開辟和文件操作等。這里存放數(shù)據(jù)的結(jié)構(gòu)是線性表。這個(gè)指針就可以通過動(dòng)態(tài)開辟內(nèi)存來調(diào)整存放信息的大小。擴(kuò)容成功這樣就實(shí)現(xiàn)了檢查通訊錄是否需要擴(kuò)容的函數(shù)。
本篇文章將用C語言代碼實(shí)現(xiàn)一個(gè)通訊錄管理系統(tǒng),本片文章博主將會(huì)運(yùn)用到架構(gòu)提,枚舉,動(dòng)態(tài)內(nèi)> 存開辟和文件操作等。這里存放數(shù)據(jù)的結(jié)構(gòu)是線性表。
博主碼云gitee鏈接:https://gitee.com/byte-binxin(需要源碼自?。?/p>
先給大家展示一張效果圖
我們要實(shí)現(xiàn)的通訊錄應(yīng)該具備增刪查改四種基本功能,還有顯示,排序,退出和保存的功能。所以我們會(huì)有個(gè)功能。實(shí)現(xiàn)如下:
void menu(){ printf("--------------------------------------/n"); printf("------------通訊錄管理系統(tǒng)------------/n"); printf("------------1.添加聯(lián)系人--------------/n"); printf("------------2.刪除聯(lián)系人--------------/n"); printf("------------3.查找聯(lián)系人--------------/n"); printf("------------4.更改聯(lián)系人信息----------/n"); printf("------------5.顯示通訊錄--------------/n"); printf("------------6.對聯(lián)系人進(jìn)行排序--------/n"); printf("------------7.保存通訊錄--------------/n"); printf("------------0.退出通訊錄--------------/n"); printf("--------------------------------------/n");}
打印效果如下:
我們可以先創(chuàng)建一個(gè)結(jié)構(gòu)體,里面包含聯(lián)系人的各種信息。
#define NAME_MAX 20#define TELE_MAX 12#define SEX_MAX 5#define ADDR_MAX 50typedef struct PeoInfo{ char name[NAME_MAX]; int age; char sex[SEX_MAX]; char tele[TELE_MAX]; char address[ADDR_MAX];}PeoInfo;
然后創(chuàng)建一個(gè)結(jié)構(gòu)體,其中有用來存放通訊錄的大小信息,通訊錄的容量和一個(gè)結(jié)構(gòu)體指針指向PeoInfo這個(gè)結(jié)構(gòu)體。這個(gè)指針就可以通過動(dòng)態(tài)開辟內(nèi)存來調(diào)整存放信息的大小。
typedef struct Contact{ PeoInfo* data; int size; int capacity;}Contact;
為了讓通訊錄能夠存放數(shù)據(jù),我們需要初始化一下通訊錄,首先動(dòng)態(tài)開辟一個(gè)3個(gè)(根據(jù)自己來)PepInfo結(jié)構(gòu)體大小的空間,然后后續(xù)根據(jù)需求再擴(kuò)大容量。還要設(shè)計(jì)一個(gè)加載函數(shù),把上一次保存的信息加載進(jìn)來,這個(gè)函數(shù)我們后面部分講解。代碼實(shí)現(xiàn)如下:
//初始化通訊錄void InitContact(Contact* pc){ assert(pc); //開辟三個(gè)大小的空間 pc->data = (PeoInfo*)malloc(sizeof(PeoInfo)* 3); if (pc->data==NULL) { printf("%s", strerror(errno)); exit(-1); } pc->size = 0; pc->capacity = 3; //加載數(shù)據(jù)到通訊錄上 LoadContact(pc);}
我們要讓用戶選擇對應(yīng)的操作,我們應(yīng)該提供對應(yīng)的實(shí)現(xiàn),考慮到多種選擇,我們可以用switch語句,還有為了讓用戶多次選擇,我們可以把這個(gè)選擇放到一個(gè)do-while循環(huán)里面,根據(jù)用戶的選擇來進(jìn)行相應(yīng)的操作。
為了方便之后自己更好的了解哪個(gè)對應(yīng)哪個(gè)選擇對功能,我們可以創(chuàng)建一個(gè)枚舉類型,這樣我們就可以一目了然哪里該實(shí)現(xiàn)哪個(gè)功能。
enum Option{ EXIT, ADD, DEL, SEARCH, MODIFY, SHOW, SORT, SAVE};
int main(){ //創(chuàng)建一個(gè)通訊錄 Contact con; //初始化通訊錄 InitContact(&con); int input = 0; do { //清屏 system("cls"); menu(); printf("請選擇:>"); scanf("%d", &input); switch (input) { case ADD: //增加聯(lián)系人函數(shù) break; case DEL: //刪除聯(lián)系人函數(shù) break; case SEARCH: //查找聯(lián)系人函數(shù) break; case MODIFY: //修改聯(lián)系人函數(shù) break; case SHOW: //顯示聯(lián)系人函數(shù) break; case SORT: //對聯(lián)系人進(jìn)行排序函數(shù) break; case SAVE: //保存聯(lián)系人函數(shù) break; case EXIT: //銷毀通訊錄函數(shù) 防止內(nèi)存泄漏 printf("退出通訊錄/n"); break; default: printf("選擇錯(cuò)誤/n"); system("pause"); break; } } while (input); return 0;}
很顯然,當(dāng)用戶選擇0是就可以退出這個(gè)循環(huán)了,也就退出了這個(gè)程序。
//初始化通訊錄void InitContact(Contact* pc);//增加聯(lián)系人void AddContact(Contact* pc);//刪除聯(lián)系人void DelContact(Contact* pc);//查找聯(lián)系人void SearchContact(Contact* pc);//更改聯(lián)系人信息void ModifyContact(Contact* pc);//顯示聯(lián)系人void ShowContact(Contact* pc);//對通訊錄進(jìn)行排序void SortContact(Contact* pc);//保存通訊錄void SaveContact(Contact* pc);//銷毀通訊錄void DestoryContact(Contact* pc);
添加聯(lián)系人要考慮通訊錄容量的問題,所以每次添加聯(lián)系人的時(shí)候就要檢查一下通訊錄的先有容量,看是否需要擴(kuò)容,如果通訊錄現(xiàn)有容量和size相同,說明通訊錄滿了,就要擴(kuò)容了。擴(kuò)容需要用到realloc函數(shù)來擴(kuò)大data指針的指向空間的大小。
void CheckCapacity(Contact* pc){ if (pc->capacity == pc->size) { PeoInfo* tmp = (PeoInfo*)realloc(pc->data, sizeof(PeoInfo)*(pc->capacity * 2)); if (tmp == NULL) { printf("%s", strerror(errno)); exit(-1); } pc->data = tmp; pc->capacity *= 2; printf("擴(kuò)容成功/n"); }}
這樣就實(shí)現(xiàn)了檢查通訊錄是否需要擴(kuò)容的函數(shù)。
void AddContact(Contact* pc){ assert(pc); //檢查容量 CheckCapacity(pc); printf("請輸入你要添加人的姓名:>"); scanf("%s", pc->data[pc->size].name); printf("請輸入你要添加人的性別:>"); scanf("%s", pc->data[pc->size].sex); printf("請輸入你要添加人的年齡:>"); scanf("%d", &(pc->data[pc->size].age)); printf("請輸入你要添加人的電話號(hào)碼:>"); scanf("%s", pc->data[pc->size].tele); printf("請輸入你要添加人的家庭住址:>"); scanf("%s", pc->data[pc->size].address); pc->size++; printf("增加成功/n"); system("pause");}
為了讓我們更好的觀察添加聯(lián)系人這個(gè)功能和其他的功能是否很好的實(shí)現(xiàn)了,我們先來實(shí)現(xiàn)一個(gè)顯示通訊錄函數(shù)來觀察一下。
先判斷參數(shù),如果通訊錄為空就打印一下通訊錄為空,然后退出,否則就顯示聯(lián)系人,先打印通訊錄信息。
打印之前還要尋找用戶要查找的聯(lián)系人是存在,我們先實(shí)現(xiàn)查找聯(lián)系人的函數(shù)。
int FindPeopleByName(const Contact* pc, char name[]){ int i = 0; for (i = 0; i < pc->size; i++) { if (strcmp(pc->data[i].name, name) == 0) { return i; } } return -1;}
我們?yōu)榱撕每?,可以搭建一個(gè)表頭,通過循環(huán)來控制,可以自己根據(jù)訓(xùn)練次數(shù)來調(diào)節(jié)
可以通過格式化輸出的"-""%x"來對齊控制,具體看一下如下代碼。
//顯示聯(lián)系人void ShowContact(Contact* pc){ assert(pc); if (pc->size == 0) { printf("通訊錄為空/n"); system("pause"); return; } //打印橫線 int j = 0; for (j = 0; j < 21; j++) { printf("——"); } printf("/n"); printf("|%42s/t/t/t/t/t/t/b/b/b/b/b|/n", "通訊錄"); for (j = 0; j < 21; j++) { printf("——"); } printf("/n"); //打印標(biāo)題 printf("|%-15s|%-5s|%-5s|%-12s|%-42s/b|/n", "姓名", "性別", "年齡", "電話", "家庭住址"); //打印信息 int i = 0; for (i = 0; i < pc->size; i++) { for (j = 0; j < 21; j++) { printf("——"); } printf("/n"); printf("|%-15s|%-5s|%-5d|%-12s|%-42s/b|/n", pc->data[i].name, pc->data[i].sex, pc->data[i].age, pc->data[i].tele, pc->data[i].address); } for (j = 0; j < 21; j++) { printf("——"); } printf("/n"); system("pause");}
下面我們先來看一下添加聯(lián)系人功能的效果:
刪除聯(lián)系人的第一步首先要檢查參數(shù),看通訊錄是否為空,空就返回,無法刪除,不為空就要查找聯(lián)系人,看這個(gè)聯(lián)系人是否存在,在哪個(gè)位置,這些都是我們需要考慮的,查找聯(lián)系人的函數(shù)在上面我們已經(jīng)實(shí)現(xiàn)過來,這里就不過多介紹。
接下來就是刪除了,有兩種方式:
第一種相對來說比較簡單,就是就通訊錄中最后一個(gè)人挪動(dòng)到要?jiǎng)h除的那個(gè)人的位置,但這樣就有一個(gè)缺點(diǎn)就是通訊錄的順序發(fā)生了改變。
另一種方法相對來說比較麻煩,但其實(shí)也很簡單,就是把鑰刪除的位置后面的聯(lián)系人都往前挪動(dòng)一個(gè)就可以了,具體實(shí)現(xiàn)如下:
//刪除聯(lián)系人void DelContact(Contact* pc){ assert(pc); if (pc->size == 0) { printf("通訊錄為空/n"); system("pause"); return; } else { char name[NAME_MAX]; printf("請輸入你要?jiǎng)h除聯(lián)系人的姓名:>"); scanf("%s", name); //查找聯(lián)系人 int pos = FindPeopleByName(pc,name); if (pos == -1) { printf("該聯(lián)系人不存在/n"); printf("刪除失敗/n"); system("pause"); } else { //刪除 int i = 0; for (i = pos; i < pc->size - 1; i++) { pc->data[i] = pc->data[i + 1]; } pc->size--; printf("刪除成功/n"); system("pause"); } }}
動(dòng)態(tài)效果圖如下:
查找聯(lián)系人就是由要用到上面的查找函數(shù),找到后把這個(gè)信息打印一遍就可以了。
//查找聯(lián)系人void SearchContact(Contact* pc){ assert(pc); if (pc->size == 0) { printf("通訊錄為空/n"); system("pause"); return; } else { char name[NAME_MAX]; printf("請輸入你要查找聯(lián)系人的姓名:>"); scanf("%s", name); //查找聯(lián)系人 int pos = FindPeopleByName(pc, name); if (pos == -1) { printf("該聯(lián)系人不存在/n"); printf("查找失敗/n"); system("pause"); } else { printf("查找成功/n"); //打印 int j = 0; for (j = 0; j < 21; j++) { printf("——"); } printf("/n"); //打印標(biāo)題 printf("|%-15s|%-5s|%-5s|%-12s|%-42s/b|/n", "姓名", "性別", "年齡", "電話", "家庭住址"); for (j = 0; j < 21; j++) { printf("——"); } printf("/n"); printf("|%-15s|%-5s|%-5d|%-12s|%-42s/b|/n", pc->data[pos].name, pc->data[pos].sex, pc->data[pos].age, pc->data[pos].tele, pc->data[pos].address); for (j = 0; j < 21; j++) { printf("——"); } printf("/n"); system("pause"); } }}
動(dòng)態(tài)效果演示如下:
我們先創(chuàng)建一個(gè)簡易的菜單欄來提示用戶要對哪個(gè)人的哪個(gè)信息進(jìn)行修改。
void ModifyMenu(){ printf("---------------------------/n"); printf("-----1.姓名 2.性別-----/n"); printf("-----3.年齡 4.電話-----/n"); printf("-----5.家庭住址 0.退出-----/n"); printf("---------------------------/n");}
然后我們可以在ModifyContact函數(shù)里面調(diào)用,與主函數(shù)內(nèi)部的框進(jìn)搭建有相似之處,我們來一起看看代碼是如何實(shí)現(xiàn)的:
//更改聯(lián)系人信息void ModifyContact(Contact* pc){ assert(pc); if (pc->size == 0) { printf("通訊錄為空/n"); system("pause"); return; } else { char name[NAME_MAX]; printf("請輸入你要更改的聯(lián)系人的姓名:>"); scanf("%s", name); //查找聯(lián)系人 int pos = FindPeopleByName(pc, name); if (pos == -1) { printf("該聯(lián)系人不存在/n"); printf("更改信息失敗/n"); system("pause"); } else { int input = 0; do { system("cls"); ModifyMenu(); printf("請選擇:>"); scanf("%d", &input); switch (input) { case 1: printf("請輸入修改后的姓名:>"); scanf("%s", pc->data[pos].name); printf
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://specialneedsforspecialkids.com/yun/121282.html
摘要:文章目錄前言前言一建立文件二編寫函數(shù)三調(diào)試運(yùn)行四成果展示五代碼匯總總結(jié)前言通訊錄是我們?nèi)粘J謾C(jī)中常見的功能之一,綜合語言中結(jié)構(gòu)體,循環(huán),條件語句,動(dòng)態(tài)內(nèi)存分配等等知識(shí)點(diǎn),我們對手機(jī)通訊錄進(jìn)行一個(gè)簡單的實(shí)現(xiàn),下面我們開始講解準(zhǔn)備工作利用語 文章目錄 前言一、建立文件二、編寫函數(shù)三、調(diào)試運(yùn)...
摘要:之前的通訊錄在程序退出后內(nèi)部的數(shù)據(jù)就會(huì)消失,再次打開程序后只能重新輸入數(shù)據(jù),為此我們增加了一個(gè)保存功能來保存信息。 前言: 由于之前實(shí)現(xiàn)的通訊錄在存儲(chǔ)方面只能支持靜態(tài)的1000人的存儲(chǔ)量,但是如果聯(lián)系人較少,則會(huì)造成較大的內(nèi)存浪費(fèi)。而當(dāng)聯(lián)系人一旦超過1000時(shí),就不能再繼續(xù)存儲(chǔ)信息了。因...
摘要:結(jié)構(gòu)體類型的特殊聲明在初階結(jié)構(gòu)體中,我們已經(jīng)將了結(jié)構(gòu)體類型是如何進(jìn)行聲明的,那么在這里,我們將講一些特殊的結(jié)構(gòu)體聲明不完全的聲明。所以我們應(yīng)該這樣寫通過指針來找到下一個(gè)同類型結(jié)構(gòu)體的寫法,我們就稱之為結(jié)構(gòu)體的自引用。 ...
摘要:那么我們首先來改造儲(chǔ)存空間也就是通訊錄結(jié)構(gòu)體靜態(tài)版本人信息存放在數(shù)組中統(tǒng)計(jì)存放的人數(shù)動(dòng)態(tài)版本統(tǒng)計(jì)存放的人數(shù)有效容量我們將原本的結(jié)構(gòu)體數(shù)組改為一個(gè)結(jié)構(gòu)體指針,以此來維護(hù)用以儲(chǔ)存?zhèn)€人信息的空間。 上一期我們編寫了一個(gè)C語言版本的簡易通訊錄,但是我們的之前的通訊錄是沒有記憶功能的,也就是說,一旦關(guān)...
??C語言通訊錄管理系統(tǒng)(簡易版)?? ?一、通訊錄?二、菜單實(shí)現(xiàn)和用戶交互?三、主函數(shù)????1.enum選項(xiàng)????2.switch判斷 ?四、定義聯(lián)系人和通訊錄????1.定義聯(lián)系人結(jié)構(gòu)體????2.定義通訊錄結(jié)構(gòu)體????3.定義結(jié)構(gòu)體變量 ?五、通訊錄初始化?六、新增聯(lián)系人?七、查找聯(lián)系人?八、刪除聯(lián)系人?九、修改聯(lián)系人?十、查看所有聯(lián)系人?十一、清空所有聯(lián)系人?十二、以名字排序所有...
閱讀 3878·2021-09-27 13:36
閱讀 4553·2021-09-22 15:12
閱讀 3062·2021-09-13 10:29
閱讀 1825·2021-09-10 10:50
閱讀 2360·2021-09-03 10:43
閱讀 518·2019-08-29 17:10
閱讀 442·2019-08-26 13:52
閱讀 3249·2019-08-23 14:37