在没学动态内存管理之前,我们用的结构体,数组等都是静态分配内存的,也就是说数组的长度是固定的,但是这并不满足我们的实际需求,所以在通讯录项目里面我就用到了动态内存分布。简单来说,就是当需要储存的联系人数据太多了的时候,我们就可以扩大一点空间用来存放新的数据,也就是说实现了要多少,就开辟多少的空间。
该项目实现一个通讯录功能,除了能根据具体需求扩大空间之外,也实现了最基本基本的增删查改等功能,并在退出通讯录时销毁创造的空间,从而不造成内存泄露。
另外,这个项目由三部分组成,函数功能的实现在Contact.c源文件中,各种头文件、函数等声明则由文件Contact.h来实现,最后测试在源文件test.c文件中进行。
- #define _CRT_SECURE_NO_WARNINGS 1
- #include"Contact.h"
-
-
- enum Option {
- Exit,
- add,
- modify,
- del,
- search,
- show,
- sort
- };
-
- void menu() {
- printf("************************\n");
- printf("**1.添加 2.修改******\n");
- printf("**3.删除 4.搜索******\n");
- printf("**5.展示 6.排序******\n");
- printf("**0.退出 ******\n");
- printf("************************\n");
- }
-
-
- int main() {
- int input = 0;
- Contacts Con;
- Init(&Con);
- do {
- menu();
- printf("请输入你的选择--》\n");
- scanf("%d", &input);
- switch (input) {
- case add://添加
- Add_Peo(&Con);
- break;
- case modify://修改
- Modify_Peo(&Con);
- break;
- case del:
- Del_Peo(&Con);
- break;
- case search:
- Sear_Peo(&Con);
- break;
- case show:
- Show_Peo(&Con);
- break;
- case sort:
- Sort_Peo(&Con);
- break;
- case Exit:
- SaveContact(&Con);
- Destory_Contacts(&Con);
- printf("退出通讯录\n");
- break;
- default:
- printf("你的输入有误!\n");
- break;
-
- }
- } while (input != 0);
- return 0;
- }
- #define _CRT_SECURE_NO_WARNINGS 1
- #include
- #include
- #include
- #include
-
- #define name_max 20
- #define sex_max 5
- #define tele_max 12
- #define addr_max 20
- #define num_max 100
- #define default_cap 3
-
- typedef struct PeoInfo {
- char name[name_max];
- char sex[sex_max];
- char tele[tele_max];
- int age;
- }PeoInfo;
- //静态通讯录版本
- //typedef struct Contacts {
- // PeoInfo data[num_max];
- // int sz;
- //}Contacts;
- //动态版本
- typedef struct Contacts {
- PeoInfo *data;//存放数据
- int sz;//记录当前联系人的数量
- int cap;//当前通讯录的容量
- }Contacts;
-
-
-
- //初始化通讯录
- void Init(Contacts* Con);
- //添加功能
- void Add_Peo(Contacts* Con);
- //修改功能
- void Modify_Peo(Contacts* Con);
- //删除联系人
- void Del_Peo(Contacts* Con);
- //展示联系人
- void Show_Peo(Contacts* Con);
- //查询联系人
- void Sear_Peo(Contacts* Con);
- //排序
- void Sort_Peo(Contacts* Con);
- //保存数据到通讯录中
- void SaveContact(Contacts* Con);
- //加载信息到通讯录
- void LoadContact(Contacts* Con);
- #define _CRT_SECURE_NO_WARNINGS 1
- #include"Contact.h"
-
- // 自定义比较剂,按名字字典序排序
-
- int cmp(void* e1,void *e2) {
- //printf("%s %s\n", (, ((struct PeoInfo*)e2)->name);
- return strcmp(((struct PeoInfo*)e1)->name, ((struct PeoInfo*)e2)->name);
- }
-
- //初始化通讯录
- void Init(Contacts* Con) {
- assert(Con);
- Con->sz = 0;
- Con->cap = default_cap;
- Con->data = calloc(Con->cap, sizeof(PeoInfo));
- if (Con->data == NULL) {
- printf("初始化失败\n");
- return;
- }
- LoadContact(Con);
- }
-
- //void Init(Contacts* Con) {
- // assert(Con);
- // Con->sz = 0;
- // memset(Con->data, 0, sizeof(Con->data));
- //}
-
- //增加容量
- void check_cap(Contacts* Con) {
-
- PeoInfo* ptr = realloc(Con->data, (Con->cap + 2) * sizeof(PeoInfo));
- if (ptr != NULL) {
- Con->data = ptr;
- Con->cap += 2;
- printf("增容成功\n");
- }
- else {
- perror("AddContacts->realloc");
- return;
- }
-
- }
- //添加功能
- //动态版本
- void Add_Peo(Contacts* Con) {
- assert(Con);
- if (Con->sz == Con->cap) {
- check_cap(Con);
- }
- printf("请输入添加人的姓名\n");
- scanf("%s", Con->data[Con->sz].name);
- printf("请输入添加人的年龄\n");
- scanf("%d", &Con->data[Con->sz].age);
- printf("请输入添加人的性别\n");
- scanf("%s", Con->data[Con->sz].sex);
- printf("请输入添加人的号码\n");
- scanf("%s", Con->data[Con->sz].tele);
- Con->sz++;
- return;
- }
- //静态版本
- //void Add_Peo(Contacts* Con) {
- // assert(Con);
- // if (Con->sz == num_max) {
- // printf("通讯录已满\n");
- // return;
- // }
- // else {
- // printf("请输入添加人的姓名\n");
- // scanf("%s", Con->data[Con->sz].name);
- // printf("请输入添加人的年龄\n");
- // scanf("%d", &Con->data[Con->sz].age);
- // printf("请输入添加人的性别\n");
- // scanf("%s", Con->data[Con->sz].sex);
- // printf("请输入添加人的号码\n");
- // scanf("%s", Con->data[Con->sz].tele);
- // Con->sz++;
- // return;
- // }
- //}
- //按名字查找
- int find_name(Contacts* Con,char *tager) {
- assert(Con);
- for (int i = 0; i < Con->sz; i++) {
- if (strcmp(Con->data[i].name, tager)==0) {
- return i;
- }
- }
- return -1;
-
-
- }
- //修改功能
- void Modify_Peo(Contacts* Con) {
- assert(Con);
- char name[name_max] = {0};
- while (1) {
- printf("请输入你要修改联系人的名字\n");
- scanf("%s", name);
- int k = find_name(Con, name);
- if ( k!= -1&&k>=0&&k
sz) { - printf("请重新输入修改的姓名\n");
- scanf("%s", Con->data[k].name);
- printf("请重新输入修改的的年龄\n");
- scanf("%d",&Con->data[k].age);
- printf("请重新输入修改的的性别\n");
- scanf("%s", Con->data[k].sex);
- printf("请重新输入修改的的号码\n");
- scanf("%s", Con->data[k].tele);
- printf("修改成功!\n");
- break;
- }
- else {
- printf("查无此人\n");
- break;
- }
- }
-
- }
- //删除联系人
- void Del_Peo(Contacts* Con) {
- assert(Con);
- if (Con->sz == 0) {
- printf("该通讯录还没有联系人\n");
- return;
- }
- printf("请输入你要删除联系人的姓名\n");
- char name1[name_max] = { 0 };
- scanf("%s", name1);
- int k = find_name(Con, name1);
- if (k != -1&&k>=0&&k
sz) { - for (int i = k; i < Con->sz - 1; i++) {
- Con->data[i] = Con->data[i + 1];
- }
- Con->sz--;
- printf("删除成功\n");
- }
- else {
- printf("查无此人\n");
- return;
- }
- }
- //展示联系人
- void Show_Peo(Contacts* Con) {
- assert(Con);
- if (Con->sz == 0) {
- printf("没有联系人\n");
- return;
- }
- printf("-------------------------------------------------\n");
- printf("|%-20s |%-5s |%-5s |%-12s| \n","姓名","年龄","性别","号码");
- printf("-------------------------------------------------\n");
- for (int i = 0; i < Con->sz; i++) {
- printf("|%-20s |%-5d |%-5s |%-12s|\n", Con->data[i].name, Con->data[i].age, Con->data[i].sex, Con->data[i].tele);
- if (i != (Con->sz - 1)) {
- printf("-------------------------------------------------\n");
- }
- }
- printf("-------------------------------------------------\n");
- }
- //查询联系人
- void Sear_Peo(Contacts* Con) {
- assert(Con);
- char tager[name_max] = { 0 };
- if (Con->sz == 0) {
- printf("没有联系人\n");
- return;
- }
- printf("请输入你要查找的名字\n");
- scanf("%s", tager);
- int k = find_name(Con, tager);
- if (k != -1 && k >= 0 && k < Con->sz) {
- printf("-------------------------------------------------\n");
- printf("|%-20s |%-5s |%-5s |%-12s| \n", "姓名", "年龄", "性别", "号码");
- printf("|%-20s |%-5d |%-5s |%-12s|\n", Con->data[k].name, Con->data[k].age, Con->data[k].sex, Con->data[k].tele);
- printf("-------------------------------------------------\n");
- }
- else {
- printf("查无此人\n");
- return;
- }
- }
- //排序
- void Sort_Peo(Contacts* Con) {
- assert(Con);
- qsort(Con->data, Con->sz, sizeof(struct PeoInfo), cmp);
- printf("排序成功\n");
- return;
- }
- //销毁通讯录
- void Destory_Contacts(Contacts* Con) {
- free(Con->data);
- Con->data = NULL;
- Con->cap = 0;
- Con->sz = 0;
- }
-
- //保存数据到文件中
- void SaveContact(Contacts* Con) {
- assert(Con);
-
- FILE* pf = fopen("Contact.txt", "wb");
- if (pf == NULL) {
- perror("SaveContact");
- return;
- }
-
- for (int i = 0; i < Con->sz; i++) {
- fwrite(Con->data + i, sizeof(PeoInfo), 1, pf);
- }
-
- fclose(pf);
- pf = NULL;
- }
-
- //加载文件中的数据到通讯录中
- void LoadContact(Contacts* Con) {
- assert(Con);
-
- FILE* pf = fopen("Contact.txt", "rb");
- if (pf == NULL) {
- perror("LoadContact");
- return;
- }
-
- PeoInfo temp = { 0 };
- while (fread(&temp, sizeof(PeoInfo), 1, pf)) {
- check_cap(Con);
- Con->data[Con->sz] = temp;
- Con->sz++;
- }
-
- fclose(pf);
- pf = NULL;
- }
好了以上就是整个项目的源代码了,是不是很简单呢?感兴趣的可以自己去试试哦!