1 題目一 : 通訊錄
1.1問題描述
編寫一個通訊錄管理系統,以把所學數據結構知識應用到實際軟件開發中去。每條信息至包含 :姓名(NAME )街道(STREET)城市(CITY)郵編(EIP)國家(STATE)幾項
1.2.算法設計與分析
1.2.1設計思路分析
根據平常我們使用的通訊錄,我們可以抽象出一個人的一些基本信息,我們把它們封裝成一個結構體,代表一個我們實現的通訊錄中一個人的基本信息應該有哪些內容。然后我們再用一個這個結構體來定義一個結構體數組,就是我們通訊錄的存儲方式。
接下來,我們要實現一些相應的功能
初始化通訊錄:為了方便我們更好的對空間進行管理,擴容或者縮減,所以這里我們采用動態分配空間的方式開辟數組
添加聯系人:按順序輸入要添加的聯系人,輸入完畢后通訊錄當前數量加1
刪除聯系人:遍歷整個通訊錄,找到要刪除的聯系人后刪除,找到,則不刪除
修改聯系人:遍歷整個通訊錄,找到要修改的聯系人后刪除,找到,則不修改
查找聯系人:遍歷整個通訊錄,找到要查找的聯系人,找到打印,否則提示沒找到
打印通訊錄:遍歷整個通訊錄,依次打印聯系人
按姓名(字節序)排序:依照姓名在計算機中的字節序來為聯系人排序
清空所有聯系人:通信錄當前大小記為0
1.2.2設計程序流程圖(要求圖文并茂)
進入程序中,先初始化整個通訊錄,隨后進入菜單頁面,選擇相應功能,每次選擇功能并執行完后返回選擇頁面,只有當選擇0時才是退出程序。
1.2.3數據結構定義
typedef struct PeoInfo //定義個人信息
{char NAME[MAX_NAME]; //姓名int age; //年齡char CITY[MAX_ADDR]; //城市char sex[MAX_SEX]; //性別char STREET[MAX_STREET]; //街道char EIP[MAX_TELE]; //郵編char STATE[MAX_ADDR]; //國家
}PeInfo;typedef struct Contact //定義通訊錄
{PeInfo *array;int sz; int Capacity;
}Contact;
1.2.4算法的時間復雜度分析
初始化通訊錄:為了方便我們更好的對空間進行管理,擴容或者縮減,所以這里我們采用動態分配空間的方式開辟數組,時間復雜度為O(1)
添加聯系人:按順序輸入要添加的聯系人,輸入完畢后通訊錄當前數量加1.
直接按順序插入,時間復雜度為O(1)
刪除聯系人:遍歷整個通訊錄,找到要刪除的聯系人后刪除,找到,則不刪除,遍歷整個數組,時間復雜度為O(n)
修改聯系人:遍歷整個通訊錄,找到要修改的聯系人后刪除,找到,則不修改,遍歷整個數組,時間復雜度為O(n)
查找聯系人:遍歷整個通訊錄,找到要查找的聯系人,找到打印,否則提示沒找到,遍歷整個數組,時間復雜度為O(n)
打印通訊錄:遍歷整個通訊錄,依次打印聯系人,遍歷整個數組,時間復雜度為O(n)
按姓名(字節序)排序:依照姓名在計算機中的字節序來為聯系人排序,要遍歷整個數組,所以時間復雜度為O(n)
清空所有聯系人:直接將當前大小記為0,時間復雜度為O(1)
1.3源程序清單(帶注釋)
contact.h文件
#define MAX_NAME 20 //名字數組的大小
#define MAX_SEX 5 //性別的大小
#define MAX_TELE 12
#define MAX_ADDR 20 //城市和國家的大小
#define MAX 1000 //通訊錄得最大容量
#define MAX_STREET 20 //街道的大小#include<string.h>
#include<stdio.h>
#include<assert.h>
#include<windows.h>typedef struct PeoInfo //定義人的信息
{char NAME[MAX_NAME]; //姓名int age; //年齡char CITY[MAX_ADDR]; //城市char sex[MAX_SEX]; //性別char STREET[MAX_STREET]; //街道char EIP[MAX_TELE]; //郵編char STATE[MAX_ADDR]; //國家
}PeInfo;typedef struct Contact //定義通訊錄的信息
{PeInfo *array;int sz; int Capacity;
}Contact;enum Option //枚舉類型,方便調用功能函數
{EXIT,ADD,DEL,SEARCH,MODIFY,SHOW,SORT,DESTROY
};
//各類功能函數聲明
void InitContact(Contact* pcon);
void AddContact(Contact *pcon);
void ShowContact(const Contact* pcon);
void DelContact(Contact* pcon);
void SearchContact( const Contact* pcon);
void ModifyContact(Contact* pcon);
void SortContact(Contact* pcon);
void clearContact(Contact *pcon);
void Load(Contact* pcon);
void Save(Contact* pcon);
contact.c文件
#define _CRT_SECURE_NO_WARNINGS
#include "contact.h"void CheckFull(Contact* PhoneBook) //擴容函數
{if (PhoneBook->sz == PhoneBook->Capacity) //如果當前通訊錄的大小等于通訊錄的最大容量{printf("聯系人已達上限:%d/%d!\n", PhoneBook->sz, PhoneBook->Capacity); PeInfo*tmp = (PeInfo*)realloc(PhoneBook->array, sizeof(PeInfo)*(PhoneBook->Capacity + 1)); //重新申請空間,比原來大小多一位if (tmp != NULL) //提示申請空間成功{PhoneBook->array = tmp;PhoneBook->Capacity = PhoneBook->Capacity + 1;printf("擴容成功!\n");}else //如果指針為空,則申請空間失敗{printf("擴容失敗!\n");exit(1);}}
}//這里是每次程序運行時,加載儲存在本地txt文檔里的聯系人信息,如果沒有找到這個文檔,就在當前目錄下創建一個txt記事本:
void Load(Contact* pcon)
{FILE* fp = fopen("contact.txt", "r+"); //打開文件,如果沒有,則創建打開PeInfo temp = { 0 }; //建立一個結構體數組printf("加載聯系人的信息中\n"); if (fp == NULL) {printf("文件打開失敗!\n");}if (fread(&temp, sizeof(PeInfo), 1, fp)) //讀文件,如果無法讀入,則說明通訊錄已滿需要擴容{CheckFull(pcon); //調擴容函數pcon->array[pcon->sz] = temp; pcon->sz++;}fclose(fp);printf("數據讀取成功,加載了%d條信息\n", pcon->sz);
}
//這個函數是在程序即將結束前,將修改變動的聯系人信息的操作,儲存在本地文檔中
void Save(Contact* pcon)
{FILE* fp = fopen("contact.txt", "w+");if (fp == NULL){printf("文件打開失敗!\n");}else{for (int i = 0; i < pcon->sz; i++){/*if (pcon->array[i].NAME[0] != 0)//名字 年齡 性別 郵編 國家 街道 城市fprintf(fp, "%s %s %s %s %s %s %s\n",pcon->array[i].NAME,pcon->array[i].age,pcon->array[i].sex,pcon->array[i].EIP,pcon->array[i].STATE,pcon->array[i].STREET,pcon->array[i].CITY);*/fwrite(pcon->array, sizeof(PeInfo),1,fp); //寫入文件中}}fclose(fp);//printf("保存成功\n");
}void InitContact(Contact* pcon) //初始化函數
{pcon->sz = 0; //通訊錄當前大小置為0pcon->array = (PeInfo *)malloc(sizeof(PeInfo)* MAX);//動態開辟空間pcon->Capacity = MAX; //設置最大容量//memset(pcon->array, 0, sizeof(PeInfo)* MAX);
}void AddContact(Contact *pcon) //添加聯系人
{assert(pcon != NULL); //判斷指針是否為空if (pcon->sz == MAX){ //判斷通訊錄錄是否已滿printf("通訊錄已滿,無法添加.\n");}else{ //如果沒有滿則輸入數據printf("請輸入名字\n");scanf("%s", pcon->array[pcon->sz].NAME);printf("請輸入年齡\n");scanf("%d", &(pcon->array[pcon->sz].age));printf("請輸入性別\n");scanf("%s", pcon->array[pcon->sz].sex);printf("請輸入國家\n");scanf("%s", pcon->array[pcon->sz].STATE);printf("請輸入郵編\n");scanf("%s", pcon->array[pcon->sz].EIP);printf("請輸入城市\n");scanf("%s", pcon->array[pcon->sz].CITY);printf("請輸入街道\n");scanf("%s", pcon->array[pcon->sz].STREET);pcon->sz++;printf("錄入成功!\n");}void ShowContact(const Contact* pcon) //打印通訊錄
{assert(pcon != NULL);int i = 0;//名字 年齡 性別 郵編 國家 街道 城市printf("%10s\t%4s\t%4s\t%12s\t%15s\t%15s\t%15s\t\n","名字","年齡","性別","郵編","國家","城市","街道");for (i = 0; i < pcon->sz; i++){printf("%10s\t%4d\t%4s\t%12s\t%15s\t%15s\t%15s\t\n",pcon->array[i].NAME,pcon->array[i].age,pcon->array[i].sex,pcon->array[i].EIP,pcon->array[i].STATE,pcon->array[i].CITY,pcon->array[i].STREET);}}int FindEntry(Contact* pcon, char name[]) //查詢函數
{ //注意這里 第二個參數是name[] 千萬不能寫成name,要不然程序會崩潰assert(pcon != NULL);int i = 0;for (i = 0; i < pcon->sz; i++){ //遍歷整個數組,找到返回對應下標//找不到if (strcmp(pcon->array[i].NAME, name) == 0){return i ;}}//找到return -1; //沒找到,返回1
}
void DelContact(Contact* pcon) //刪除聯系人
{assert(pcon != NULL);//查找int i = 0;int j = 0;int pos = 0;char name[MAX_NAME] = { 0 };if (pcon->sz == 0){printf("通訊已空,無法刪除:\n");return;}printf("請輸入要刪除人的名字:\n");scanf("%s", name);//查找過程pos=FindEntry(pcon, name); //調查詢函數if (pos == -1){printf("刪除的人不存在\n");return;}//刪除for (j = pos; j < pcon->sz ; j++){ //找到后,依次往前搬移數組元素pcon->array[j] = pcon->array[j + 1];}pcon->sz--;printf("刪除成功\n");}
void SearchContact(const Contact* pcon) //查找聯系人
{assert(pcon != NULL);int pos = 0; char name[MAX_NAME] = { 0 };printf("請輸入要查找人的名字:\n");scanf("%s", name);pos = FindEntry(pcon, name); //調查詢函數if (pos == -1){printf("要查找人的信息不存在\n");}else //找到打印{printf("%10s\t%4s\t%4s\t%12s\t%15s\t%15s\t%15s\t\n", "名字", "年齡", "性別", "郵編", "國家", "城市", "街道");printf("%10s\t%4d\t%4s\t%12s\t%15s\t%15s\t%15s\t\n",pcon->array[pos].NAME,pcon->array[pos].age,pcon->array[pos].sex,pcon->array[pos].EIP,pcon->array[pos].STATE,pcon->array[pos].CITY,pcon->array[pos].STREET);}
}
void ModifyContact(Contact* pcon) //修改聯系人
{assert(pcon != NULL);int pos = 0;char name[MAX_NAME] = { 0 };printf("請輸入要修改人的名字:\n");scanf("%s", name);pos = FindEntry(pcon, name); //調查詢函數if (pos == -1){printf("要修改人的信息不存在\n");}else //找到則修改{printf("請輸入名字\n");scanf("%s", pcon->array[pos].NAME);printf("請輸入年齡\n");scanf("%d", &(pcon->array[pos].age));printf("請輸入性別\n");scanf("%s", pcon->array[pos].sex);printf("請輸入國家\n");scanf("%s", pcon->array[pos].STATE);printf("請輸入郵編\n");scanf("%s", pcon->array[pos].EIP);printf("請輸入城市\n");scanf("%s", pcon->array[pcon->sz].CITY);printf("請輸入街道\n");scanf("%s", pcon->array[pcon->sz].STREET);printf("修改成功\n");}
}
void SortContact(Contact* pcon) //按名字排序
{int i = 0;assert(pcon);//趟數for (i = 0; i < pcon->sz - 1; i++){int flag = 1; //表示已經排好序int j = 0;for (j = 0; j < pcon->sz - 1 - i; j++){if (strcmp(pcon->array[j].NAME, pcon->array[j + 1].NAME)>0) //比較兩個名字的字節序大小{PeInfo tmp = pcon->array[j];pcon->array[j] = pcon->array[j + 1];pcon->array[j + 1] = tmp;flag = 0; //表明之前無序}}if (flag == 1){break;}}printf("排序完成\n");
}
void clearContact(Contact *pcon) //刪除通訊錄中全部信息
{assert(pcon);int flag = 0;while (1){printf("請問你確定要刪除整個通訊錄嗎?\n");printf("1:刪除,0:不刪除\n");scanf("%d", &flag);if (flag == 1){pcon->sz = 0;printf("通訊錄已刪除\n");break;}else{break;}}
}
test.c文件
#define _CRT_SECURE_NO_WARNINGS
#include "contact.h" //包含頭文件#include<stdio.h>void menu(){ //菜單函數printf("****************************************\n");printf("***1 添加聯系人 2 刪除聯系人 **\n");printf("***3 查詢聯系人 4 修改聯系人 **\n");printf("***5 查看當前通訊錄 6 排序 **\n");printf("***7 刪除通訊錄 0 退出 **\n");printf("****************************************\n");}
void test(){ //主功能程序//創建通訊錄Contact con;//初始化InitContact(&con);Load(&con);int input = 0;do{ menu();printf("請選擇:\n");scanf("%d", &input);switch (input ){case ADD:AddContact(&con);break;case DEL:DelContact(&con);break;case SHOW :ShowContact(&con);break;case SEARCH:SearchContact(&con);break;case MODIFY :ModifyContact(&con);break;case SORT:SortContact(&con);break;case EXIT:printf("退出\n");break;case DESTROY:clearContact(&con);break;default:printf("選擇錯誤\n");break;}} while (input);Save(&con); //保存信息到文件中printf("保存成功\n");free(con.array);
}int main() //主函數
{test();system("pause");return 0;
}
1.4執行結果
1.添加聯系人
2刪除聯系人
3查詢聯系人
4修改聯系人
5查看當前通訊錄
6排序聯系人(按字節序排序)
7刪除通訊錄
0 退出
1.5存在問題分析
1.通訊錄中無法分辨同名同姓的情況。
2 通訊錄沒有一個圖形化界面,用戶需要手動輸入相關命令,無法實現鼠標點擊。
1.6結論
已經可以實現通訊錄的基本功能,但在數據處理和用戶操作上具有一些問題。