##資料結構課程設計-通訊錄管理系統
一,前言
自從上次C語言課設寫完后,這次資料結構課設就寫的游刃有余了,很快啊,不足三天就寫完了它(年輕人不講武德),如果你認真看過我之前寫的C語言課程設計-球隊管理系統,你就不難發現,這次資料結構的課設完全就是那篇直接改過來的,也就存盤結構變了一下,
C語言課設在這里-----球隊管理系統(C語言版)
廢話先不多說,直接上完整代碼:
二,直接上代碼
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<malloc.h>
typedef int ElemType;
typedef struct person{
char num[10];//編號
char name[10];//姓名
char sex[10];//性別
char phone[10];//電話
}personal;/*={};測驗*/
typedef struct node
{
person data;//資料域
struct node * next;//指標域
}ListNode,* LinkList;
LinkList InitList();
LinkList Create(LinkList head);
void List(LinkList head);//顯示所有記錄
void save(LinkList head);//保存到檔案
void Find(LinkList head);//按要求查找
int GetLength(LinkList head);//總記錄條數
void Add(LinkList head);//增加新的記錄
void Alter(LinkList head);//修改
void Delete(LinkList head); //洗掉
void Statis_sex(LinkList head);//性別個數
void Quit();//退出選單
void Menu(LinkList head);//選單
//Creat模塊已通過讀取檔案資訊實作
LinkList InitList()
{
LinkList head=(LinkList)malloc(sizeof(ListNode));//創立頭結點
if(head==NULL)
{
printf("空間分配無效!");
exit(-1);//退出程式
}
head->next=NULL;
return head;
}
LinkList Create(LinkList head)
{
person LM;//接受檔案資料
LinkList rear;
rear=head;
FILE *fp= fopen("file.txt","r");
if(fp==NULL)
{
printf("打開檔案失敗!");
return NULL;
}
while(fscanf(fp,"%s%s%s%s",LM.num,LM.name,LM.sex,LM.phone)!=EOF)//處理到檔案尾
{
LinkList s=(LinkList)malloc(sizeof(ListNode));
s->data=LM;
s->next=NULL;
rear->next=s;
rear=s;
}
fclose(fp);
return head;
}
void List(LinkList head) {
LinkList p;
p = head->next;
if (!p) //如果head指標為空說明鏈表為空
{
printf("\n鏈表為空!\n\n");
}
else
{
printf("\n通信錄:\n\n");
printf("編號 姓名 性別 電話 \n");
while (p) //回圈將各個節點值輸出
{
printf("%s\t%s\t%s\t%s\n",p->data.num,p->data.name,p->data.sex,p->data.phone);//列印
p = p->next;//此句放在列印后面,防止產生野指標
}
Statis_sex(head);
printf("\n回傳主選單\n");
system("pause");//頁面停留
Menu(head);
}
}
void save(LinkList head)
{
LinkList rear;
person LM;
rear=head->next;//跳過頭節點
FILE *fp;
int i;
if((fp=fopen("file.txt","wb"))==NULL)/*只打開或建立一個二進制檔案,只允許寫資料*/
{
printf("\n檔案不存在!\n");
}
while(rear)//處理到檔案尾
{
LM=rear->data;
fprintf(fp,"%s\t%s\t%s\t%s\n",LM.num,LM.name,LM.sex,LM.phone);
rear=rear->next;
}
fclose(fp);
}
void Find(LinkList head)
{
int Loop=0;
char name[10];
printf("請輸入要查詢聯系人的姓名[ ]\b\b\b\b\b\b");
scanf("%s",name);
LinkList rear=head->next;
while(rear)
{
if (strcmp(rear->data.name,name)==0)
{
printf("編號 姓名 性別 電話 \n");
printf("%s\t%s\t%s\t%s\n",rear->data.num,rear->data.name,rear->data.sex,rear->data.phone);
Loop=1;
}
rear=rear->next;
}
if(Loop==1)
{
printf("\n查詢聯系人成功!回傳選單\n");
system("pause");
Menu(head);
}
else
{
int n;
printf("無此聯系人!!!\n\n回傳選單(1) or 重新輸入(2)[ ]\b\b\b");
scanf("%d",&n);
printf("\n");
switch(n)
{
case 1:system("cls");Menu(head);break;
case 2:system("cls");Find(head);break;
}
}
}
int GetLength(LinkList head)
{
LinkList p=head->next;
int i=0;
while(p)
{
i++;
p=p->next;
}
return i;
}//獲取鏈表長度
void Add(LinkList head)
{
char c;
person LM;
LinkList p=head;
printf("請輸入新建聯系人的資訊\n\n編號 /姓名 /性別 /電話號碼:\n");
do
{
scanf("%s",LM.num);
scanf("%s",LM.name);
scanf("%s",LM.sex);
scanf("%s",LM.phone);
LinkList s=(LinkList)malloc(sizeof(ListNode));
s->data=LM;
s->next=NULL;
while(p->next)
{
p=p->next;
}
p->next=s;
save(head);
printf("是否繼續添加 y/n\n");
scanf(" %c",&c);
}while(c=='y'||c=='Y');
printf("\n回傳主選單\n");
system("pause");
Menu(head);
}
void Alter(LinkList head)
{
int loop=0;
int n;
char name[10];
printf("請輸入要查詢聯系人的姓名 [ ]\b\b\b\b\b\b");
scanf("%s",name);
printf("\n");
LinkList rear=head->next;
while(rear)
{
if (strcmp(rear->data.name,name)==0)
{
printf("請輸入要修改的內容:(1)編號 (2)姓名 (3)性別 (4)電話號碼 (5)全部資訊 [ ]\b\b");//printf("%s\t%s\t%s\t%s\n",rear->data.num,rear->data.name,rear->data.sex,rear->data.phone);
scanf("%d",&n);
printf("\n");
switch(n)
{
case 1: printf("請輸入修改后的編號:");scanf("%s",rear->data.num);break;
case 2: printf("請輸入修改后的姓名:");scanf("%s",rear->data.name);break;
case 3: printf("請輸入修改后的性別:");scanf("%s",rear->data.sex);break;
case 4: printf("請輸入修改后的電話號碼");scanf("%s",rear->data.phone);break;
case 5: printf("請輸入要修改聯系人的資訊: \n\n編號 姓名 性別 電話號碼:\n");
scanf("%s",rear->data.num);
scanf("%s",rear->data.name);
scanf("%s",rear->data.sex);
scanf("%s",rear->data.phone);break;
}
system("cls");
loop=1;
}
rear=rear->next;
}
if(loop==0)
{
printf("無此聯系人!!!\n\n回傳選單(1) or 重新輸入(2)[ ]\b\b\b");
scanf("%d",&n);
printf("\n");
switch(n)
{
case 1:system("cls");Menu(head);break;
case 2:system("cls");Alter(head);break;
}
}
save(head);
printf("\n修改成功!回傳選單\n");
system("pause");
Menu(head);
}
void Delete(LinkList head)
{
LinkList rear=head;//用來找要洗掉節點的前一節點
LinkList p=rear->next;//用來找要洗掉節點
char name[10];
int Loop=0,n;
printf("請輸入要洗掉聯系人的姓名:[ ]\b\b\b\b\b");
scanf("%s",name);
printf("\n");
while(p)
{
if(strcmp(p->data.name,name)==0)
{
rear->next=p->next;
free(p);
save(head);
Loop=1;
}
rear=p;
p=p->next;
}
if(Loop==1)
{
printf("\n洗掉聯系人成功!回傳選單\n");
system("pause");
Menu(head);
}
else
{
printf("無此聯系人!!!\n\n回傳選單(1) or 重新輸入(2)[ ]\b\b\b");
scanf("%d",&n);
printf("\n");
switch(n)
{
case 1:system("cls");Menu(head);break;
case 2:system("cls");Delete(head);break;
}
}
}
void Statis_sex(LinkList head)
{
int i=0;//記錄男性數目
int j=GetLength(head);//獲取總記錄數
LinkList rear=head->next;
char sex[10]="man";
while(rear)
{
if(strcmp(rear->data.sex,sex)==0)
i++;
rear=rear->next;
}
printf("\n通信錄中男性有 %d 人,有女性 %d 人,\n",i,j-i);
}
void Quit()
{
printf("\n\t ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★\n\n");
puts("\n");
puts("\t ┃ ┃");
puts("\t ┃ ┃");
puts("\t ┃ 感謝訪問通信錄管理系統!歡迎下次再來! ┃");
puts("\t ┃ ┃");
puts("\t ┃ ┃");
puts("\t ┃ 制作人:追足夢幻 ┃");
puts("\t ┃ 2020.7.3 ┃ ");
puts("\n ");
}
void Menu(LinkList head)
{
int n;
int choice=0;
do
{
system("cls");
printf("\n");
printf(" ---通訊錄管理系統---\n");
puts("\n");
printf(" 1/按姓名查詢聯系人資訊\n");
puts("\n");
printf(" 2/ 新建聯系人\n");
puts("\n");
printf(" 3/修改聯系人資訊\n");
puts("\n");
printf(" 4/ 洗掉聯系人資訊\n");
puts("\n");
printf(" 5/顯示所有聯系人資訊\n");
puts("\n");
printf(" 6/ 退出\n");
puts("\n");
printf(" 請選擇服務種類(1-6) : [ ]\b\b");
scanf("%d",&n);
if(n<1||n>6)
{
system("cls");
printf("選擇錯誤! 請重新選擇!\n");
system("pause");
choice=1;
}
else
{
break;
}
}while(choice==1);
switch(n)
{
case 1:system("cls");Find(head);break;//Find函式查詢
case 2:system("cls");Add(head);break;//Add函式新建聯系人
case 3:system("cls");Alter(head);break;//Alter修改聯系人資訊
case 4:system("cls");Delete(head);break;//Delete洗掉聯系人資訊
case 5:system("cls");List(head);break;//List顯示所有資訊
case 6:system("cls");Quit();break;//退出
}
}
int main()
{
LinkList head=InitList();
head=Create(head);
printf("\n資訊錄入成功!");
system("pause");
Menu(head);
}
三,設計報告
接下來是我課設報告中的設計部分內容
一、 引言(簡要說明設計題目的目的、意義、內容、主要任務等)
目的:構建通訊錄管理系統
意義:對于一個通信錄來說,要管理聯系人的資訊,包括編號,姓名,性別,電話,開發其系統主要為了幫助用戶提高通訊錄有管理效率,節約資源,提高資訊的精確度,
內容:九大模塊((主函式main(),選單函式Menu(),退出選單函式Quit(),創建資料函式Create(),增減資料函式Add(),查找函式Find(),修改函式Alter(),洗掉函式Delete(),顯示所有記錄函式List())加上四個輔助功能函式(初始化鏈表函式InitList(),保存函式save(),獲取鏈表長度函式GetLength(),統計性別函式Statis_sex()),
主要任務:
1,打開檔案讀取通信錄資訊
2,通過鏈式存盤接受檔案儲存資訊
3,對檔案資訊進行修改
4,保存修改并將資訊寫回檔案
二、 正文(課程設計的主要內容,包括實驗與觀測方法和結果、儀器設備、計算方法、編程原理、資料處理、設計說明與依據、加工整理和圖表、形成的論點和匯出的結論等,正文內容必須實事求是、客觀真切、準確完備、合乎邏輯、層次分明、語言流暢、結構嚴謹,符合各學科、專業的有關要求,)
主要內容:首先定義結構體,定義主函式,定義鏈表初始化函式,用主函式呼叫鏈表初始化函式構建鏈表 head,接下來的所有操作基于鏈表head,呼叫Create()函式以將檔案里面的資料寫出并賦給鏈表,鏈表里面每個結點的屬性為定義的結構體型別,然后呼叫Menu()函式以顯示歡迎界面和選單,
Menu函式通過switch條件陳述句呼叫各功能函式,選擇1時,
1, 可按姓名查詢聯系人;
2, 新建聯系人并保存到檔案;
3, 可以修改聯系人資訊并保存,修改聯系人資訊有包括了對聯系人編號,姓名,性別,電話號碼的分別修改,也可以同時對編號,姓名,性別,電話號碼修改;
4, 修改聯系人資訊;
5, 顯示所有聯系人資訊并停機男女個數;
6, 可以呼叫fail函式以顯示退出系統頁面,
總流程圖

每模塊都需有每個函式功能介紹,截圖,關鍵代碼等
1, 定義結構體
typedef struct person{
char num[10];//編號
char name[10];//姓名
char sex[10];//性別
char phone[10];//電話
}personal;
typedef struct node
{
person data;//資料域
struct node * next;//指標域
}ListNode,* LinkList;
2, 鏈表初始化
LinkList InitList()
{
LinkList head=(LinkList)malloc(sizeof(ListNode));//創立頭結點
if(head==NULL)
{
printf("空間分配無效!");
exit(-1);//退出程式
}
head->next=NULL;
return head;
}
3,主函式
int main()
{
LinkList head=InitList();
head=Create(head);
printf("\n資訊錄入成功!");
system("pause");
Menu(head);
}
首先初始化鏈表 head,然后或讀取檔案file.txt中的資料掛靠到鏈表 head=Create()
4, 讀取檔案資料到鏈表Create()
打開檔案 file.txt FILE *fp= fopen(“file.txt”,“r”); 然后從頭到尾處理檔案將每一個聯系人的資料寫入結構體變數,并掛靠到鏈表中
while(fscanf(fp,"%s%s%s%s",LM.num,LM.name,LM.sex,LM.phone)!=EOF)//處理到檔案尾
{
LinkList s=(LinkList)malloc(sizeof(ListNode));
s->data=LM;
s->next=NULL;
rear->next=s;
rear=s;
}
fclose(fp); 記得一定要關閉檔案
return head; 此時回傳的鏈表就是一個滿載資料的鏈表了,以后的操作都基于這條鏈表
5,選單函式Menu()
關鍵代碼: switch() 選擇陳述句
6,按姓名查找 Find()
遍歷鏈表知道找到要查詢聯系人姓名為止
關鍵代碼:
LinkList rear=head->next; //跳過第一個節點,因為第一個節點沒有存資料
while(rear)//回圈直到鏈表結束
{
if (strcmp(rear->data.name,name)==0) //字串比較函式,如果與輸入聯系人姓名相同則列印
{
printf("編號 姓名 性別 電話 \n");
printf("%s\t%s\t%s\t%s\n",rear->data.num,rear->data.name,rear->data.sex,rear->data.phone);
Loop=1;
}
rear=rear->next;//回圈進行下去的標志
}
7,新增加新的記錄Add()
定義結構體變數LM person LM;
將要新建的聯系人資訊賦給 LM;
再用尾插法將LM添加到鏈表head
關鍵代碼:
LinkList s=(LinkList)malloc(sizeof(ListNode));
s->data=LM;
s->next=NULL;
while(p->next)
{
p=p->next;
}//處理到最后防止產生野指標
p->next=s;//插入s
save(head);//記得保存修改
8,保存函式save
打開檔案只允許寫資料,檔案從頭處理到位,并將鏈表中的資料寫入檔案
關鍵代碼:
LinkList rear;
person LM;
rear=head->next;//跳過頭節點
FILE *fp;
int i;
if((fp=fopen("file.txt","wb"))==NULL)/*只打開或建立一個二進制檔案,只允許寫資料*/
{
printf("\n檔案不存在!\n");
}
while(rear)//處理到檔案尾
{
LM=rear->data;
fprintf(fp,"%s\t%s\t%s\t%s\n",LM.num,LM.name,LM.sex,LM.phone);
rear=rear->next;
}
fclose(fp);//處理完,一定要關閉檔案
9,修改資訊函式Alter()
遍歷鏈表資料,查找輸入的關鍵字(姓名),找到后鎖定這一結點并通過一個switch陳述句選擇要修改的資訊(編號,姓名,性別,電話號碼,全部資訊),選擇好后對應結點資料相應位置覆寫修改即可,
關鍵代碼:
while(rear)
{
if (strcmp(rear->data.name,name)==0)
{
printf("請輸入要修改的內容:(1)編號 (2)姓名 (3)性別 (4)電話號碼 (5)全部信 息 [ ]\b\b");
scanf("%d",&n);
printf("\n");
switch(n)
{
case 1: printf("請輸入修改后的編號:");scanf("%s",rear->data.num);break;
… …
scanf("%s",rear->data.num);
… …
}
}
rear=rear->next;
}
修改完save()保存
10,洗掉聯系人資訊函式Delete()
洗掉節點圖解:

遍歷鏈表,尋找關鍵字(姓名),分別用兩個指標(rear,p)指向關鍵字這一結點和它前一結點,
關鍵代碼:
while(p)
{
if(strcmp(p->data.name,name)==0)
{
rear->next=p->next;
free(p);//釋放洗掉的結點
save(head);
Loop=1;
}
rear=p;
p=p->next;
}
11,顯示所有資訊List()
從頭到尾遍歷鏈表,列印除頭結點的資料域的資料即可,
關鍵代碼:
LinkList p;
p = head->next;
{
printf("\n通信錄:\n\n");
printf("編號 姓名 性別 電話 \n");
while (p) //回圈將各個節點值輸出
{
printf("%s\t%s\t%s\t%s\n",p->data.num,p->data.name,p->data.sex,p->data.phone);//列印
p = p->next;//此句放在列印后面,防止產生野指標
}
Statis_sex(head);//顯示性別人數
12,統計性別人數Statis_sex()
先計算出鏈表總長度 j,再以某一性別作為關鍵字遍歷鏈表并計數統計這一性別的人數i,用j-i即是另一性別的人數,
關鍵代碼;
int i=0;//記錄男性數目
int j=GetLength(head);//獲取總記錄數
LinkList rear=head->next;
char sex[10]="man";
while(rear)
{
if(strcmp(rear->data.sex,sex)==0)
i++;
rear=rear->next;
}
printf("\n通信錄中男性有 %d 人,有女性 %d 人,\n",i,j-i);
13, 獲取鏈表長度GetLength()
從頭到尾遍歷鏈表并計數
關鍵代碼:
{
LinkList p=head->next;
int i=0;
while(p)
{
i++;
p=p->next;
}
return i;
}//獲取鏈表長度
關鍵步驟運行截圖









三、結論(應當準確、完整、明確精練;也可以在結論或討論中提出建議、設想、尚待解決問題等,
1、課程設計的特點
根據問題描述可知,需要解決問題并不復雜,整個問題只需要實作一個通訊錄管理系統功能,那就是在這個系統中實作對通信錄資訊的插入、洗掉、查詢、修改以及保存,但是,為了實作該功能,卻需要優秀的演算法和資料結構以保證實作的時間和空間效率,把聯系人資訊存盤在一個單鏈表中,利用指標實作對聯系人資訊的各項基本操作,
2、存在的不足
雖然設計的程式完成了題目描述所需要實作的功能,但是仍然存在不盡人意的地方,那就是可以再排序上面多設計幾個演算法,實作多角度排序,
3、心得體會
經過這次資料結構課程設計,我們不僅及時鞏固的了資料結構、演算法、以及軟體工程的知識,并對資料結構和演算法的配合對于程式時間和空間性能的影響以及軟體工程提供的開發流程和工具對于實作特定功能程式的重要意義,
當我們面對一個實際問題,應該迅速根據問題性質和特點抽象成特定的資料結構,當然每個問題都有可能能夠抽象成多種資料結構,每種資料結構適應于不同的演算法,例如,馬踏棋盤問題就可以采用廣度優先搜索或深度優先搜索來解決,因此此時就應該綜合考慮這樣的資料結構、演算法以及它們的空間和時間效率,然后從中選擇一個作為實作程式的基礎,
此外,對程式的測驗應該要仔細,根據模塊的特點和測驗階段,采用各種軟體測驗方法對程式進行測驗,確保各個模塊的正確性和完整性,最后集成起來測驗其是否正確和完整地實作了問題描述中要求的功能,
4、程式經驗教訓總結:
通過這個程式設計,我不僅提高了動手操作能力,對 C語言和資料結構有了更深的認識, 能夠更好地運用 C語言進行編程設計,同時在思維、看待問題的全面性等方面也有了很大的提高,不過由于時間、經驗不夠、對語言的掌握程度不深等問題,在這個系統設計還存在一些問題,比如記憶體設計還不夠完善,整個系統的流暢性等,希望可以在今后的設計上能夠解決這些問題,做的更好,
四、參考文獻
[1] 嚴蔚敏,吳偉民編著.《資料結構(C語言版)》.北京:清華大學出版社,1997.4. 18-39
[2] 菜鳥教程 網站https://www.runoob.com/
[3] CSDN 網站 https://www.csdn.net/
轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/233904.html
標籤:其他
