🎉🎉大家好,我是青衫,这期我们来模拟实现一个能够存储数据的动态内存通讯录🎉🎉
✨✨通讯录功能:
1、添加联系人
2、删除联系人
3、查找联系人
4、修改联系人
5、保存已经存储的联系人(存储进文件,以便下次运行时读取)
6、展示通讯录
7、退出通讯录
✨✨所要用到的函数:
1、打印菜单-------void menu()
2、初始化通讯录-------void inint_contact(Contact* pc)
3、添加联系人-------void add_contact(Contact* pc)
4、删除联系人-------void add_contact(Contact* pc)
5、查找联系人-------void find_contact(Contact* pc)
6、修改联系人-------void modify_contact(Contact* pc)
7、展示联系人-------void show_contact(Contact* pc)
8、检查通讯录是否已满-------void check_contact(Contact* pc)
9、文件存储通讯录数据-------void save_contact(Contact* pc)
10、加载文件中的数据-------void load_contact(Contact* pc)
11、销毁通讯录-------void destroy_contact(Contact* pc)
12、通过名字查找-------static int find_per_by_name(Contact* pc,char name[ ])
文件准备
一个名为“contact.h”的头文件,一个名为“contact.c”的源文件,一个“test.c”的源文件。两个源文件分别包含头文件。
源文件准备工作
包含头文件以及宏定义和结构体定义:
#pragma once #include <stdio.h> #include <assert.h> #include <stdlib.h> #include <string.h> #define DEFAULT_SZ 3 #define INC 2 #define MAX_NAME 10 #define MAX_TELE 12 #define MAX_ADDRESS 100 #define MAX_SEX 5 //人 typedef struct Person { char name[MAX_NAME]; char tele[MAX_TELE]; char address[MAX_ADDRESS]; char sex[MAX_SEX]; int age; }Person; typedef struct Contact { //人物数据 Person* data; //存储的数量 int size; //总容量 int capacity; }Contact;
函数声明:
//添加 void add_contact(Contact* pc); //删除 void delete_contact(Contact* pc); //查找 void find_contact(Contact* pc); //修改 void modify_contact(Contact* pc); //销毁通讯录 void destroy_contact(Contact* pc); //初始化通讯录 void inint_contact(Contact* pc); //检查通讯录是否满了 void check_contact(Contact* pc); //展示通讯录 void show_contact(Contact* pc); //文件保存通讯录 void save_contact(Contact* pc); //加载文件中的通讯录联系人信息 void load_contact(Contact* pc);
接下来我们该实现函数了
🛸1.1打印菜单
void menu() { printf("************************************\n"); printf("***** 1、添加 2、删除 *********\n"); printf("*******3、查找 4、修改 *********\n"); printf("***********5、展示联系人************\n"); printf("*********** 0、退出 **************\n"); printf("************************************\n"); }
🛸1.2初始化通讯录
void inint_contact(Contact* pc) { assert(pc); pc->size = 0; pc->capacity = 2; pc->data = (Person*)malloc(DEFAULT_SZ * sizeof(Person)); if (pc->data == NULL) { perror("InitContact::malloc"); return; } //加载文件中存储好的通讯录联系人信息 load_contact(pc); }
这里用malloc开辟足够的空间来存储联系人。
load_Contact函数是读取文件中的数据的函数,后文会讲到如何实现。
1.3 检查通讯录是否已满
void check_contact(Contact* pc) { if (pc->size == pc->capacity) { Person* ptr = realloc(pc->data, (pc->capacity + INC) * sizeof(Person)); if (ptr != NULL) { pc->data = ptr; pc->capacity += INC; printf("增容成功\n"); } else { perror("add_contact realloc"); return; } } }
这里判断容量capacity是否足够,如果不足了,就用realloc来扩容。扩容后capacity也应该加上扩容的容量。
🛸1.4添加联系人
void add_contact(Contact* pc) { assert(pc); check_contact(pc); printf("请输入姓名-> "); scanf("%s", &pc->data[pc->size].name); printf("请输入电话-> "); scanf("%s", &pc->data[pc->size].tele); printf("请输入地址-> "); scanf("%s", &pc->data[pc->size].address); printf("请输入性别-> "); scanf("%s", &pc->data[pc->size].sex); printf("请输入年龄-> "); scanf("%d", &pc->data[pc->size].age); pc->size++; printf("添加成功\n"); }
先断言判断传入的指针非空。
之后逐个输入即可。
🛸1.5通过输入的名字查找到联系人
static int find_per_by_name(Contact* pc,char name[]) { assert(pc); int i = 0; for (int i = 0; i < pc->size; i++) { if (strcmp(pc->data[i].name, name) == 0) { return i; } } return -1; }
通过输入的姓名,遍历查找整个通讯录,如果发现相同名字的,那么就返回其对应的下标。
如果找不到,返回-1;
注:这里因为只是在这个文件中实现其他函数的时候用到这个函数,所以用static来声明保护它,让它不能在其他文件中使用。
🛸1.6删除联系人
void delete_contact(Contact* pc) { assert(pc); if (pc->size == 0) { printf("通讯录为空\n"); } else { char name[MAX_NAME] = { 0 }; printf("请输入要删除的人的姓名\n"); scanf("%s", name); int pos = find_per_by_name(pc, name); if (pos == -1) { printf("不存在此人\n"); } else { int j = 0; for (j = pos; j < pc->size - 1; j++) { pc->data[j] = pc->data[j + 1]; } pc->size--; printf("删除成功\n"); } } }
输入要删除的联系人的姓名,然后通过前面实现的 find_per_by_name 函数来查找的所要删除的联系人的下标,然后从后往前覆盖数据,再将通讯录的大小-1即可。
🛸1.7查找联系人
void find_contact(Contact* pc) { assert(pc); char name[MAX_NAME] = { 0 }; printf("请输入要查找的人名->"); scanf("%s", name); int pos = find_per_by_name(pc, name); if (pos == -1) { printf("不存在此人\n"); } else { printf("姓名:%s\n", pc->data[pos].name); printf("性别:%s\n", pc->data[pos].sex); printf("年龄:%d\n", pc->data[pos].age); printf("电话:%s\n", pc->data[pos].tele); printf("地址:%s\n", pc->data[pos].address); printf("\n"); } }
还是通过find_per_by_name 函数来查找联系人,然后打印他的信息。
🛸1.8修改联系人
void modify_contact(Contact* pc) { assert(pc); char name[MAX_NAME] = { 0 }; printf("请输入要查找的人名->"); scanf("%s", name); int pos = find_per_by_name(pc, name); if (pos == -1) { printf("不存在此人\n"); } else { printf("请输入姓名-> "); scanf("%s", &pc->data[pc->size].name); printf("请输入电话-> "); scanf("%s", &pc->data[pc->size].tele); printf("请输入地址-> "); scanf("%s", &pc->data[pc->size].address); printf("请输入性别-> "); scanf("%s", &pc->data[pc->size].sex); printf("请输入年龄-> "); scanf("%d", &pc->data[pc->size].age); printf("修改成功!\n"); } }
通过find_per_by_name 函数来查找联系人,然后重新输入新的联系人信息。
🛸1.9展示通讯录的联系人
void show_contact(Contact* pc) { assert(pc); int i = 0; if (pc->size == 0) { printf("通讯录为空\n"); return 1; } for (; i < pc->size; i++) { printf("%d\n", i+1); printf("姓名:%s\n", pc->data[i].name); printf("性别:%s\n", pc->data[i].sex); printf("年龄:%d\n", pc->data[i].age); printf("电话:%s\n", pc->data[i].tele); printf("地址:%s\n", pc->data[i].address); printf("\n"); } }
将整个通讯录的联系人信息一 一打印一遍。
🛸2.0销毁通讯录
void destroy_contact(Contact* pc) { assert(pc); free(pc->data); pc->data = NULL; pc->size = 0; pc->capacity = 0;
free释放之前malloc和realloc申请的内存空间,将指针置空,将容量和大小等归零。
🛸2.1将通讯录中的联系人存储进文件中
void save_contact(Contact* pc) { FILE* pfwritting = fopen("Contact.dat", "wb"); if (pfwritting == NULL) { perror("open file for writting"); return 1; } //写数据进文件 for (int i = 0; i < pc->size; i++) { fwrite(pc->data + i, sizeof(Person), 1, pfwritting); } fclose(pfwritting); pfwritting = NULL; }
fopen打开文件“Contact.dat”,方式为二进制写入。用一个类型为FILE的指针接收。
用fwrite以二进制的形式写入pc->date+i所指向的数据到文件中。
最后fclose关闭文件,将指针置空。
🛸2.2读取文件中存储的联系人数据
void load_contact(Contact* pc) { Person p1 = { 0 }; FILE* pfreading = fopen("Contact.dat", "rb"); if (pfreading == NULL) { perror("open file for reading"); return; } while (fread(&p1, sizeof(Person), 1, pfreading)) { check_contact(pc); pc->data[pc->size] = p1; pc->size++; } }
fopen打开文件,以二进制形式读取。创建Person类型的临时变量p1。
fread将pfreading指向的文件中的内容读取到临时变量p1中。
再用pc->date+i 来接收p1中的内容,存储进通讯录中。
每接收一个,size++;
感谢各位的观看!代码放在最后!
Contact.h
#pragma once #include <stdio.h> #include <assert.h> #include <stdlib.h> #include <string.h> #define DEFAULT_SZ 3 #define INC 2 #define MAX_NAME 10 #define MAX_TELE 12 #define MAX_ADDRESS 100 #define MAX_SEX 5 //人 typedef struct Person { char name[MAX_NAME]; char tele[MAX_TELE]; char address[MAX_ADDRESS]; char sex[MAX_SEX]; int age; }Person; typedef struct Contact { //人物数据 Person* data; //存储的数量 int size; //总容量 int capacity; }Contact; //添加 void add_contact(Contact* pc); //删除 void delete_contact(Contact* pc); //查找 void find_contact(Contact* pc); //修改 void modify_contact(Contact* pc); //销毁通讯录 void destroy_contact(Contact* pc); //初始化通讯录 void inint_contact(Contact* pc); //检查通讯录是否满了 void check_contact(Contact* pc); //展示通讯录 void show_contact(Contact* pc); //文件保存通讯录 void save_contact(Contact* pc); //加载文件中的通讯录联系人信息 void load_contact(Contact* pc);
Contact.c
#define _CRT_SECURE_NO_WARNINGS 1 #include "contact.h" void load_contact(Contact* pc) { Person p1 = { 0 }; FILE* pfreading = fopen("Contact.dat", "rb"); if (pfreading == NULL) { perror("open file for reading"); return; } while (fread(&p1, sizeof(Person), 1, pfreading)) { check_contact(pc); pc->data[pc->size] = p1; pc->size++; } } void inint_contact(Contact* pc) { assert(pc); pc->size = 0; pc->capacity = 2; pc->data = (Person*)malloc(DEFAULT_SZ * sizeof(Person)); if (pc->data == NULL) { perror("InitContact::malloc"); return; } //加载文件中存储好的通讯录联系人信息 load_contact(pc); } void check_contact(Contact* pc) { if (pc->size == pc->capacity) { Person* ptr = realloc(pc->data, (pc->capacity + INC) * sizeof(Person)); if (ptr != NULL) { pc->data = ptr; pc->capacity += INC; printf("增容成功\n"); } else { perror("add_contact realloc"); return; } } } void add_contact(Contact* pc) { assert(pc); check_contact(pc); printf("请输入姓名-> "); scanf("%s", &pc->data[pc->size].name); printf("请输入电话-> "); scanf("%s", &pc->data[pc->size].tele); printf("请输入地址-> "); scanf("%s", &pc->data[pc->size].address); printf("请输入性别-> "); scanf("%s", &pc->data[pc->size].sex); printf("请输入年龄-> "); scanf("%d", &pc->data[pc->size].age); pc->size++; printf("添加成功\n"); } static int find_per_by_name(Contact* pc,char name[]) { assert(pc); int i = 0; for (int i = 0; i < pc->size; i++) { if (strcmp(pc->data[i].name, name) == 0) { return i; } } return -1; } void delete_contact(Contact* pc) { assert(pc); if (pc->size == 0) { printf("通讯录为空\n"); } else { char name[MAX_NAME] = { 0 }; printf("请输入要删除的人的姓名\n"); scanf("%s", name); int pos = find_per_by_name(pc, name); if (pos == -1) { printf("不存在此人\n"); } else { int j = 0; for (j = pos; j < pc->size - 1; j++) { pc->data[j] = pc->data[j + 1]; } pc->size--; printf("删除成功\n"); } } } void show_contact(Contact* pc) { assert(pc); int i = 0; if (pc->size == 0) { printf("通讯录为空\n"); return 1; } for (; i < pc->size; i++) { printf("%d\n", i+1); printf("姓名:%s\n", pc->data[i].name); printf("性别:%s\n", pc->data[i].sex); printf("年龄:%d\n", pc->data[i].age); printf("电话:%s\n", pc->data[i].tele); printf("地址:%s\n", pc->data[i].address); printf("\n"); } } void find_contact(Contact* pc) { assert(pc); char name[MAX_NAME] = { 0 }; printf("请输入要查找的人名->"); scanf("%s", name); int pos = find_per_by_name(pc, name); if (pos == -1) { printf("不存在此人\n"); } else { printf("姓名:%s\n", pc->data[pos].name); printf("性别:%s\n", pc->data[pos].sex); printf("年龄:%d\n", pc->data[pos].age); printf("电话:%s\n", pc->data[pos].tele); printf("地址:%s\n", pc->data[pos].address); printf("\n"); } } void modify_contact(Contact* pc) { assert(pc); char name[MAX_NAME] = { 0 }; printf("请输入要查找的人名->"); scanf("%s", name); int pos = find_per_by_name(pc, name); if (pos == -1) { printf("不存在此人\n"); } else { printf("请输入姓名-> "); scanf("%s", &pc->data[pc->size].name); printf("请输入电话-> "); scanf("%s", &pc->data[pc->size].tele); printf("请输入地址-> "); scanf("%s", &pc->data[pc->size].address); printf("请输入性别-> "); scanf("%s", &pc->data[pc->size].sex); printf("请输入年龄-> "); scanf("%d", &pc->data[pc->size].age); printf("修改成功!\n"); } } void destroy_contact(Contact* pc) { assert(pc); free(pc->data); pc->data = NULL; pc->size = 0; pc->capacity = 0; } void save_contact(Contact* pc) { FILE* pfwritting = fopen("Contact.dat", "wb"); if (pfwritting == NULL) { perror("open file for writting"); return 1; } //写数据进文件 for (int i = 0; i < pc->size; i++) { fwrite(pc->data + i, sizeof(Person), 1, pfwritting); } fclose(pfwritting); pfwritting = NULL; }
test.c
#define _CRT_SECURE_NO_WARNINGS 1 #include "contact.h" void menu() { printf("************************************\n"); printf("***** 1、添加 2、删除 *********\n"); printf("*******3、查找 4、修改 *********\n"); printf("***********5、展示联系人************\n"); printf("*********** 0、退出 **************\n"); printf("************************************\n"); } int main() { Contact con = { 0 }; inint_contact(&con); int input = 0; printf("欢迎使用通讯录系统,请选择您要使用的功能: \n"); do { menu(); scanf("%d", &input); switch (input) { case 1: add_contact(&con); break; case 2: delete_contact(&con); break; case 3: find_contact(&con); case 4: modify_contact(&con); break; case 5: show_contact(&con); break; case 0: save_contact(&con); destroy_contact(&con); printf("欢迎下次使用\n"); break; default: printf("输入有误,请重试\n"); break; } } while (input); return 0; }