目錄
1. 前言:
2.通訊錄項目的創建
3. 通訊錄的實現
3.1 通訊錄的初始化
3.2 通訊錄的銷毀
3.3 通訊錄添加數據
3.4 通訊錄查找數據
3.5 通訊錄展示數據?
?3.6 通訊錄刪除數據
?3.7 通訊錄修改數據
?4. 通訊錄完整代碼
4.1 test.c
4.2 SeqList.h
4.3 SeqList.c
?4.4 Contact.h
4.5 Contact.c
1. 前言:
想必大家也都用過手機上面的通訊錄吧,手機上面的通訊錄有著許多的功能,可以新建聯系人,刪除聯系人,查找聯系人,修改聯系人等等一系列的功能,我們其實也可以使用數據結構中的順序表來模擬實現一下這樣功能。
本章主要講述利用順序表來實現一個簡單的通訊錄項目
2.通訊錄項目的創建
通訊錄項目在以順序表的結構上面會多增加兩個文件
通訊錄頭文件Contact.h和通訊錄源文件Contact.h
我們之前使用順序表數據是用的整型,但是我們想要實現一個通訊錄,那么單單一個整型的數據肯定是不能完成的,通訊錄里面的數據要有聯系人姓名,聯系人性別,聯系人年齡,聯系人電話,聯系人住址,一想到需要這么多數據,我們不免就會用到結構體了。
Contact.h 創建結構體
//這里我們用#define來定義大小,方便后續修改
#define NAME_MAX 20
#define GENDER_MAX 20
#define TEL_MAX 20
#define ADDR_MAX 100typedef struct SeqList son;//這里我們把順序表重新命名為son//創建一個存放聯系人數據的結構體
typedef struct personinfo
{char name[NAME_MAX];//姓名char gender[GENDER_MAX];//性別int age;//年齡char tel[TEL_MAX];//電話char addr[ADDR_MAX];//住址
}person;
我們在SeqList.h里面包含通訊錄頭文件,并把int類型修改為struct類型
這里我們的test.c里面也包含通訊錄頭文件
?這里我們把int類型修改成struct類型之后,在SeqList.c里面我們的查找方法和打印方法就會報錯,這時我們只需要注釋掉這兩個方法就好了。
最后在Contact.c里面包含通訊錄頭文件和順序表頭文件
3. 通訊錄的實現
3.1 通訊錄的初始化
思路:
我們在之前寫順序表的時候,寫過初始化的方法,我們可以直接調用這個方法為我們的通訊錄進行初始化
Contact.c
void ConInit(son* con)
{assert(con);//判斷con是否為空指針//這里我們在順序表里面就寫過初始化的方法,我們直接調用,這個就是初始化方法的復用SLInit(con);
}
通訊錄初始化的測試
3.2 通訊錄的銷毀
思路:
我們寫順序表時也寫過銷毀方法,我們這里直接調用方法就可以了
?Contact.c
void ConDestroy(son* con)
{assert(con);//判斷con是否為空指針SLDestroy(con);//順序表銷毀方法復用
}
通訊錄的銷毀測試
3.3 通訊錄添加數據
思路:
在我們對通訊錄添加數據之前,我們需要檢查一下空間大小是否足夠,不夠申請空間,調用我們之前順序表的空間檢查,增容函數,然后,我們創建一個結構體,把我們想要添加的聯系人數據都寫上,最后我們在寫順序表時有三種插入方法,我們這里選擇尾插,調用尾插方法,將創建的結構體變量傳過去,這樣通訊錄添加數據就完成了
Contact.h
void ConAdd(son* con)
{assert(con);//判斷con是否為空指針//在我們添加聯系人數據之前,我們需要檢查空間大小SLCheckCapacity(con);//這里我們創建一個結構體變量person p;//我們在這里將我們添加聯系人的數據寫入到p結構體里面//這里姓名,性別,電話,住址都是數組,數組名是首元素的地址,所以不需要取地址符號printf("請輸入你要添加聯系人的姓名\n");scanf("%s", p.name);printf("請輸入你要添加聯系人的性別\n");scanf("%s", p.gender);printf("請輸入你要添加聯系人的年齡\n");scanf("%d", &(p.age));//age是整型,需要取地址printf("請輸入你要添加聯系人的電話\n");scanf("%s", p.tel);printf("請輸入你要添加聯系人的住址\n");scanf("%s", p.addr);//在這里我們寫了3中插入數據的方法,隨便調用一種即可,我們選擇尾插printf("聯系人新建成功!\n");SLPushBack(con, p);//我們將p結構體尾插進去
}
通訊錄添加數據測試
3.4 通訊錄查找數據
思路:
我們一般想要在通訊錄里面查找聯系人一般直接就是查找聯系人的姓名,這里我們也是這樣思考的,我們直接創建一個字符數組來接收要查找的聯系人姓名,然后再通訊錄里面利用循環的方法進行查找,然后找到聯系人了,我們就把它的數據都打印出來,這樣通訊錄查找數據就完成了。
Contact.c
int Confind(son* con,char name[])
{int i = 0;//循環查找for (i = 0; i < con->size; i++){if (strcmp(con->arr[i].name,name) == 0){return i;}}return -1;
}
void ConFind(son* con)
{assert(con);//判斷con是否為空指針//在這里我們創建一個字符數組用來接收輸入要查找的聯系人姓名char name[NAME_MAX];printf("請輸入你要查找的聯系人姓名\n");scanf("%s",name);//寫一個查找函數,在通訊錄里面循環查找int find =Confind(con,name);//查找到了返回下標,如果沒有查找到返回不是下標的數if (find < 0){printf("你要查找的聯系人不存在!\n");}else{ //當我們查找到了,就把它打印出來printf("姓名 性別 年齡 電話 住址\n");printf("%4s %4s %4d %4s %4s\n",con->arr[find].name,con->arr[find].gender,con->arr[find].age,con->arr[find].tel,con->arr[find].addr);}
}
?通訊錄查找數據測試:
3.5 通訊錄展示數據?
思路:
我們直接利用循環來打印通訊里里面的所有聯系人數據
Contact.c
void ConShow(son* con)
{assert(con);//判斷con是否為空指針printf("姓名 性別 年齡 電話 住址\n");int i = 0;for (i = 0; i < con->size; i++){printf("%4s %4s %4d %4s %4s\n",con->arr[i].name,con->arr[i].gender,con->arr[i].age,con->arr[i].tel,con->arr[i].addr);}
}
通訊錄展示數據測試
?3.6 通訊錄刪除數據
思路:
這個刪除數據,首先我們肯定要考慮到通過聯系人姓名進行刪除聯系人數據,我們要先創建一個字符數據來接收我們要刪除的聯系人姓名,然后利用前面寫過的查找函數,來判斷聯系人是否在通訊錄里面,最后,我們利用在前面順序表里面寫過的指定位置刪除的方法進行刪除,這樣通訊錄刪除數據就完成了
Contact.c
void ConDel(son* con)
{assert(con);//判斷con是否為空指針char name[NAME_MAX];//創建變量來接收要刪除的聯系人姓名printf("請輸入你要刪除的聯系人姓名\n");scanf("%s", name);//這里先調用一下查找函數,看看聯系人是否存在int find = Confind(con,name);if (find < 0){printf("你要刪除的聯系人不存在\n");}else{printf("聯系人刪除成功!\n");//這里我們在前面順序表里面寫過在指定位置刪除,進行復用SLEarse(con,find);}
}
通訊錄刪除數據測試
?
?3.7 通訊錄修改數據
思路:
這里,我們是要對在通訊錄里面的聯系人數據進行修改,那我們肯定先查找要修改的聯系人姓名在不在通訊錄里面,利用查找函數,如果存在,直接進行修改
Contact.
void ConModify(son* con)
{assert(con);//判斷con是否為空指針char name[NAME_MAX];//創建變量來接收要修改的聯系人姓名printf("請輸入你要修改的聯系人姓名\n");scanf("%s",name);//這里先調用一下查找函數,看看聯系人是否存在int find = Confind(con, name);if (find < 0){printf("你要修改的聯系人不存在\n");}else{ //我們直接在這里進行修改printf("請輸入你要新建聯系人的姓名\n");scanf("%s", con->arr[find].name);printf("請輸入你要新建聯系人的性別\n");scanf("%s", con->arr[find].gender);printf("請輸入你要新建聯系人的年齡\n");scanf("%d", &(con->arr[find].age));//age是整型,需要取地址printf("請輸入你要新建聯系人的電話\n");scanf("%s", con->arr[find].tel);printf("請輸入你要新建聯系人的住址\n");scanf("%s", con->arr[find].addr);}printf("聯系人修改成功!\n");
}
通訊錄修改數據測試
?
?4. 通訊錄完整代碼
4.1 test.c
#include"SeqList.h"//包含順序表頭文件
#include"Contact.h"//包含通訊錄頭文件void menu()
{printf("----------通訊錄----------\n");printf("-------1.新建聯系人-------\n");printf("-------2.刪除聯系人-------\n");printf("-------3.展示聯系人-------\n");printf("-------4.查找聯系人-------\n");printf("-------5.修改聯系人-------\n");printf("-------0.退出通訊錄-------\n");}
int main()
{int input = 0;son con;ConInit(&con);do{menu();printf("請選擇你的操作!\n");scanf("%d", &input);switch (input){case 1:ConAdd(&con);break;case 2:ConDel(&con);break;case 3:ConShow(&con);break;case 4:ConFind(&con);break;case 5:ConModify(&con);break;default:printf("選擇錯誤,請重新選擇!\n");break;}} while (input);return 0;
}
4.2 SeqList.h
#include"Contact.h"//下面是需要使用到的庫函數的頭文件
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
#include<string.h>//typedef int SLData;//類型重命名,為了方便后續替換類型
//我們把int類型替換成strcut 類型
typedef person SLData;typedef struct SeqList //類型重命名
{SLData *arr;//定長數組int size;//順序表當前有效的數據個數int capacity;//容量大小
}sl;//順序表增容
void SLCheckCapacity(sl* ps);
//順序表初始化
void SLInit(sl* ps);
//順序表打印
void SLPaint(sl* ps);
//順序表尾插
void SLPushBack(sl* ps, SLData x);
//順序表頭插
void SLPushFront(sl* ps, SLData x);
//順序表尾刪
void SLPopBack(sl* ps);
//順序表頭刪
void SLPopFront(sl* ps);
//順序表指定位置之前插入
void SLInsert(sl* ps, int pos, SLData x);
//順序表指定位置刪除
void SLEarse(sl* ps, int pos);
//順序表修改指定位置數據
void SLModify(sl* ps,int pos, SLData x);
//順序表數據查找
int SLFind(sl* ps, SLData x);
//順序表銷毀
void SLDestroy(sl* ps);
4.3 SeqList.c
#include"SeqList.h"//包含順序表的頭文件void SLInit(sl* ps)
{assert(ps);//判斷ps是否為空指針//這里我們不知道這個順序表需求的大小ps->arr = NULL;//我們就先把指針置為空ps->size = ps->capacity = 0;//這里有效數據個數和可存儲數據個數都置為0;
}void SLDestroy(sl* ps)
{assert(ps);//判斷ps是否為空指針free(ps->arr);//釋放動態內存開辟的空間ps->arr = NULL;//防止ps->arr變成野指針ps->size = ps->capacity = 0;//將有效數據和空間大小置0
}void SLCheckCapacity(sl* ps)
{assert(ps);//判斷ps是否為空指針if (ps->size == ps->capacity)//判斷有效數據個數和可存儲數據個數,這里如果有效數據個數==可存儲數據個數,說明空間不夠了,需要增容{//這里利用三目操作符,判斷可用數據個數的大小,并創建相同變量來接收int tmp = ps->capacity == 0 ? 4 : 2 * ps->capacity;//這里我們用于同類型指針來接收realloc開辟空間返回的地址SLData* ptr = (SLData*)realloc(ps->arr, tmp * sizeof(SLData));//判斷是否開辟成功if (ptr == NULL){//開辟失敗,報錯perror("realloc");exit(1);//退出程序}//開辟成功,接收ps->arr = ptr;ps->capacity = tmp;//接收可用空間數據}
}void SLPushBack(sl* ps, SLData x)
{assert(ps);//斷言ps是否為空指針//檢查空間大小,不夠進行增容SLCheckCapacity(ps);//這里我們在size位置進行尾插,之后讓size++(后置++,先使用在++),用來記錄順序表中有效數據的個數ps->arr[ps->size++] = x;
}//void SLPaint(sl* ps)
//{
// assert(ps);//判斷ps是否為空指針
// int i = 0;
// //循環打印
// for (i = 0; i < ps->size; i++)
// {
// printf("%d ", ps->arr[i]);
// }
// //換行
// printf("\n");
//}void SLPushFront(sl* ps, SLData x)
{assert(ps);//判斷ps是否為空指針//判斷空間大小SLCheckCapacity(ps);int i = 0;//循環移動數據for (i = ps->size; i > 0; i--){ps->arr[i] = ps->arr[i - 1];//將前面的數據復制到后一位}//這里i == 0,跳出循環ps->arr[i] = x;//讓順序表有效數據個數++ps->size++;
}void SLPopBack(sl* ps)
{assert(ps);//判斷ps是否為空指針assert(ps->size);//判斷順序表里面的有效數據個數ps->size--;
}void SLPopFront(sl* ps)
{assert(ps);//判斷ps是否為空指針assert(ps->size);//判斷順序表里面的有效數據個數int i = 0;//循環移動for (i = 0; i < ps->size; i++){ps->arr[i] = ps->arr[i + 1];//將后面值賦值給前一位}ps->size--;
}void SLInsert(sl* ps, int pos, SLData x)
{assert(ps);//判斷ps是否為空指針assert(pos >= 0 && pos < ps->size);//判斷刪除數據的范圍SLCheckCapacity(ps);//判斷空間大小int i = 0;for (i = ps->size; i > pos; i--){ps->arr[i] = ps->arr[i - 1];//將數據整體往后移動一位}//i == pos 跳出循環ps->arr[i] = x;ps->size++;
}void SLEarse(sl* ps, int pos)
{assert(ps);//判斷ps是否為空指針assert(pos >= 0 && pos < ps->size);//判斷指定位置的范圍int i = 0;for (i = pos; i < ps->size; i++){ps->arr[i] = ps->arr[i + 1];//將指定位置之后的數據整體往前移動一位}ps->size--;
}void SLModify(sl* ps, int pos, SLData x)
{assert(ps);//判斷ps是否為空指針assert(pos >= 0 && pos < ps->size);//判斷指定位置是否合法ps->arr[pos] = x;
}
?4.4 Contact.h
//這里我們用#define來定義大小,方便后續修改
#define NAME_MAX 20
#define GENDER_MAX 20
#define TEL_MAX 20
#define ADDR_MAX 100typedef struct SeqList son;//這里我們把順序表重新命名為son//創建一個存放聯系人數據的結構體
typedef struct personinfo
{char name[NAME_MAX];//姓名char gender[GENDER_MAX];//性別int age;//年齡char tel[TEL_MAX];//電話char addr[ADDR_MAX];//住址
}person;//通訊錄初始化
void ConInit(son* con);
//通訊錄銷毀
void ConDestroy(son* con);
//通訊錄添加數據
void ConAdd(son* con);
//通訊錄查找數據
void ConFind(son* con);
//通訊錄展示數據
void ConShow(son* con);
//通訊錄刪除數據
void ConDel(son* con);
//通訊錄修改數據
void ConModify(son* con);
4.5 Contact.c
#include"Contact.h"
#include"SeqList.h"void ConInit(son* con)
{assert(con);//判斷con是否為空指針//這里我們在順序表里面就寫過初始化的方法,我們直接調用,這個就是初始化方法的復用SLInit(con);
}void ConDestroy(son* con)
{assert(con);//判斷con是否為空指針SLDestroy(con);//順序表銷毀方法復用
}void ConAdd(son* con)
{assert(con);//判斷con是否為空指針//在我們添加聯系人數據之前,我們需要檢查空間大小SLCheckCapacity(con);//這里我們創建一個結構體變量person p;//我們在這里將我們添加聯系人的數據寫入到p結構體里面//這里姓名,性別,電話,住址都是數組,數組名是首元素的地址,所以不需要取地址符號printf("請輸入你要添加聯系人的姓名\n");scanf("%s", p.name);printf("請輸入你要添加聯系人的性別\n");scanf("%s", p.gender);printf("請輸入你要添加聯系人的年齡\n");scanf("%d", &(p.age));//age是整型,需要取地址printf("請輸入你要添加聯系人的電話\n");scanf("%s", p.tel);printf("請輸入你要添加聯系人的住址\n");scanf("%s", p.addr);printf("聯系人新建成功!\n");printf("--------------------------\n");//在這里我們寫了3中插入數據的方法,隨便調用一種即可,我們選擇尾插SLPushBack(con, p);//我們將p結構體尾插進去
}int Confind(son* con,char name[])
{int i = 0;//循環查找for (i = 0; i < con->size; i++){if (strcmp(con->arr[i].name,name) == 0){return i;}}return -1;
}
void ConFind(son* con)
{assert(con);//判斷con是否為空指針//在這里我們創建一個字符數組用來接收輸入要查找的聯系人姓名char name[NAME_MAX];printf("請輸入你要查找的聯系人姓名\n");scanf("%s",name);//寫一個查找函數,在通訊錄里面循環查找int find =Confind(con,name);//查找到了返回下標,如果沒有查找到返回不是下標的數if (find < 0){printf("你要查找的聯系人不存在!\n");return;//提前返回}else{ //當我們查找到了,就把它打印出來printf("姓名 性別 年齡 電話 住址\n");printf("%4s %4s %4d %4s %4s\n",con->arr[find].name,con->arr[find].gender,con->arr[find].age,con->arr[find].tel,con->arr[find].addr);}
}void ConShow(son* con)
{assert(con);//判斷con是否為空指針printf("姓名 性別 年齡 電話 住址\n");int i = 0;for (i = 0; i < con->size; i++){printf("%4s %4s %4d %4s %4s\n",con->arr[i].name,con->arr[i].gender,con->arr[i].age,con->arr[i].tel,con->arr[i].addr);}
}void ConDel(son* con)
{assert(con);//判斷con是否為空指針char name[NAME_MAX];//創建變量來接收要刪除的聯系人姓名printf("請輸入你要刪除的聯系人姓名\n");scanf("%s", name);//這里先調用一下查找函數,看看聯系人是否存在int find = Confind(con,name);if (find < 0){printf("你要刪除的聯系人不存在\n");return;//提前返回}else{//這里我們在前面順序表里面寫過在指定位置刪除,進行復用printf("聯系人刪除成功!\n");SLEarse(con,find);}
}void ConModify(son* con)
{assert(con);//判斷con是否為空指針char name[NAME_MAX];//創建變量來接收要修改的聯系人姓名printf("請輸入你要修改的聯系人姓名\n");scanf("%s",name);//這里先調用一下查找函數,看看聯系人是否存在int find = Confind(con, name);if (find < 0){printf("你要修改的聯系人不存在\n");}else{ //我們直接在這里進行修改printf("請輸入你要新建聯系人的姓名\n");scanf("%s", con->arr[find].name);printf("請輸入你要新建聯系人的性別\n");scanf("%s", con->arr[find].gender);printf("請輸入你要新建聯系人的年齡\n");scanf("%d", &(con->arr[find].age));//age是整型,需要取地址printf("請輸入你要新建聯系人的電話\n");scanf("%s", con->arr[find].tel);printf("請輸入你要新建聯系人的住址\n");scanf("%s", con->arr[find].addr);}printf("聯系人修改成功!\n");
}