整体思路
本文将会用c语言实现一个通讯录的系统,并且存储若干人的信息,每个人的信息包括:姓名,性别,年龄,电话号码,住址。此通讯录系统的功能包括: 1.增加联系人 2.删除对应的联系人 3.查找联系人 4.修改联系人的信息 5.排序此通讯录 6.打印出通讯录每个人的信息
- 设置每一个联系人的结构体,里面存的是联系人的基本信息
- 然后我们想到联系人不止一个,这样就要开辟一个结构体类型的数组,然后还要有一个数字来存里面已经有了几个联系人,所以还要将这个结构体数组和数字再用一个结构体来存起来
- 最后就是各个细节的实现,注意:结构体传参是传址调用,这样少了重新开辟内存的一步,可以节省很多的时间。
主要函数功能:
- 初始化,构造出结构体数组
- 实现添加联系人的函数
- 实现删除联系人的函数
- 实现查找联系人的函数
- 实现修改联系人的函数
- 实现展示联系人的函数
- 实现排序联系人的函数
删除的思路:
删除联系人前,我们需要先判断用户输入的联系人是否存在,如果存在删除,不存在提示用户没有要删除的联系人
因此我们可以把检测联系人是否存在封装成一个函数中,如果存在,返回联系人在通讯录中的位置,不存在返回-1
添加的思路:
考虑是否需要添加容量的问题,如果需要就动态的添加内存
排序的思路:
排序就是根据我们前面学习的
qsort
函数来实现。
静态
直接上代码:
#define _CRT_SECURE_NO_WARNINGS #define MAX 100 #include <stdio.h> #include <string.h> #include <stdlib.h> struct PeoInfo { char name[20]; char sex[5]; char tele[12]; int age; char addr[30]; }; struct Contact { struct PeoInfo data[MAX]; int sz; }; //初始化 void initContact(struct Contact* pc) { pc->sz = 0; memset(pc->data, 0, MAX * sizeof(struct PeoInfo)); } // 添加 void AddContact(struct Contact* pc) { if (pc->sz == MAX) { printf("通讯录已满,无法添加!\n"); return; } else { printf("请输入名字>\n"); scanf("%s", pc->data[pc->sz].name); printf("请输入性别>\n"); scanf("%s", pc->data[pc->sz].sex); printf("请输入年龄>\n"); scanf("%d", &pc->data[pc->sz].age); printf("请输入电话>\n"); scanf("%s", pc->data[pc->sz].tele); printf("请输入家庭地址\n"); scanf("%s", pc->data[pc->sz].addr); pc->sz++; printf("成功添加联系人\n"); } } //显示 void ShowContact(struct Contact* pc) { for (int i = 0; i < pc->sz; i++) { printf("%s %s %d %s %s\n", pc->data[i].name, pc->data[i].sex, pc->data[i].age, pc->data[i].tele, pc->data[i].addr); } } static int FindByName(struct Contact* pc, char name[]) { for (int i = 0; i < pc->sz; i++) { if (strcmp(pc->data[i].name, name) == 0) { return i; } } return -1; } //删除 void DelContact(struct Contact* pc) { char name[20]; printf("请输入要删除人的名字\n"); scanf("%s", name); int ret = FindByName(pc, name); if (ret == -1) { printf("要删除的人不存在\n"); } else { for (int i = ret; i < pc->sz - 1; i++) { pc->data[i] = pc->data[i + 1]; } pc->sz--; printf("成功删除指定联系人\n"); } } //查找 void SearchContact(struct Contact* pc) { char name[20]; printf("请输入要查找人的名字\n"); scanf("%s", name); int ret = FindByName(pc, name); if (ret == -1) { printf("联系人不存在\n"); } else { printf("%s %s %d %s %s\n", pc->data[ret].name, pc->data[ret].sex, pc->data[ret].age, pc->data[ret].tele, pc->data[ret].addr); } } //修改 void ModifyContact(struct Contact* pc) { char name[20]; printf("请输入要修改人的名字\n"); scanf("%s", name); int ret = FindByName(pc, name); if (ret == -1) { printf("要修改的人不存在\n"); } else { printf("请输入名字>\n"); scanf("%s", pc->data[ret].name); printf("请输入性别>\n"); scanf("%s", pc->data[ret].sex); printf("请输入年龄>\n"); scanf("%d", &pc->data[ret].age); printf("请输入电话>\n"); scanf("%s", pc->data[ret].tele); printf("请输入家庭地址\n"); scanf("%s", pc->data[ret].addr); printf("修改成功\n"); } } int cmp(const void* e1, const void* e2) { return ((struct PeoInfo*)e1)->age - ((struct PeoInfo*)e2)->age; } //排序 void SortContact(struct Contact* pc) { qsort(pc->data, pc->sz, sizeof(struct PeoInfo), cmp); } void menu() { printf("***************************************\n"); printf("*********1.add 2.del************\n"); printf("*********3.search 4.modify*********\n"); printf("*********5.show 6.sort***********\n"); printf("*************0.exit********************\n"); printf("***************************************\n"); } int main() { int input = 0; struct Contact con; initContact(&con); do { menu(); printf("请选择:>"); scanf("%d", &input); switch (input) { case 1: AddContact(&con); break; case 2: DelContact(&con); break; case 3: SearchContact(&con); break; case 4: ModifyContact(&con); break; case 5: ShowContact(&con); break; case 6: SortContact(&con); break; case 0: printf("退出通讯录\n"); break; default : printf("选择错误\n"); break; } } while (input); }
这里的结构体传参,就像上篇文章提到的一样,传的是地址。
动态
#define _CRT_SECURE_NO_WARNINGS #define MAX 100 #include <stdio.h> #include <string.h> #include <stdlib.h> struct PeoInfo { char name[20]; char sex[5]; char tele[12]; int age; char addr[30]; }; struct Contact { struct PeoInfo* data; int sz; int capacity; }; //初始化 void initContact(struct Contact* pc) { pc->data = (struct PeoInfo*)malloc(3 * sizeof(struct PeoInfo)); if (pc == NULL) { printf("开辟失败\n"); } pc->sz = 0; pc->capacity = 3; } // 添加 void AddContact(struct Contact* pc) { if (pc->sz == pc->capacity) { //增加容量 struct PeoInfo* ptr = (struct PeoInfo*)realloc(pc->data, (pc->capacity + 2) * sizeof(struct PeoInfo)); if (ptr != NULL) { pc->data = ptr; pc->capacity += 2; printf("增容成功\n"); } else { printf("调整失败\n"); return; } } printf("请输入名字>\n"); scanf("%s", pc->data[pc->sz].name); printf("请输入性别>\n"); scanf("%s", pc->data[pc->sz].sex); printf("请输入年龄>\n"); scanf("%d", &pc->data[pc->sz].age); printf("请输入电话>\n"); scanf("%s", pc->data[pc->sz].tele); printf("请输入家庭地址\n"); scanf("%s", pc->data[pc->sz].addr); pc->sz++; printf("成功添加联系人\n"); } //显示 void ShowContact(struct Contact* pc) { for (int i = 0; i < pc->sz; i++) { printf("%s %s %d %s %s\n", pc->data[i].name, pc->data[i].sex, pc->data[i].age, pc->data[i].tele, pc->data[i].addr); } } static int FindByName(struct Contact* pc, char name[]) { for (int i = 0; i < pc->sz; i++) { if (strcmp(pc->data[i].name, name) == 0) { return i; } } return -1; } //删除 void DelContact(struct Contact* pc) { char name[20]; printf("请输入要删除人的名字\n"); scanf("%s", name); int ret = FindByName(pc, name); if (ret == -1) { printf("要删除的人不存在\n"); } else { for (int i = ret; i < pc->sz - 1; i++) { pc->data[i] = pc->data[i + 1]; } pc->sz--; printf("成功删除指定联系人\n"); } } //查找 void SearchContact(struct Contact* pc) { char name[20]; printf("请输入要查找人的名字\n"); scanf("%s", name); int ret = FindByName(pc, name); if (ret == -1) { printf("联系人不存在\n"); } else { printf("%s %s %d %s %s\n", pc->data[ret].name, pc->data[ret].sex, pc->data[ret].age, pc->data[ret].tele, pc->data[ret].addr); } } //修改 void ModifyContact(struct Contact* pc) { char name[20]; printf("请输入要修改人的名字\n"); scanf("%s", name); int ret = FindByName(pc, name); if (ret == -1) { printf("要修改的人不存在\n"); } else { printf("请输入名字>\n"); scanf("%s", pc->data[ret].name); printf("请输入性别>\n"); scanf("%s", pc->data[ret].sex); printf("请输入年龄>\n"); scanf("%d", &pc->data[ret].age); printf("请输入电话>\n"); scanf("%s", pc->data[ret].tele); printf("请输入家庭地址\n"); scanf("%s", pc->data[ret].addr); printf("修改成功\n"); } } int cmp(const void* e1, const void* e2) { return ((struct PeoInfo*)e1)->age - ((struct PeoInfo*)e2)->age; } //排序 void SortContact(struct Contact* pc) { qsort(pc->data, pc->sz, sizeof(struct PeoInfo), cmp); } void menu() { printf("***************************************\n"); printf("*********1.add 2.del************\n"); printf("*********3.search 4.modify*********\n"); printf("*********5.show 6.sort***********\n"); printf("*************0.exit********************\n"); printf("***************************************\n"); } int main() { int input = 0; struct Contact con; initContact(&con); do { menu(); printf("请选择:>"); scanf("%d", &input); switch (input) { case 1: AddContact(&con); break; case 2: DelContact(&con); break; case 3: SearchContact(&con); break; case 4: ModifyContact(&con); break; case 5: ShowContact(&con); break; case 6: SortContact(&con); break; case 0: free((&con)->data); (&con)->data = NULL; (&con)->capacity = 0; (&con)->sz = 0; printf("退出通讯录\n"); break; default: printf("选择错误\n"); break; } } while (input); }
这个思路是通讯录那个结构体里面多添加了一个变量,来表示容量,当通讯录里面的个数和容量相等是就要考虑增容。就用之前文章提到的malloc,realloc函数来实现。
文件
需求:
通讯录退出后,之前保存的不能丢,当下一次重新运行通讯录的时候,还能看到上次保存的信息。
具体分析:
退出的时候,把数据保存到文件中,当下一次运行的时候,再从文件中加载信息就可以了
#define _CRT_SECURE_NO_WARNINGS #define MAX 100 #include <stdio.h> #include <string.h> #include <stdlib.h> struct PeoInfo { char name[20]; char sex[5]; char tele[12]; int age; char addr[30]; }; struct Contact { struct PeoInfo* data; int sz; int capacity; }; void LoadContact(struct Contact* pc) { FILE* pf = fopen("data.txt", "rb"); if (pf == NULL) { perror("LoadContact::fopen"); return; } struct PeoInfo tmp = { 0 }; while (fread(&tmp, sizeof(struct PeoInfo), 1, pf)) { //考虑增容量的问题 if (pc->sz == pc->capacity) { struct PeoInfo* ptr = (struct PeoInfo*)realloc(pc->data, (pc->capacity + 2) * sizeof(struct PeoInfo)); if (ptr != NULL) { pc->data = ptr; pc->capacity += 2; printf("增容成功\n"); } else { printf("调整失败\n"); return; } } pc->data[pc->sz] = tmp; pc->sz++; } fclose(pf); pf = NULL; } //初始化 void initContact(struct Contact* pc) { pc->data = (struct PeoInfo*)malloc(3 * sizeof(struct PeoInfo)); if (pc == NULL) { printf("开辟失败\n"); } pc->sz = 0; pc->capacity = 3; //加载文件中的信息到通讯录 LoadContact(pc); } // 添加 void AddContact(struct Contact* pc) { if (pc->sz == pc->capacity) { //增加容量 struct PeoInfo* ptr = (struct PeoInfo*)realloc(pc->data, (pc->capacity + 2) * sizeof(struct PeoInfo)); if (ptr != NULL) { pc->data = ptr; pc->capacity += 2; printf("增容成功\n"); } else { printf("调整失败\n"); return; } } printf("请输入名字>\n"); scanf("%s", pc->data[pc->sz].name); printf("请输入性别>\n"); scanf("%s", pc->data[pc->sz].sex); printf("请输入年龄>\n"); scanf("%d", &pc->data[pc->sz].age); printf("请输入电话>\n"); scanf("%s", pc->data[pc->sz].tele); printf("请输入家庭地址\n"); scanf("%s", pc->data[pc->sz].addr); pc->sz++; printf("成功添加联系人\n"); } //显示 void ShowContact(struct Contact* pc) { for (int i = 0; i < pc->sz; i++) { printf("%s %s %d %s %s\n", pc->data[i].name, pc->data[i].sex, pc->data[i].age, pc->data[i].tele, pc->data[i].addr); } } static int FindByName(struct Contact* pc, char name[]) { for (int i = 0; i < pc->sz; i++) { if (strcmp(pc->data[i].name, name) == 0) { return i; } } return -1; } //删除 void DelContact(struct Contact* pc) { char name[20]; printf("请输入要删除人的名字\n"); scanf("%s", name); int ret = FindByName(pc, name); if (ret == -1) { printf("要删除的人不存在\n"); } else { for (int i = ret; i < pc->sz - 1; i++) { pc->data[i] = pc->data[i + 1]; } pc->sz--; printf("成功删除指定联系人\n"); } } //查找 void SearchContact(struct Contact* pc) { char name[20]; printf("请输入要查找人的名字\n"); scanf("%s", name); int ret = FindByName(pc, name); if (ret == -1) { printf("联系人不存在\n"); } else { printf("%s %s %d %s %s\n", pc->data[ret].name, pc->data[ret].sex, pc->data[ret].age, pc->data[ret].tele, pc->data[ret].addr); } } //修改 void ModifyContact(struct Contact* pc) { char name[20]; printf("请输入要修改人的名字\n"); scanf("%s", name); int ret = FindByName(pc, name); if (ret == -1) { printf("要修改的人不存在\n"); } else { printf("请输入名字>\n"); scanf("%s", pc->data[ret].name); printf("请输入性别>\n"); scanf("%s", pc->data[ret].sex); printf("请输入年龄>\n"); scanf("%d", &pc->data[ret].age); printf("请输入电话>\n"); scanf("%s", pc->data[ret].tele); printf("请输入家庭地址\n"); scanf("%s", pc->data[ret].addr); printf("修改成功\n"); } } int cmp(const void* e1, const void* e2) { return ((struct PeoInfo*)e1)->age - ((struct PeoInfo*)e2)->age; } //排序 void SortContact(struct Contact* pc) { qsort(pc->data, pc->sz, sizeof(struct PeoInfo), cmp); } void SaveContact(struct Contact* pc) { FILE* pf = fopen("data.txt", "wb"); if (pf == NULL) { perror("SaveContact::fopen"); return; } for (int i = 0; i < pc->sz; i++) { fwrite(pc->data + i, sizeof(struct PeoInfo), 1, pf); } fclose(pf); pf = NULL; } void menu() { printf("***************************************\n"); printf("*********1.add 2.del************\n"); printf("*********3.search 4.modify*********\n"); printf("*********5.show 6.sort***********\n"); printf("*************0.exit********************\n"); printf("***************************************\n"); } int main() { int input = 0; struct Contact con; initContact(&con); do { menu(); printf("请选择:>"); scanf("%d", &input); switch (input) { case 1: AddContact(&con); break; case 2: DelContact(&con); break; case 3: SearchContact(&con); break; case 4: ModifyContact(&con); break; case 5: ShowContact(&con); break; case 6: SortContact(&con); break; case 0: SaveContact(&con); free((&con)->data); (&con)->data = NULL; (&con)->capacity = 0; (&con)->sz = 0; printf("退出通讯录\n"); break; default: printf("选择错误\n"); break; } } while (input); }
文件操作终于学了,这篇文章也到了真正收尾的时候啦