前言
😻这博客介绍通讯录的实现,也适用于实现信息管理系统什么的,实现方法是相同的。
😽代码的实现分模块化进行,(test.c)是主函数测试部分、(Contact.c)是各功能的具体实现、(Contact.h)放置各种声明;每个功能都单独封装函数实现。
1. 静态版本
1.1 实现要求
通讯录可以用来存储1000个人的信息,每个人的信息包括:姓名、性别、年龄、电话、住址;实现如下功能:
- 添加联系人信息
- 删除指定联系人信息
- 查找指定联系人信息
- 修改指定联系人信息
- 显示所有联系人信息
- 清空所有联系人
- 以名字排序所有联系人
1.2 实现思路
静态版本的通讯录首先声明一个结构体类型(struct Person)用来描述一个人的联系人的各种信息;
然后再声明一个结构体类型(struct Contact)用来描述通讯录,成员使用数组开辟1000个联系人的内存空间实现通讯录,数组的类型为struct Person
最后就是对存放联系人信息数组的一系列访问操作,封装各个函数实现各部分功能!
1.3 代码实现
test.c
#include"Contact.h" void menu() { printf("--------------------------------\n"); printf(" 1.add 2.del\n"); printf(" 3.search 4.modify\n"); printf(" 5.show 6.Clear\n"); printf(" 7.sort 0.exit\n"); printf("--------------------------------\n"); } int main() { //创建一个通讯录 Contact con; InitContact(&con); menu(); int input = 0; do { printf("请选择:>"); scanf("%d", &input); switch (input) { case ADD: AddContact(&con); break; case DEL: DelContact(&con); break; case SEARCH: SearchContact(&con); break; case MODIFY: ModifyContact(&con); break; case SHOW: ShowContact(&con); break; case CLEAR: ClearContact(&con); break; case SORT: SortContact(&con); break; case EXIT: printf("退出成功\n"); break; default: printf("选择错误,请重新输入\n"); break; } } while (input); return 0; }
Contact.h
#pragma once #include<stdio.h> #include<assert.h> #include<string.h> #include<stdlib.h> #define MAX_NAME 20 #define MAX_SEX 10 #define MAX_TELE 12 #define MAX_ADDR 30 #define MAX_DATA 1000 //枚举 enum Optint { EXIT, ADD, DEL, SEARCH, MODIFY, SHOW, CLEAR, SORT }; //定义一个人的信息 typedef struct Person { char name[MAX_NAME]; int age; char sex[MAX_SEX]; char tele[MAX_NAME]; char addr[MAX_ADDR]; }Person; //定义一个通讯录 typedef struct Contact { Person data[MAX_DATA];//存放人的信息 int count; }Contact; //初始化通讯录 void InitContact(Contact* pc); //添加联系人 void AddContact(Contact* pc); //删除联系人 void DelContact(Contact* pc); //搜索联系人 void SearchContact(Contact* pc); //修改联系人 void ModifyContact(Contact* pc); //显示联系人 void ShowContact(Contact* pc); //清空联系人 void ClearContact(Contact* pc); //排序联系人 void SortContact(Contact* pc);
Contact.c
#include"Contact.h" void InitContact(Contact* pc) { assert(pc); int i = 0; pc->count = 0; memset(pc->data, 0, sizeof(pc->data)); } void AddContact(Contact* pc) { assert(pc); if (pc->count == MAX_DATA) { printf("通讯录已满,无法添加\n"); return; } printf("请输入姓名:>"); scanf("%s", pc->data[pc->count].name); printf("请输入年龄:>"); scanf("%d", &pc->data[pc->count].age); printf("请输入性别:>"); scanf("%s", pc->data[pc->count].sex); printf("请输入电话:>"); scanf("%s", pc->data[pc->count].tele); printf("请输入地址:>"); scanf("%s", pc->data[pc->count].addr); pc->count++; printf("添加成功!\n"); } static int FindByName(Contact* pc, char name[]) { assert(pc && name); int i = 0; for (i = 0; i < pc->count; i++) { if (0 == strcmp(pc->data[i].name, name)) { return i; } } return -1; } void DelContact(Contact* pc) { assert(pc); char name[MAX_NAME] = { 0 }; if (0 == pc->count) { printf("通讯录为空,无法进行删除\n"); } else { printf("请输入要删除人的姓名:>"); scanf("%s", name); //查找 int pos = FindByName(pc, name); if (-1 == pos) { printf("要删除的人不存在\n"); return; } int i = 0; //删除,从后往前进行覆盖 for (i = pos; i < pc->count - 1; i++) { pc->data[i] = pc->data[i + 1]; } pc->count--; printf("删除成功\n"); } } void ShowContact(Contact* pc) { assert(pc); if (0 == pc->count) { printf("通讯录为空\n"); return; } int i = 0; printf("%-10s%-8s%-8s%-20s%-20s\n", "姓名", "年龄", "性别", "电话", "地址"); for (i = 0; i < pc->count; i++) { printf("%-10s%-8d%-8s%-20s%-20s\n", pc->data[i].name, pc->data[i].age, pc->data[i].sex, pc->data[i].tele, pc->data[i].addr); } } void SearchContact(Contact* pc) { assert(pc); char name[MAX_NAME] = { 0 }; printf("请输入要查找人的姓名:>"); scanf("%s", name); //查找 int pos = FindByName(pc, name); if (-1 == pos) { printf("要查找的人不存在\n"); return; } //输出 printf("%-10s%-8s%-8s%-20s%-20s\n", "姓名", "年龄", "性别", "电话", "地址"); printf("%-10s%-8d%-8s%-20s%-20s\n", pc->data[pos].name, pc->data[pos].age, pc->data[pos].sex, pc->data[pos].tele, pc->data[pos].addr); } void ModifyContact(Contact* pc) { assert(pc); char name[MAX_NAME] = { 0 }; printf("请输入要修改人的姓名:>"); scanf("%s", name); //查找 int pos = FindByName(pc, name); if (-1 == pos) { printf("要修改的联系人不存在\n"); return; } //修改 printf("请输入姓名:>"); scanf("%s", pc->data[pos].name); printf("请输入年龄:>"); scanf("%d", &pc->data[pos].age); printf("请输入性别:>"); scanf("%s", pc->data[pos].sex); printf("请输入电话:>"); scanf("%s", pc->data[pos].tele); printf("请输入地址:>"); scanf("%s", pc->data[pos].addr); printf("修改成功!\n"); } void ClearContact(Contact* pc) { assert(pc); InitContact(pc); printf("清空成功\n"); } int cmp_Per_by_name(const void* e1, const void* e2) { return strcmp(((Person*)e1)->name, ((Person*)e2)->name); } void SortContact(Contact* pc) { assert(pc); qsort(pc->data, pc->count, sizeof(Person), cmp_Per_by_name); ShowContact(pc); }
1.4 实现效果
2. 动态版本
2.1 实现要求
在静态版本的基础上做修改,储存联系人联系的空间不再是固定大小,实现根据内存中联系人的个数,内存空间可以动态增长分配!
2.2 实现思路
动态版的通讯录要用到动态内存分配的相关函数,与静态不同的是在声明描述通讯录的结构体时不再使用数组来开辟空空间,只需要给出struct Person* 类型的指针,
然后就可以在这个地址处使用calloc或malloc进行内存分配,可以先默认分配3个联系人的空间,当空间不够时再使用realloc进行扩容,可以设置为每次扩容增加2个联系人的空间;
在静态版本上稍做修改即可!
2.3 代码实现
test.c
#include"Contact.h" void menu() { printf("--------------------------------\n"); printf(" 1.add 2.del\n"); printf(" 3.search 4.modify\n"); printf(" 5.show 6.Clear\n"); printf(" 7.sort 0.exit\n"); printf("--------------------------------\n"); } int main() { //创建一个通讯录 Contact con; InitContact(&con); menu(); int input = 0; do { printf("请选择:>"); scanf("%d", &input); switch (input) { case ADD: AddContact(&con); break; case DEL: DelContact(&con); break; case SEARCH: SearchContact(&con); break; case MODIFY: ModifyContact(&con); break; case SHOW: ShowContact(&con); break; case CLEAR: ClearContact(&con); break; case SORT: SortContact(&con); break; case EXIT: DestroyContact(&con); printf("退出成功\n"); break; default: printf("选择错误,请重新输入\n"); break; } } while (input); return 0; }
Contact.h
#pragma once #include<stdio.h> #include<assert.h> #include<string.h> #include<stdlib.h> #include<string.h> #include<errno.h> #define DEFAULT_SZ 3 #define INCREASE_SZ 2 #define MAX_NAME 20 #define MAX_SEX 10 #define MAX_TELE 12 #define MAX_ADDR 30 #define MAX_DATA 1000 //枚举 enum Optint { EXIT, ADD, DEL, SEARCH, MODIFY, SHOW, CLEAR, SORT }; //定义一个人的信息 typedef struct Person { char name[MAX_NAME]; int age; char sex[MAX_SEX]; char tele[MAX_NAME]; char addr[MAX_ADDR]; }Person; //定义一个通讯录 静态版本 //typedef struct Contact //{ // Person data[MAX_DATA];//存放人的信息 // int count; // //}Contact; //动态版本 typedef struct Contact { Person* data;//存放人的信息,维护通讯录的指针 int count;//记录通讯录中实际联系人的个数 int capacity;//当前通讯录的容量 }Contact; //初始化通讯录 void InitContact(Contact* pc); //添加联系人 void AddContact(Contact* pc); //删除联系人 void DelContact(Contact* pc); //搜索联系人 void SearchContact(Contact* pc); //修改联系人 void ModifyContact(Contact* pc); //显示联系人 void ShowContact(Contact* pc); //清空联系人 void ClearContact(Contact* pc); //排序联系人 void SortContact(Contact* pc); //释放通讯录动态内存 void DestroyContact(Contact* pc);
Contact.c
#include"Contact.h" //静态版本 //void InitContact(Contact* pc) //{ // assert(pc); // int i = 0; // pc->count = 0; // memset(pc->data, 0, sizeof(pc->data)); //} //void AddContact(Contact* pc) //{ // assert(pc); // if (pc->count == MAX_DATA) // { // printf("通讯录已满,无法添加\n"); // return; // } // printf("请输入姓名:>"); // scanf("%s", pc->data[pc->count].name); // printf("请输入年龄:>"); // scanf("%d", &pc->data[pc->count].age); // printf("请输入性别:>"); // scanf("%s", pc->data[pc->count].sex); // printf("请输入电话:>"); // scanf("%s", pc->data[pc->count].tele); // printf("请输入地址:>"); // scanf("%s", pc->data[pc->count].addr); // pc->count++; // printf("添加成功!\n"); // //} //动态版本 void InitContact(Contact* pc) { assert(pc); pc->count = 0; pc->data = (Person*)calloc(DEFAULT_SZ, sizeof(Person)); if (NULL == pc->data) { printf("InitContact: :%s\n", strerror(errno)); return; } pc->capacity = DEFAULT_SZ; } void CheckCapacity(Contact* pc) { if (pc->capacity == pc->count) { Person* prt = (Person*)realloc(pc->data, (pc->capacity + INCREASE_SZ) * sizeof(Person)); if (NULL == prt) { printf("AddContact: :%s\n", strerror(errno)); return; } else { pc->data = prt; pc->capacity += INCREASE_SZ; printf("增容成功\n"); } } } void AddContact(Contact* pc) { assert(pc); //增容 CheckCapacity(pc); printf("请输入姓名:>"); scanf("%s", pc->data[pc->count].name); printf("请输入年龄:>"); scanf("%d", &pc->data[pc->count].age); printf("请输入性别:>"); scanf("%s", pc->data[pc->count].sex); printf("请输入电话:>"); scanf("%s", pc->data[pc->count].tele); printf("请输入地址:>"); scanf("%s", pc->data[pc->count].addr); pc->count++; printf("添加成功!\n"); } void DestroyContact(Contact* pc) { assert(pc); free(pc->data); pc->data = NULL; } static int FindByName(Contact* pc, char name[]) { assert(pc && name); int i = 0; for (i = 0; i < pc->count; i++) { if (0 == strcmp(pc->data[i].name, name)) { return i; } } return -1; } void DelContact(Contact* pc) { assert(pc); char name[MAX_NAME] = { 0 }; if (0 == pc->count) { printf("通讯录为空,无法进行删除\n"); } else { printf("请输入要删除人的姓名:>"); scanf("%s", name); //查找 int pos = FindByName(pc, name); if (-1 == pos) { printf("要删除的人不存在\n"); return; } int i = 0; //删除,从后往前进行覆盖 for (i = pos; i < pc->count - 1; i++) { pc->data[i] = pc->data[i + 1]; } pc->count--; printf("删除成功\n"); } } void ShowContact(Contact* pc) { assert(pc); if (0 == pc->count) { printf("通讯录为空\n"); return; } int i = 0; printf("%-10s%-8s%-8s%-20s%-20s\n", "姓名", "年龄", "性别", "电话", "地址"); for (i = 0; i < pc->count; i++) { printf("%-10s%-8d%-8s%-20s%-20s\n", pc->data[i].name, pc->data[i].age, pc->data[i].sex, pc->data[i].tele, pc->data[i].addr); } } void SearchContact(Contact* pc) { assert(pc); char name[MAX_NAME] = { 0 }; printf("请输入要查找人的姓名:>"); scanf("%s", name); //查找 int pos = FindByName(pc, name); if (-1 == pos) { printf("要查找的人不存在\n"); return; } //输出 printf("%-10s%-8s%-8s%-20s%-20s\n", "姓名", "年龄", "性别", "电话", "地址"); printf("%-10s%-8d%-8s%-20s%-20s\n", pc->data[pos].name, pc->data[pos].age, pc->data[pos].sex, pc->data[pos].tele, pc->data[pos].addr); } void ModifyContact(Contact* pc) { assert(pc); char name[MAX_NAME] = { 0 }; printf("请输入要修改人的姓名:>"); scanf("%s", name); //查找 int pos = FindByName(pc, name); if (-1 == pos) { printf("要修改的联系人不存在\n"); return; } //修改 printf("请输入姓名:>"); scanf("%s", pc->data[pos].name); printf("请输入年龄:>"); scanf("%d", &pc->data[pos].age); printf("请输入性别:>"); scanf("%s", pc->data[pos].sex); printf("请输入电话:>"); scanf("%s", pc->data[pos].tele); printf("请输入地址:>"); scanf("%s", pc->data[pos].addr); printf("修改成功!\n"); } void ClearContact(Contact* pc) { assert(pc); InitContact(pc); printf("清空成功\n"); } int cmp_Per_by_name(const void* e1, const void* e2) { return strcmp(((Person*)e1)->name, ((Person*)e2)->name); } void SortContact(Contact* pc) { assert(pc); qsort(pc->data, pc->count, sizeof(Person), cmp_Per_by_name); ShowContact(pc); }
2.4 实现效果
3. 文件版本
3.1 实现要求
在动态版本的基础上,实现通讯录中的信息在退出通讯录的时候可以保存到文件中,在通讯录打开的时候,可以把文件中的信息加载到通讯录中!
3.2 实现思路
文件版本的通讯录做到了信息的持久化,在动态版本的基础上稍加修饰即可;
在退出通讯录时加上文件操作,将内存空间中的信息写入到文件当中;
在初始化通讯录InitContact函数部分加上文件操作,将文件中的信息读到内存空间当中,在读入信息时默认分配的内存空间不够时要进行扩容;
文件版本的通讯录在实现清空所有联系人的时候,不光要考虑将内存中的数据清除,还应该使文件中的内容全部清空,使用remove删除对应文件即可!
3.3 代码实现
test.c
#include"Contact.h" void menu() { printf("--------------------------------\n"); printf(" 1.add 2.del\n"); printf(" 3.search 4.modify\n"); printf(" 5.show 6.Clear\n"); printf(" 7.sort 0.exit\n"); printf("--------------------------------\n"); } int main() { //创建一个通讯录 Contact con; InitContact(&con); menu(); int input = 0; do { printf("请选择:>"); scanf("%d", &input); switch (input) { case ADD: AddContact(&con); break; case DEL: DelContact(&con); break; case SEARCH: SearchContact(&con); break; case MODIFY: ModifyContact(&con); break; case SHOW: ShowContact(&con); break; case CLEAR: ClearContact(&con); break; case SORT: SortContact(&con); break; case EXIT: SaveContact(&con); DestroyContact(&con); printf("退出成功\n"); break; default: printf("选择错误,请重新输入\n"); break; } } while (input); return 0; }
Contact.h
#pragma once #include<stdio.h> #include<assert.h> #include<string.h> #include<stdlib.h> #include<string.h> #include<errno.h> #define DEFAULT_SZ 3 #define INCREASE_SZ 2 #define MAX_NAME 20 #define MAX_SEX 10 #define MAX_TELE 12 #define MAX_ADDR 30 #define MAX_DATA 1000 //枚举 enum Optint { EXIT, ADD, DEL, SEARCH, MODIFY, SHOW, CLEAR, SORT }; //定义一个人的信息 typedef struct Person { char name[MAX_NAME]; int age; char sex[MAX_SEX]; char tele[MAX_NAME]; char addr[MAX_ADDR]; }Person; //定义一个通讯录 静态版本 //typedef struct Contact //{ // Person data[MAX_DATA];//存放人的信息 // int count; // //}Contact; //动态版本 typedef struct Contact { Person* data;//存放人的信息,维护通讯录的指针 int count;//记录通讯录中实际联系人的个数 int capacity;//当前通讯录的容量 }Contact; //初始化通讯录 void InitContact(Contact* pc); //添加联系人 void AddContact(Contact* pc); //删除联系人 void DelContact(Contact* pc); //搜索联系人 void SearchContact(Contact* pc); //修改联系人 void ModifyContact(Contact* pc); //显示联系人 void ShowContact(Contact* pc); //清空联系人 void ClearContact(Contact* pc); //排序联系人 void SortContact(Contact* pc); //释放通讯录动态内存 void DestroyContact(Contact* pc); //保存通讯录的信息到文件 void SaveContact(Contact* pc); //加载文件中的信息到通讯录 void LoadContact(Contact* pc);
Contact.c
#include"Contact.h" //静态版本 //void InitContact(Contact* pc) //{ // assert(pc); // pc->count = 0; // memset(pc->data, 0, sizeof(pc->data)); //} //void AddContact(Contact* pc) //{ // assert(pc); // if (pc->count == MAX_DATA) // { // printf("通讯录已满,无法添加\n"); // return; // } // printf("请输入姓名:>"); // scanf("%s", pc->data[pc->count].name); // printf("请输入年龄:>"); // scanf("%d", &pc->data[pc->count].age); // printf("请输入性别:>"); // scanf("%s", pc->data[pc->count].sex); // printf("请输入电话:>"); // scanf("%s", pc->data[pc->count].tele); // printf("请输入地址:>"); // scanf("%s", pc->data[pc->count].addr); // pc->count++; // printf("添加成功!\n"); // //} void CheckCapacity(Contact* pc) { if (pc->capacity == pc->count) { Person* prt = (Person*)realloc(pc->data, (pc->capacity + INCREASE_SZ) * sizeof(Person)); if (NULL == prt) { printf("AddContact: :%s\n", strerror(errno)); return; } else { pc->data = prt; pc->capacity += INCREASE_SZ; printf("增容成功\n"); } } } //动态版本 void InitContact(Contact* pc) { assert(pc); pc->count = 0; pc->data = (Person*)calloc(DEFAULT_SZ, sizeof(Person)); if ( NULL == pc->data) { printf("InitContact: :%s\n", strerror(errno)); return; } pc->capacity = DEFAULT_SZ; //加载文件中的信息到通讯录 LoadContact(pc); } void LoadContact(Contact* pc) { assert(pc); FILE* pfRead = fopen("Contact.txt", "rb"); if (pfRead == NULL) { perror("LoadContact"); return; } Person tmp = { 0 }; while (fread(&tmp, sizeof(Person), 1, pfRead) == 1) { CheckCapacity(pc); pc->data[pc->count] = tmp; pc->count++; } fclose(pfRead); pfRead = NULL; } void AddContact(Contact* pc) { assert(pc); //增容 CheckCapacity(pc); printf("请输入姓名:>"); scanf("%s", pc->data[pc->count].name); printf("请输入年龄:>"); scanf("%d", &pc->data[pc->count].age); printf("请输入性别:>"); scanf("%s", pc->data[pc->count].sex); printf("请输入电话:>"); scanf("%s", pc->data[pc->count].tele); printf("请输入地址:>"); scanf("%s", pc->data[pc->count].addr); pc->count++; printf("添加成功!\n"); } void DestroyContact(Contact* pc) { assert(pc); free(pc->data); pc->data = NULL; } static int FindByName(Contact* pc, char name[]) { assert(pc && name); int i = 0; for (i = 0; i < pc->count; i++) { if (0 == strcmp(pc->data[i].name, name)) { return i; } } return -1; } void DelContact(Contact* pc) { assert(pc); char name[MAX_NAME] = { 0 }; if (0 == pc->count) { printf("通讯录为空,无法进行删除\n"); } else { printf("请输入要删除人的姓名:>"); scanf("%s", name); //查找 int pos = FindByName(pc, name); if (-1 == pos) { printf("要删除的人不存在\n"); return; } int i = 0; //删除,从后往前进行覆盖 for (i = pos; i < pc->count - 1; i++) { pc->data[i] = pc->data[i + 1]; } pc->count--; printf("删除成功\n"); } } void ShowContact(Contact* pc) { assert(pc); if (0 == pc->count) { printf("通讯录为空\n"); return; } int i = 0; printf("%-10s%-8s%-8s%-20s%-20s\n", "姓名", "年龄", "性别", "电话", "地址"); for (i = 0; i < pc -> count; i++) { printf("%-10s%-8d%-8s%-20s%-20s\n", pc->data[i].name, pc->data[i].age, pc->data[i].sex, pc->data[i].tele, pc->data[i].addr); } } void SearchContact(Contact* pc) { assert(pc); char name[MAX_NAME] = { 0 }; printf("请输入要查找人的姓名:>"); scanf("%s", name); //查找 int pos = FindByName(pc, name); if (-1 == pos) { printf("要查找的人不存在\n"); return; } //输出 printf("%-10s%-8s%-8s%-20s%-20s\n", "姓名", "年龄", "性别", "电话", "地址"); printf("%-10s%-8d%-8s%-20s%-20s\n", pc->data[pos].name, pc->data[pos].age, pc->data[pos].sex, pc->data[pos].tele, pc->data[pos].addr); } void ModifyContact(Contact* pc) { assert(pc); char name[MAX_NAME] = { 0 }; printf("请输入要修改人的姓名:>"); scanf("%s", name); //查找 int pos = FindByName(pc, name); if (-1 == pos) { printf("要修改的联系人不存在\n"); return; } //修改 printf("请输入姓名:>"); scanf("%s", pc->data[pos].name); printf("请输入年龄:>"); scanf("%d", &pc->data[pos].age); printf("请输入性别:>"); scanf("%s", pc->data[pos].sex); printf("请输入电话:>"); scanf("%s", pc->data[pos].tele); printf("请输入地址:>"); scanf("%s", pc->data[pos].addr); printf("修改成功!\n"); } //void ClearContact(Contact* pc) //{ // assert(pc); // InitContact(pc); // printf("清空成功\n"); //} void ClearContact(Contact* pc) { assert(pc); //删除文件 if (remove("Contact.txt") == -1) { perror("ClearContact"); return; } pc->count = 0; memset(pc->data, 0, sizeof(Person)*(pc->count)); printf("清空成功\n"); } int cmp_Per_by_name(const void* e1, const void* e2) { return strcmp( ((Person*)e1)->name, ((Person*)e2)->name); } void SortContact(Contact* pc) { assert(pc); qsort(pc->data, pc->count, sizeof(Person), cmp_Per_by_name); ShowContact(pc); } void SaveContact(Contact* pc) { assert(pc); FILE* pfWrite = fopen("Contact.txt", "wb"); if (pfWrite == NULL) { perror("SaveContact"); return; } //以二进制的形式写入文件 int i = 0; for (i = 0; i < pc->count; i++) { fwrite(pc->data + i, sizeof(Person), 1, pfWrite); } fclose(pfWrite); pfWrite = NULL; }
3.4 实现效果