C语言 通讯录管理系统(链表,手机号码分段存储,txt文件存取)
通訊錄管理系統(tǒng)
- 一、需求分析
- 二、設(shè)計(jì)思路
- 三、數(shù)據(jù)
- 1、內(nèi)存數(shù)據(jù)結(jié)構(gòu)
- 2、文件數(shù)據(jù)
- 四、主要功能接口
- 五、問題以及解決方案
- 1.從txt文件中讀取數(shù)據(jù)到內(nèi)存時(shí)
- 2.用scanf函數(shù)從stdin中讀取輸入數(shù)據(jù),因錯(cuò)誤輸入的數(shù)據(jù)可能導(dǎo)致scanf函數(shù)死循環(huán)的問題
- 3.itoa函數(shù)不是C語言標(biāo)準(zhǔn)庫函數(shù),需要實(shí)現(xiàn)該函數(shù)
- 六、完整代碼
- 七、效果截圖
一、需求分析
設(shè)計(jì)一個(gè)通訊錄管理系統(tǒng),記錄聯(lián)系人的手機(jī)號(hào)碼,姓名,聯(lián)系地址,職業(yè),公司,郵箱。可以增加聯(lián)系人信息,刪除聯(lián)系人信息,修改聯(lián)系人信息,查找聯(lián)系人,排序,打印通訊錄信息,一鍵清空通信錄等
二、設(shè)計(jì)思路
1.根據(jù)需求分析,需要對(duì)數(shù)據(jù)進(jìn)行增加,刪除,修改,查找,排序等,我選擇了雙向鏈表作為內(nèi)存數(shù)據(jù)結(jié)構(gòu),考慮到每個(gè)人的手機(jī)號(hào)碼是唯一的,選擇了手機(jī)號(hào)碼作為key,同時(shí)考慮到數(shù)據(jù)量很大的情況下,可能會(huì)影響排序性能,所以考慮用手機(jī)號(hào)碼的前四位進(jìn)行分段存儲(chǔ),每一段對(duì)應(yīng)一個(gè)鏈表,所以代碼中管理了10000條雙向鏈表,分別對(duì)應(yīng)手機(jī)號(hào)碼前四位0-9999的手機(jī)號(hào)碼段。
2.數(shù)據(jù)持久化,我選擇將通訊錄內(nèi)存數(shù)據(jù)保存到txt文件中,從內(nèi)存數(shù)據(jù)到txt文件,用C語言庫函數(shù)提供的fopen函數(shù)和sprintf函數(shù)即可實(shí)現(xiàn),從txt文件數(shù)據(jù)到內(nèi)存數(shù)據(jù),用C語言庫函數(shù)fopen函數(shù)和strtok函數(shù)即可實(shí)現(xiàn)。
三、數(shù)據(jù)
1、內(nèi)存數(shù)據(jù)結(jié)構(gòu)
聯(lián)系人信息
struct People {char tel[20]; //手機(jī)號(hào)碼char name[30]; //姓名char address[100]; //聯(lián)系地址char occupation[20]; //職業(yè)char company[40]; //公司char email[30]; //郵箱 };鏈表中的一個(gè)節(jié)點(diǎn)
struct People_Node {struct People people; //聯(lián)系人信息struct People_Node *next; //上一個(gè)節(jié)點(diǎn)struct People_Node *pre; //下一個(gè)節(jié)點(diǎn) };一條鏈表
struct People_List {int len; //鏈表節(jié)點(diǎn)總個(gè)數(shù)struct People_Node *head; //頭節(jié)點(diǎn)struct People_Node *tail; //尾節(jié)點(diǎn) };2、文件數(shù)據(jù)
默認(rèn) contact.txt 文件(注意最后一行是空白行)
手機(jī)號(hào)碼 姓名 聯(lián)系地址 職業(yè) 公司 郵箱contact.txt 文件 保存示例(用測(cè)試命令生產(chǎn)的數(shù)據(jù))
手機(jī)號(hào)碼 姓名 聯(lián)系地址 職業(yè) 公司 郵箱 10121882476 宋八 天津 快遞員 云上科技 555@163.com 10698756589 宋八 武漢 老師 云上科技 333@qq.com 12121198969 唐九 武漢 個(gè)體 小云直播 666@163.com 14779567330 王五 廣西 個(gè)體 小蔥蔬菜 111@163.com 18817493813 李四 北京 快遞員 滕芬網(wǎng)絡(luò) 111@163.com四、主要功能接口
增加聯(lián)系人相關(guān)
int add_con(); //增加聯(lián)系人 int add_people(struct People people); //增加聯(lián)系人到鏈表刪除聯(lián)系人相關(guān)
int del_con(); //刪除聯(lián)系人 int del_people(struct People people); //從鏈表中刪除聯(lián)系人修改聯(lián)系人相關(guān)
int mod_con(); //修改聯(lián)系人信息 int mod_people(struct People people); //從鏈表中修改聯(lián)系人信息查找聯(lián)系人相關(guān)
int find_con(); //查找聯(lián)系人 struct People_Node *find_people(struct People people); //從鏈表中查找聯(lián)系人排序通訊錄相關(guān)
void sort_con(); //排序通訊錄 void sort_people_list(); //按照手機(jī)號(hào)碼從小到大排序通訊錄并輸出到屏幕打印通訊錄相關(guān)
void print_con(); //打印通訊錄 void print_people_list(); //打印通訊錄列表 void print_people(struct People *p); //打印聯(lián)系人信息清空通訊錄
int clean_con(); //清空通訊錄退出通訊錄
void exit_con(); //退出通訊錄五、問題以及解決方案
1.從txt文件中讀取數(shù)據(jù)到內(nèi)存時(shí)
fprintf(fp, "%s %s %s %s %s %s\n", people.tel, people.name, people.address, people.occupation, people.company, people.email);問題1:如上代碼所示,因?yàn)橛胒printf函數(shù)寫入到txt文件時(shí),最后一個(gè)數(shù)據(jù)是加了\n的,所以從txt文件中讀取數(shù)據(jù)到內(nèi)存數(shù)據(jù)時(shí),應(yīng)該將\0替換掉\n,再保存在內(nèi)存中,如下代碼所示。
//字符串拷貝剔除掉換行符\n void strcpy_not_n(char *des, char *src) {while (*src != '\0'){if (*src != '\n')*des = *src;else*des = '\0';src++;des++;} }從txt文件中加載數(shù)據(jù)到內(nèi)存代碼片段
switch (column){case 0:strcpy(people.tel, str);break;case 1:strcpy(people.name, str);break;case 2:strcpy(people.address, str);break;case 3:strcpy(people.occupation, str);break;case 4:strcpy(people.company, str);break;default:strcpy_not_n(people.email, str); //去掉\nbreak;}str = strtok(NULL, LINE);column++;問題2:因?yàn)槲覀兇鎯?chǔ)數(shù)據(jù)的txt文件,默認(rèn)最后一行是空白行,所以從txt文件中加載數(shù)據(jù)到內(nèi)存的時(shí)候,應(yīng)該過濾掉空白行,不然我們從txt文件中加載數(shù)據(jù)會(huì)多了一個(gè)6個(gè)數(shù)據(jù)都為空的記錄,具體處理如下所示。
從txt文件中加載數(shù)據(jù)到內(nèi)存代碼片段
char buf[BUFF_SIZE];int len = 0;int row = 0;while(fgets(buf, BUFF_SIZE, fp)){if ((row++) == 0) //第一行是注釋 手機(jī)號(hào)碼 姓名 聯(lián)系地址 職業(yè) 公司 郵箱continue;if(buf[0] == '\n') //過濾掉讀到的是空白行continue;2.用scanf函數(shù)從stdin中讀取輸入數(shù)據(jù),因錯(cuò)誤輸入的數(shù)據(jù)可能導(dǎo)致scanf函數(shù)死循環(huán)的問題
因?yàn)閟canf函數(shù),我們從命令行輸入數(shù)據(jù),并按下enter換行鍵后,scanf函數(shù)會(huì)從stdin緩沖區(qū)中按照我們格式化的格式讀取輸入的數(shù)據(jù),并且不符合讀取格式的數(shù)據(jù)會(huì)跳過,并還留在緩沖區(qū)中,直到按照我們的格式讀取到完整數(shù)據(jù)為止,并且輸入過多的未讀取的數(shù)據(jù)也還在緩沖區(qū)中,所以為了防止殘留的stdin中的垃圾數(shù)據(jù)阻礙我們下一次從stdin緩沖區(qū)中讀取到不準(zhǔn)確的數(shù)據(jù),我們應(yīng)該在scanf函數(shù)讀取到完整數(shù)據(jù)后,對(duì)stdin緩沖區(qū)進(jìn)行清空,處理如下:
//清空無效的輸入 void clean_stdin() {char s;do{scanf("%c", &s);}while(s != '\n'); }部分代碼段
scanf("%s %s %s %s %s", people.name, people.address, people.occupation, people.company, people.email);clean_stdin();3.itoa函數(shù)不是C語言標(biāo)準(zhǔn)庫函數(shù),需要實(shí)現(xiàn)該函數(shù)
//數(shù)字轉(zhuǎn)字符串函數(shù) char *itoa_my(int value, char *str, int radix) {static char dig_my[] ="0123456789""abcdefghijklmnopqrstuvwxyz";int n = 0, neg = 0;unsigned int v;char* p, *q;char c;/* 負(fù)數(shù):十進(jìn)制直接在前面加負(fù)號(hào),其它進(jìn)制用補(bǔ)碼 */if (radix == 10 && value < 0) {v = -value;neg = 1;}else{v = value;}/* 其它進(jìn)制的負(fù)數(shù)轉(zhuǎn)為unsigned int類型,即取了補(bǔ)碼 */do {str[n++] = dig_my[v%radix];v /= radix;} while (v);if (neg)str[n++] = '-';str[n] = '\0';/* 字符串反轉(zhuǎn) */for (p = str, q = p + (n-1); p < q; ++p, --q)c = *p, *p = *q, *q = c;return str; }六、完整代碼
contact.h 文件
#ifndef CONTACT_H #define CONTACT_H#define CON_TXT_PATH "./contact.txt" #define BUFF_SIZE 256 #define LINE " " //分割符號(hào) #define COUNT_TEL_MAX 9999 #define RETURN_MAIN ".." #define RETURN_MAIN_FLAG 100 #define PEOPLE_INFO "手機(jī)號(hào)碼\t姓名\t聯(lián)系地址\t職業(yè)\t公司\t郵箱\n"enum OPTION {TEST = 0,ADD = 1,DEL,MOD,FIND,SORT,PRINT,CLEAN,EXIT,END };//聯(lián)系人信息 struct People {char tel[20]; //手機(jī)號(hào)碼char name[30]; //姓名char address[100]; //聯(lián)系地址char occupation[20]; //職業(yè)char company[40]; //公司char email[30]; //郵箱 };//鏈表中的一個(gè)節(jié)點(diǎn) struct People_Node {struct People people; //聯(lián)系人信息struct People_Node *next; //上一個(gè)節(jié)點(diǎn)struct People_Node *pre; //下一個(gè)節(jié)點(diǎn) };//一個(gè)鏈表 struct People_List {int len; //鏈表節(jié)點(diǎn)總個(gè)數(shù)struct People_Node *head; //頭節(jié)點(diǎn)struct People_Node *tail; //尾節(jié)點(diǎn) };//手機(jī)號(hào)碼前四位對(duì)應(yīng)的鏈表集合 struct People_List *g_tel[COUNT_TEL_MAX];void display_menu(); //列出功能菜單 int init_con(); //初始化通訊錄 int load_con(); //從txt文件中加載通訊錄int add_con(); //增加聯(lián)系人 int add_people(struct People people); //增加聯(lián)系人到鏈表int del_con(); //刪除聯(lián)系人 int del_people(struct People people); //從鏈表中刪除聯(lián)系人int mod_con(); //修改聯(lián)系人信息 int mod_people(struct People people); //從鏈表中修改聯(lián)系人信息int find_con(); //查找聯(lián)系人 struct People_Node *find_people(struct People people); //從鏈表中查找聯(lián)系人void sort_con(); //排序通訊錄 void sort_people_list(); //按照手機(jī)號(hào)碼從小到大排序通訊錄并輸出到屏幕void print_con(); //打印通訊錄 void print_people_list(); //打印通訊錄列表 void print_people(struct People *p); //打印聯(lián)系人信息int clean_con(); //清空通訊錄void exit_con(); //退出通訊錄int test_cmd(); //測(cè)試命令//輔助函數(shù) void clean_stdin(); //清空無效的輸入 int check_return_main(const char *str); //是否返回主菜單 int get_key(const char *tel); //返回手機(jī)號(hào)碼對(duì)應(yīng)的數(shù)組數(shù)組下標(biāo) int is_digit_string(const char *str); //檢測(cè)str是否為全數(shù)字 int check_people(struct People people); //檢測(cè)輸入的格式比如手機(jī)號(hào)碼格式是否正確等 void strcpy_not_n(char *des, char *src); //字符串拷貝剔除掉換行符\n void save_people_list(); //保持?jǐn)?shù)據(jù)到txt文件 char *itoa_my(int value, char *str, int radix); //數(shù)字轉(zhuǎn)字符串函數(shù)#endifcontact.c 文件
#include <stdio.h> #include <stdlib.h> #include <errno.h> #include <string.h> #include <ctype.h> #include <time.h> #include "contact.h"extern int errno;int main() {srand((unsigned)time(NULL)); /*播種子*/init_con();enum OPTION op = 0;int r = 0;while(1){display_menu();r = scanf("%d", &op);if (r == 0 || op < TEST || op >= END) {clean_stdin();printf("輸入錯(cuò)誤,請(qǐng)重新選擇功能\n");continue;}switch(op){case TEST:{while(1){r = test_cmd();if (r == RETURN_MAIN_FLAG)break;}break;}case ADD:{while(1){r = add_con();if (r == RETURN_MAIN_FLAG)break;}break;}case DEL:{while(1){r = del_con();if (r == RETURN_MAIN_FLAG)break;}break;}case MOD:{while(1){r = mod_con();if (r == RETURN_MAIN_FLAG)break;}break;}case FIND:{while(1){r = find_con();if (r == RETURN_MAIN_FLAG)break;}break;}case SORT:sort_con();break;case PRINT:print_con();break;case CLEAN:{while(1){r = clean_con();if (r != 0)break;}break;}case EXIT:exit_con();break;default:break;}}return 0; }//列出功能菜單 void display_menu() {printf("*****************************************************************************************\n");printf("** 通訊錄 **\n");printf("** **\n");printf("** 請(qǐng)選擇功能 **\n");printf("** 0:測(cè)試命令 **\n");printf("** 1:增加聯(lián)系人 **\n");printf("** 2:刪除聯(lián)系人 **\n");printf("** 3:修改聯(lián)系人 **\n");printf("** 4:查找聯(lián)系人 **\n");printf("** 5:排序聯(lián)系人 **\n");printf("** 6:打印通訊錄 **\n");printf("** 7:清空通訊錄 **\n");printf("** 8:退出 **\n");printf("** **\n");printf("** 在子功能下輸入:.. 返回到主目錄 **\n");printf("** **\n");printf("*****************************************************************************************\n"); }//初始化通訊錄 int init_con() {int i = 0;for (i = 0; i < COUNT_TEL_MAX; i++){struct People_List *list = (struct People_List *)malloc(sizeof(struct People_List));list->len = 0;list->head = NULL;list->tail = NULL;g_tel[i] = list;}return load_con(); }//從contact.txt文件中加載通訊錄 int load_con() {FILE *fp = fopen(CON_TXT_PATH, "r");if (!fp){fprintf(stderr, "打開%s文件錯(cuò)誤:%s\n", CON_TXT_PATH, strerror(errno));return 0;}char buf[BUFF_SIZE];int len = 0;int row = 0;while(fgets(buf, BUFF_SIZE, fp)){if ((row++) == 0) //第一行是注釋 手機(jī)號(hào)碼 姓名 聯(lián)系地址 職業(yè) 公司 郵箱continue;if(buf[0] == '\n') //過濾掉讀到的是空白行continue;int column = 0;struct People people;char *str = strtok(buf, LINE);while(str){switch (column){case 0:strcpy(people.tel, str);break;case 1:strcpy(people.name, str);break;case 2:strcpy(people.address, str);break;case 3:strcpy(people.occupation, str);break;case 4:strcpy(people.company, str);break;default:strcpy_not_n(people.email, str); //去掉\nbreak;}str = strtok(NULL, LINE);column++;}add_people(people);row++;}fclose(fp);//print_people_list();return 1; }//增加聯(lián)系人 int add_con() {printf("請(qǐng)輸入手機(jī)號(hào)碼 姓名 聯(lián)系地址 職業(yè) 公司 郵箱\n");struct People people; scanf("%s", people.tel);if(check_return_main(people.tel)){clean_stdin();return RETURN_MAIN_FLAG;}scanf("%s %s %s %s %s", people.name, people.address, people.occupation, people.company, people.email);clean_stdin();int r = check_people(people);if (r == -1)return 0;if (find_people(people)){ printf("手機(jī)號(hào)碼:%s 的聯(lián)系人已經(jīng)存在!\n", people.tel);return 0;}r = add_people(people);if (!r)return 0;//print_people_list();FILE *fp = fopen(CON_TXT_PATH, "a+"); /*打開一個(gè)文本文件,允許讀寫文件。如果文件不存在,則會(huì)創(chuàng)建一個(gè)新文件。讀取會(huì)從文件的開頭開始,寫入則只能是追加模式。*/if (!fp){fprintf(stderr, "打開%s文件錯(cuò)誤:%s\n", CON_TXT_PATH, strerror(errno));return 0;}fprintf(fp, "%s %s %s %s %s %s\n", people.tel, people.name, people.address, people.occupation, people.company, people.email);fclose(fp);printf("添加聯(lián)系人成功!\n");return 1; }//增加聯(lián)系人到鏈表 int add_people(struct People people) {struct People_List *plist = NULL;//加入手機(jī)號(hào)碼對(duì)應(yīng)的鏈表庫struct People_Node *pnode = (struct People_Node *)malloc(sizeof(struct People_Node));if (!pnode){fprintf(stderr, "申請(qǐng)內(nèi)存失敗:%s\n", strerror(errno));return 0;}pnode->people = people;pnode->pre = NULL;pnode->next = NULL;int key = get_key(people.tel);plist = g_tel[key];if ((plist->len++) == 0) //鏈表為空時(shí){plist->head = pnode;plist->tail = pnode;} else {pnode->pre = plist->tail;plist->tail->next = pnode;plist->tail = pnode;}return 1; }//刪除聯(lián)系人 int del_con() { printf("請(qǐng)輸入要?jiǎng)h除的聯(lián)系人的手機(jī)號(hào)碼\n");struct People people;int r = scanf("%s", &people.tel);clean_stdin();if(check_return_main(people.tel))return RETURN_MAIN_FLAG;if (r == 0) {printf("輸入手機(jī)號(hào)碼格式不正確--------r = %d\n", r);return 0;}r = check_people(people);if (r == -1)return 0;return del_people(people); }//從鏈表中刪除聯(lián)系人 int del_people(struct People people) {int key = get_key(people.tel);struct People_Node *pnode = g_tel[key]->head;int find = 0;while(pnode){if (strcmp(people.tel, pnode->people.tel) == 0){find = 1;break;} pnode = pnode->next;}if (!find){printf("沒有找到要?jiǎng)h除的聯(lián)系人\n");return 0;}g_tel[key]->len = g_tel[key]->len - 1;if (pnode == g_tel[key]->head){g_tel[key]->head = pnode->next;if (g_tel[key]->len == 0)g_tel[key]->tail = NULL;else pnode->next->pre = NULL;} else if (pnode == g_tel[key]->tail) {g_tel[key]->tail = pnode->pre;pnode->pre->next = NULL;} else {pnode->pre->next = pnode->next;pnode->next->pre = pnode->pre;}free(pnode);//print_people_list();save_people_list();printf("刪除聯(lián)系人成功!\n");return 1; }//修改聯(lián)系人信息 int mod_con() {printf("請(qǐng)輸入需要修改聯(lián)系人的 手機(jī)號(hào)碼 姓名 聯(lián)系地址 職業(yè) 公司 郵箱\n");struct People people;scanf("%s", people.tel);if(check_return_main(people.tel)){clean_stdin();return RETURN_MAIN_FLAG;}scanf("%s %s %s %s %s", people.name, people.address, people.occupation, people.company, people.email);clean_stdin();if(check_return_main(people.tel))return RETURN_MAIN_FLAG;int r = check_people(people);if (r == -1)return 0;return mod_people(people); }//從鏈表中修改聯(lián)系人信息 int mod_people(struct People people) {int key = get_key(people.tel);struct People_Node *pnode = g_tel[key]->head;int find = 0;while(pnode){if (strcmp(people.tel, pnode->people.tel) == 0){find = 1;break;} pnode = pnode->next;}if (!find){printf("沒有找到要修改的聯(lián)系人\n");return 0;}pnode->people = people;//print_people_list();save_people_list();printf("修改聯(lián)系人成功!\n");return 1; }//查找聯(lián)系人 int find_con() {printf("請(qǐng)輸入要查找的聯(lián)系人的手機(jī)號(hào)碼\n");struct People people;int r = scanf("%s", &people.tel);clean_stdin();if(check_return_main(people.tel))return RETURN_MAIN_FLAG;if (r == 0) {printf("輸入手機(jī)號(hào)碼格式不正確\n");return 0;}r = check_people(people);if (r == -1)return 0;struct People_Node *pnode = find_people(people);if (!pnode){printf("沒有查找到手機(jī)號(hào)碼對(duì)應(yīng)的聯(lián)系人!\n");return 0;}printf(PEOPLE_INFO);print_people(&pnode->people);return 1; }//從鏈表中查找聯(lián)系人 struct People_Node *find_people(struct People people) {int key = get_key(people.tel);struct People_Node *pnode = g_tel[key]->head;while(pnode){if (strcmp(people.tel, pnode->people.tel) == 0){return pnode;} pnode = pnode->next;}return NULL; }//排序通訊錄 void sort_con() {sort_people_list(); }//按照手機(jī)號(hào)碼從小到大排序通訊錄并輸出到屏幕 void sort_people_list() {// printf("---------------before sort---------------\n");// print_people_list();struct People_List *plist = NULL;struct People_Node *pnode = NULL;struct People_Node *pnext = NULL;struct People_Node *pmin = NULL;struct People ptemp;int i = 0;for (i = 0; i < COUNT_TEL_MAX; i++){plist = g_tel[i];pnode = plist->head;while (pnode){pmin = pnode;//ptemp = pnode;pnext = pnode->next;while(pnext){if (atof(pmin->people.tel) > atof(pnext->people.tel))pmin = pnext;pnext = pnext->next;}if (pmin != pnode) //當(dāng)前節(jié)點(diǎn)不是最小節(jié)點(diǎn){ptemp = pnode->people;pnode->people = pmin->people;pmin->people = ptemp;}pnode = pnode->next;} }// printf("---------------after sort---------------\n");// print_people_list();printf("排序成功!\n"); }//打印通訊錄 void print_con() {printf("----------開始打印通訊錄----------\n");print_people_list();printf("----------打印通訊錄完畢----------\n"); }//打印通訊錄列表 void print_people_list() {int i = 0;struct People_Node *pnode;printf(PEOPLE_INFO);for (i = 0; i < COUNT_TEL_MAX; i++){pnode = g_tel[i]->head;while (pnode){//printf("key = %d ", i);print_people(&(pnode->people));pnode = pnode->next;}} }//打印聯(lián)系人信息 void print_people(struct People *p) {printf("%s\t%s\t%s\t%s\t%s\t%s\n", p->tel, p->name, p->address, p->occupation, p->company, p->email); }//清空通訊錄 int clean_con() {printf("是否清空通訊錄:y or n\n");char op[100];int r = scanf("%s", &op);clean_stdin();if (check_return_main(op) || strcmp(op, "n") == 0)return RETURN_MAIN_FLAG;if (strcmp(op, "y") != 0){printf("輸入:y or n 錯(cuò)誤!\n");return 0;}printf("----------開始清空通訊錄,開始釋放內(nèi)存數(shù)據(jù)----------\n");int i = 0;struct People_List *plist;struct People_Node *pcur = NULL;struct People_Node *pnext = NULL;for (i = 0; i < COUNT_TEL_MAX; i++){plist = g_tel[i];pcur = plist->head;while (pcur){pnext = pcur->next;//printf("free node tel = %s\n", pcur->people.tel);free(pcur);pcur = pnext;}plist->len = 0;plist->head = NULL;plist->tail = NULL;}save_people_list();printf("----------釋放內(nèi)存數(shù)據(jù)成功,清空通訊錄成功----------\n");return 1; }//退出通訊錄 void exit_con() {printf("----------開始保存通訊錄----------\n");save_people_list();printf("----------開始退出通訊錄,開始釋放內(nèi)存數(shù)據(jù)----------\n");int i = 0;struct People_List *plist;struct People_Node *pcur = NULL;struct People_Node *pnext = NULL;for (i = 0; i < COUNT_TEL_MAX; i++){plist = g_tel[i];pcur = plist->head;while (pcur){pnext = pcur->next;//printf("free node tel = %s\n", pcur->people.tel);free(pcur);pcur = pnext;}free(plist);}printf("----------釋放內(nèi)存數(shù)據(jù)成功,退出通訊錄成功----------\n");exit(1); }//清空無效的輸入 void clean_stdin() {char s;do{scanf("%c", &s);}while(s != '\n'); }//是否返回主菜單 int check_return_main(const char *str) {if (strcmp(str, RETURN_MAIN) == 0)return 1;return 0; }//返回手機(jī)號(hào)碼對(duì)應(yīng)的數(shù)組數(shù)組下標(biāo) int get_key(const char *tel) {char str[5];memcpy(str, tel, 4);int key = atoi(str);if (key > COUNT_TEL_MAX || key < 0)return -1;return key; }//檢測(cè)str是否為全數(shù)字 int is_digit_string(const char *str) {if (*str == '\0')return 0;while (*str != '\0'){if(!isdigit(*str++))return 0;}return 1; }// 檢測(cè)輸入的格式比如手機(jī)號(hào)碼格式是否正確等 int check_people(struct People people) {if (!is_digit_string(people.tel)) //是否是數(shù)字{printf("手機(jī)號(hào)碼格式不全是數(shù)字\n");return -1;}if (strlen(people.tel) < 4) //手機(jī)號(hào)碼是否過短{printf("手機(jī)號(hào)碼不能低于4位\n");return -1;}return 0; }//字符串拷貝剔除掉換行符\n void strcpy_not_n(char *des, char *src) {while (*src != '\0'){if (*src != '\n')*des = *src;else*des = '\0';src++;des++;} }//保持?jǐn)?shù)據(jù)到txt文件 void save_people_list() {FILE *fp = fopen(CON_TXT_PATH, "w"); /*打開一個(gè)文本文件,允許讀寫文件。如果文件不存在,則會(huì)創(chuàng)建一個(gè)新文件。讀取會(huì)從文件的開頭開始,寫入則只能是追加模式。*/if (!fp){fprintf(stderr, "打開%s文件錯(cuò)誤:%s\n", CON_TXT_PATH, strerror(errno));return ;}int i = 0;fprintf(fp, "手機(jī)號(hào)碼 姓名 聯(lián)系地址 職業(yè) 公司 郵箱\n");int interval = 3;char dest[1024] = "";char str[256] = "";int record = 0;struct People_Node *pnode = NULL;for (i = 0; i < COUNT_TEL_MAX; i++){pnode = g_tel[i]->head;while (pnode){ record = record + 1;sprintf(str, "%s %s %s %s %s %s\n", pnode->people.tel, pnode->people.name, pnode->people.address, pnode->people.occupation, pnode->people.company, pnode->people.email);strcat(dest, str);strcpy(str, "");if (record%interval == 0){fprintf(fp, dest);record = 0;strcpy(dest, "");}pnode = pnode->next;}}if (strcmp(dest, "") != 0)fprintf(fp, dest);fclose(fp); }//測(cè)試命令 int test_cmd() {printf("1:隨機(jī)增加n個(gè)聯(lián)系人,例如:1 1000 就是隨機(jī)增加1000個(gè)聯(lián)系人\n");char cmd1[20];int cmd2 = 0;scanf("%s", &cmd1);if(check_return_main(cmd1)){clean_stdin();return RETURN_MAIN_FLAG;}scanf("%d", &cmd2);clean_stdin();if (atoi(cmd1) != 1 || cmd2 <= 0){printf("輸入的測(cè)試命令格式不對(duì)\n");return 0;}char *family_names[10] = {"李一一","歐陽二","張三","李四","王五","易六","高七","宋八","唐九","楊十"};char *address[10] = {"廣州","上海","天津","北京","武漢","拉薩","新疆","河北","河南","廣西"};char *occupation[10] = {"老師","快遞員","工程師","個(gè)體","醫(yī)生","護(hù)士","培訓(xùn)師","務(wù)農(nóng)","健身教練","CEO"};char *company[10] = {"滕芬網(wǎng)絡(luò)","云上科技","佳佳超市","水煮魚餐飲","來一杯奶茶","好多好吃","小蔥蔬菜","水果批發(fā)商","酸菜魚特產(chǎn)","小云直播"};char *email[10] = {"111@163.com","222@qq.com","333@qq.com","444@163.com","555@163.com","666@163.com","777@163.com","888@qq.com","999@qq.com","123@163.com"};struct People people;int i = 0, j = 0;int temp;char tel[12] = "1";char str[2];for (i = 0; i < cmd2; i ++){for (j = 0; j < 10; j++){temp = (int)rand()%10;//printf("%d\n", temp);itoa_my(temp, str, 10);strcat(tel, str);strcpy(str, "");}strcpy(people.tel, tel);strcpy(people.name, family_names[(int)rand()%10]);strcpy(people.address, address[(int)rand()%10]);strcpy(people.occupation, occupation[(int)rand()%10]);strcpy(people.company, company[(int)rand()%10]);strcpy(people.email, email[(int)rand()%10]);//printf("%s\n", tel);add_people(people);strcpy(tel, "1");}save_people_list();printf("新增聯(lián)系人成功\n");return 1; }//數(shù)字轉(zhuǎn)字符串函數(shù) char *itoa_my(int value, char *str, int radix) {static char dig_my[] ="0123456789""abcdefghijklmnopqrstuvwxyz";int n = 0, neg = 0;unsigned int v;char* p, *q;char c;/* 負(fù)數(shù):十進(jìn)制直接在前面加負(fù)號(hào),其它進(jìn)制用補(bǔ)碼 */if (radix == 10 && value < 0) {v = -value;neg = 1;}else{v = value;}/* 其它進(jìn)制的負(fù)數(shù)轉(zhuǎn)為unsigned int類型,即取了補(bǔ)碼 */do {str[n++] = dig_my[v%radix];v /= radix;} while (v);if (neg)str[n++] = '-';str[n] = '\0';/* 字符串反轉(zhuǎn) */for (p = str, q = p + (n-1); p < q; ++p, --q)c = *p, *p = *q, *q = c;return str; }七、效果截圖
首頁
測(cè)試命令增加10個(gè)聯(lián)系人,并打印通訊錄
退出通訊錄
總結(jié)
以上是生活随笔為你收集整理的C语言 通讯录管理系统(链表,手机号码分段存储,txt文件存取)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: PLECS专家的教诲
- 下一篇: mysql group_concat拼接