本文使用了malloc、realloc、calloc等和内存开辟有关的函数。
文章目录
前言
二、头文件
三、主界面
四、通讯录功能函数
1.全代码
2.增加联系人
3.删除联系人
4.查找联系人
5.修改联系人
6.展示联系人
7.清空联系人
8.退出通讯录
总结
前言
为了使用通讯录时,可以随时调整大小,所以使用动态开辟内存函数写通讯录,可增加联系人容量。
动态开辟函数,即在内存的栈区开辟空间,所以使用完毕后,需要释放内存空间。
一、通讯录运行图
二、头文件
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<assert.h>
#include<stdlib.h>#define Max 10enum function
{quit,//退出 默认值为0increase,//增加 默认值为1delete,//删除 默认值为2find,//查找 默认值为3revise,//修改 默认值为4show,//展示 默认值为5empty,//清空 默认值为6sort//排序 默认值为7
};//创建人
typedef struct Person
{char name[20];//姓名size_t age;//年龄char sex[8];//性别char address[15];//地址char phone[12];//电话
}person;//动态
//创建通讯录
typedef struct contact
{person *per;//指向人这个结构体类型size_t sz;//通讯录已有人员个数size_t ContactMax;//通讯录当前最大容量
}contact;//初始化
void init_contact(contact* con);
//增容
void tune(contact* con);
//增加
void increase_contact(contact* con);
//删除
void delete_contact(contact* con);
//查找
//return -1(no) / address(yes)
int find1(const contact** con);
void find_contact(const contact* con);
//修改
void revise_contact(contact* con);
//展示
void show_contact(const contact* con);
//排序通讯录
void sort_contact(contact* con);
//销毁通讯录
void destroy_contact(contact* con);
//保存文件
void save_contact(contact* con);
//将文件信息保存到通讯录中
void load_contact(contact* con);
三、主界面
#include "contact.h"void menu1()
{printf("**************************************\n");printf("******* Simplified address book ******\n");printf("******* 1> increase contact ******\n");printf("******* 2> delete contact ******\n");printf("******* 3> find contact ******\n");printf("******* 4> revise contact ******\n");printf("******* 5> Show all contacts ******\n");printf("******* 6> Empty all contacts ******\n");printf("******* 7> Sort by name ******\n");printf("******* 0> Quit Contacts ******\n");printf("**************************************\n");
}void test()
{//创建通讯录contact con;//初始化通讯录init_contact(&con);//将文件信息保存到通讯录中load_contact(&con);size_t choice = 0;do{menu1();printf("请输入您的选择性:");scanf("%u", &choice);switch (choice){case increase://增加increase_contact(&con);break;case delete://删除delete_contact( &con );break;case find://查找find_contact(&con);break;case revise://修改revise_contact(&con);break;case show://展示show_contact(&con);break;case empty://清空init_contact(&con);break;case sort://排序sort_contact(&con);break;case quit://保存save_contact(&con);//销毁destroy_contact(&con);printf("Exiting Contacts...\n");break;default:printf("You entered the wrong number, please re-enter it.\n");break;}} while (choice);printf("Exited Contacts.\n");}int main()
{test();return 0;
}
四、通讯录功能函数
1.全代码
#include"contact.h"void menu2()
{system("cls");printf("1> name \t 2> age\n");printf("3> sex \t 4> address\n");printf("5> phone\n");printf("Please select:");
}//动态
void init_contact(contact* con)
{assert(con);// per sz ContactMaxcon->sz = 0;person* p = (person*)calloc(Max, sizeof(person));if (p == NULL){perror("init_contact::calloc");return;}con->per = p;con->ContactMax = Max;
}//将文件信息保存到通讯录中
void load_contact(contact* con)
{//打开文件FILE* p = fopen("contact.txt", "rb");if (p == NULL){perror("load_contact::fopen");return;}person tmp = { 0 };size_t i = 0;while(fread(&tmp, sizeof(person), 1, p)){//考虑增容tune(con);con->per[i] = tmp;con->sz++;i++;}//关闭文件fclose(p);p = NULL;
}void tune(contact* con)
{if (con->sz == con->ContactMax){person *p = (person *)realloc(con->per, (con->ContactMax + Max) * sizeof(person));if (p == NULL){perror("tune::realloc");return;}con->per = p;con->ContactMax += Max;}
}//动态开辟
void increase_contact(contact* con)
{assert(con);//检测当前通讯录是否需要增容tune(con);printf("name:");scanf("%s", &(con->per[con->sz].name));printf("age:");scanf("%u", &(con->per[con->sz].age));printf("sex:");scanf("%s", &(con->per[con->sz].sex));printf("address:");scanf("%s", &(con->per[con->sz].address));printf("phone:");scanf("%s", &(con->per[con->sz].phone));(con->sz)++;
}void delete_contact(contact* con)
{assert(con);int result = find1(&con);if (result != -1){char true[5] = { 0 };printf("Are you sure you want to delete %s's information?", &con->per[result].name);printf("yes/no:");scanf("%s", true);if (!strcmp(true, "yes")){if ( con->sz ){memmove(con->per[result].name, con->per[(con->sz) - 1].name, sizeof(con->per[0]));}else{memset(con->per[result].name, 0, sizeof(con->per[0]));}(con->sz)--;printf("The deletion was successful, thanks for using!\n"); }else{printf("Delete failed, please try again!\n");}}else{printf("Delete failed, please try again!\n");}
}int find1(const contact** con)
{assert(*con);size_t i = 0;char sample1[20] = { 0 };printf("请输入你要查找的名字:");scanf("%s", sample1);while (i < (*con)->sz){if (!strcmp(sample1, (*con)->per[i].name)){return i;}else{i++;}}return -1;
}void find_contact(const contact* con)
{assert(con);int result = find1(&con);if (result != -1){printf("Found, the basic information of the contact is:");printf("name:%-20s\tage:%-4d\tsex:%-5s\taddress:%-30s\tphone:%-12s\n",con->per[result].name,con->per[result].age,con->per[result].sex,con->per[result].address,con->per[result].phone);}else{printf("Didn't find it!\n");}}void revise_contact(contact* con)
{assert(con);int result = find1(&con);if (result != -1){char choice1[5] = { 0 };printf("Are you sure you want to revise %s's information?", con->per[result].name);printf("yes/no:");scanf("%s", choice1);if (!strcmp(choice1, "yes")){menu2();printf("Please enter the option you want to modify:");int choice2 = -1;scanf("%d", &choice2);char sample1[30] = { 0 };size_t sample2 = 0;printf("请输入:");switch ( choice2 ){case 1:case 3:case 4:case 5:scanf("%s", sample1);break;case 2:scanf("%d", sample2);break;}switch (choice2){case 1:memmove(con->per[result].name, sample1, sizeof(sample1));break;case 3:memmove(con->per[result].sex, sample1, sizeof(sample1));break;case 4:memmove(con->per[result].address, sample1, sizeof(sample1));break;case 5:memmove(con->per[result].phone, sample1, sizeof(sample1));break;case 2:con->per[result].age = sample2;break;}printf("修改成功,感谢使用!!!\n");}else{printf("修改失败,请再次尝试!!!\n");}}else{printf("修改失败,请再次尝试!!!\n");}
}void show_contact(const contact* con)
{assert(con);printf("\n\n================================================\n");printf("================================================\n\n");if ( con->sz ){size_t i = 0;for (; i < (con->sz); i++){printf("name:%-20s\tage:%-4d\tsex:%-8s\taddress:%-15s\tphone:%-12s\n",con->per[i].name, con->per[i].age, con->per[i].sex,con->per[i].address, con->per[i].phone);}printf("\n\n");}else{printf("There is no contact information in the address book!\n");}
}int cmp_char(const void* str1, const void* str2)
{return strcmp(((person*)str1)->name, ((person*)str2)->name);
}void sort_contact(contact* con)
{qsort(con -> per[0].name, con -> sz, sizeof(con -> per[0]), cmp_char);
}void destroy_contact(contact* con)
{free(con->per);con->per = NULL;con->ContactMax = 0;con->sz = 0;con = NULL;
}void save_contact(contact* con)
{//写文件FILE* p = fopen("contact.txt", "wb");if (p == NULL){perror("save_contact::fopen");return;}int i = 0;for (i = 0; i < con->sz; i++){fwrite(con->per + i, sizeof(person), 1, p);}//关闭文件fclose(p);p = NULL;printf("保存成功\n");
}
2.增加联系人
使用realloc()调整通讯录大小。
联系人信息图为:
void tune(contact* con)
{if (con->sz == con->ContactMax){person *p = (person *)realloc(con->per, (con->ContactMax + Max) * sizeof(person));if (p == NULL){perror("tune::realloc");return;}con->per = p;con->ContactMax += Max;}
}//动态开辟
void increase_contact(contact* con)
{assert(con);//检测当前通讯录是否需要增容tune(con);printf("name:");scanf("%s", &(con->per[con->sz].name));printf("age:");scanf("%u", &(con->per[con->sz].age));printf("sex:");scanf("%s", &(con->per[con->sz].sex));printf("address:");scanf("%s", &(con->per[con->sz].address));printf("phone:");scanf("%s", &(con->per[con->sz].phone));(con->sz)++;
}
3.删除联系人
通过联系人的姓名来查找需要删除的联系人,找到之后确认删除该联系人。
例如:
int find1(const contact** con)
{assert(*con);size_t i = 0;char sample1[20] = { 0 };printf("请输入你要查找的名字:");scanf("%s", sample1);while (i < (*con)->sz){if (!strcmp(sample1, (*con)->per[i].name)){return i;}else{i++;}}return -1;
}void delete_contact(contact* con)
{assert(con);int result = find1(&con);if (result != -1){char true[5] = { 0 };printf("Are you sure you want to delete %s's information?", &con->per[result].name);printf("yes/no:");scanf("%s", true);if (!strcmp(true, "yes")){if ( con->sz ){memmove(con->per[result].name, con->per[(con->sz) - 1].name, sizeof(con->per[0]));}else{memset(con->per[result].name, 0, sizeof(con->per[0]));}(con->sz)--;printf("The deletion was successful, thanks for using!\n"); }else{printf("Delete failed, please try again!\n");}}else{printf("Delete failed, please try again!\n");}
}
4.查找联系人
通过联系人姓名查找联系人。
int find1(const contact** con)
{assert(*con);size_t i = 0;char sample1[20] = { 0 };printf("请输入你要查找的名字:");scanf("%s", sample1);while (i < (*con)->sz){if (!strcmp(sample1, (*con)->per[i].name)){return i;}else{i++;}}return -1;
}void find_contact(const contact* con)
{assert(con);int result = find1(&con);if (result != -1){printf("Found, the basic information of the contact is:");printf("name:%-20s\tage:%-4d\tsex:%-5s\taddress:%-30s\tphone:%-12s\n",con->per[result].name,con->per[result].age,con->per[result].sex,con->per[result].address,con->per[result].phone);}else{printf("Didn't find it!\n");}}
5.修改联系人
先查找,再修改。
可以修改联系人的任一信息。
int find1(const contact** con)
{assert(*con);size_t i = 0;char sample1[20] = { 0 };printf("请输入你要查找的名字:");scanf("%s", sample1);while (i < (*con)->sz){if (!strcmp(sample1, (*con)->per[i].name)){return i;}else{i++;}}return -1;
}void revise_contact(contact* con)
{assert(con);int result = find1(&con);if (result != -1){char choice1[5] = { 0 };printf("Are you sure you want to revise %s's information?", con->per[result].name);printf("yes/no:");scanf("%s", choice1);if (!strcmp(choice1, "yes")){menu2();printf("Please enter the option you want to modify:");int choice2 = -1;scanf("%d", &choice2);char sample1[30] = { 0 };size_t sample2 = 0;printf("请输入:");switch ( choice2 ){case 1:case 3:case 4:case 5:scanf("%s", sample1);break;case 2:scanf("%d", sample2);break;}switch (choice2){case 1:memmove(con->per[result].name, sample1, sizeof(sample1));break;case 3:memmove(con->per[result].sex, sample1, sizeof(sample1));break;case 4:memmove(con->per[result].address, sample1, sizeof(sample1));break;case 5:memmove(con->per[result].phone, sample1, sizeof(sample1));break;case 2:con->per[result].age = sample2;break;}printf("修改成功,感谢使用!!!\n");}else{printf("修改失败,请再次尝试!!!\n");}}else{printf("修改失败,请再次尝试!!!\n");}
}
6.展示联系人
展示所有联系人及其所有信息。
void show_contact(const contact* con)
{assert(con);printf("\n\n================================================\n");printf("================================================\n\n");if ( con->sz ){size_t i = 0;for (; i < (con->sz); i++){printf("name:%-20s\tage:%-4d\tsex:%-8s\taddress:%-15s\tphone:%-12s\n",con->per[i].name, con->per[i].age, con->per[i].sex,con->per[i].address, con->per[i].phone);}printf("\n\n");}else{printf("There is no contact information in the address book!\n");}
}
7.清空联系人
又名初始化通讯录。
重新向内存申请一片空间,存储联系人信息。
void init_contact(contact* con)
{assert(con);// per sz ContactMaxcon->sz = 0;person* p = (person*)calloc(Max, sizeof(person));if (p == NULL){perror("init_contact::calloc");return;}con->per = p;con->ContactMax = Max;
}
8.退出通讯录
通过free()释放内存栈区的空间,避免内存泄露。
void destroy_contact(contact* con)
{free(con->per);con->per = NULL;con->ContactMax = 0;con->sz = 0;con = NULL;
}
总结
在使用完内存函数之后,一定一定要记得释放空间哦~
上述代码展示就是整个动态通讯录的全部啦,如果你有兴趣想要了解,可以通过C_Ccpp/C_study/contact at main · Yjun6/C_Ccpp (github.com)找到它们。