前言:
在没学动态内存管理之前,我们用的结构体,数组等都是静态分配内存的,也就是说数组的长度是固定的,但是这并不满足我们的实际需求,所以在通讯录项目里面我就用到了动态内存分布。简单来说,就是当需要储存的联系人数据太多了的时候,我们就可以扩大一点空间用来存放新的数据,也就是说实现了要多少,就开辟多少的空间。
项目介绍:
该项目实现一个通讯录功能,除了能根据具体需求扩大空间之外,也实现了最基本基本的增删查改等功能,并在退出通讯录时销毁创造的空间,从而不造成内存泄露。
另外,这个项目由三部分组成,函数功能的实现在Contact.c源文件中,各种头文件、函数等声明则由文件Contact.h来实现,最后测试在源文件test.c文件中进行。
一、teat.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; }
二、Contact.h头文件:
#define _CRT_SECURE_NO_WARNINGS 1 #include<stdio.h> #include<string.h> #include<assert.h> #include<stdlib.h> #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);
三、Contact.c文件:
#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<Con->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<Con->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; }
好了以上就是整个项目的源代码了,是不是很简单呢?感兴趣的可以自己去试试哦!