C语言实现简单通讯录,malloc,calloc,realloc,free动态内存分配的学习。
作者:快盘下载 人气:35文章目录
简单通讯录初始化通讯录增加联系人展示联系人删除联系人查找联系人更改联系人通讯录的排序完整代码test.cContact.hContact.c 动态内存分配mallocfreecallocrealloc常见的错误 通讯录;动态版;test.ccontact.ccontact.h简单通讯录
在之前的博客中;我与大家分享了结构体的相关知识;今天我们就使用结构体来完成一个简单通讯录。首先我们需要创建两个结构体;一个用来描述通讯录中成员的信息;一个用于描述通讯录。
#define Max 100
#define Max_Name 20 #define Max_Sex 5 #define Max_Tele 12 #define Max_Addr 30 #define Default_Sz 3 #define Inc_Sz 2 struct PerInfo { char name[Max_Name]; char sex[Max_Sex]; char tele[Max_Tele]; int age; char addr[Max_Addr]; }; struct Contact { PeoInfo data[MAX];//存放真实数据的空间 int sz;//记录有效数据的个数 };
之后我们编写测试代码;逻辑思路是;首先打印主菜单;之后创建一个通讯录并且初始化通讯录;我们可以让用户选择需要实现的功能;可以循环操作。
#define _CRT_SECURE_NO_WARNINGS 1
#include ;contact.h; void menu() { printf(;***************** ;); printf(;******0.exit***** ;); printf(;******1.add****** ;); printf(;******2.del****** ;); printf(;******3.search*** ;); printf(;******4.modify*** ;); printf(;******5.show***** ;); printf(;******6.sort***** ;); printf(;***************** ;); } enum Option { EXIT, ADD, DEL, SEARCH, MODIFY, SHOW, SORT }; int main() { int input = 0; //创建一个通讯录 struct Contact con; //初始化通讯录 InitContact(&con); do { menu(); printf(;请输入你的选择;;); scanf(%d;, &input); switch (input) { case EXIT: DestoryContact(&con); break; case ADD: AddContact(&con); break; case DEL: DeleContact(&con); break; case SEARCH: SarchContact(&con); break; case MODIFY: ModifyContact(&con); break; case SHOW: ShowContact(&con); break; case SORT: SortContact(&con); break; } } while (input); }
初始化通讯录
大概的思路就是这样;剩下的就是各个函数的编写了;
我们来编写初始化通讯的功能。
//初始化通讯录 静态版本
void InitContact(struct Contact* pc) { assert(pc); pc->sz = 0; memset(pc->data, 0, Max * sizeof(struct PerInfo)); }
我们将我们创建的通讯录的地址传递给InitContact()函数;将sz通讯录联系人个数初始化为0;使用memset初始化结构体变量。
增加联系人
我们再来写一下增加联系人的功能;首先进行判断;通讯录是否还可以增加联系人;如果通讯录已满给出提示;如果可以添加就在指定的位置进行录入。
void AddContact(struct Contact* pc)
{ assert(pc); if (pc->sz == Max) { printf(;通讯录已满;无法录入;;; ;); return; } else { printf(;请输入姓名;;); scanf(%s;, pc->data[pc->sz].name); printf(;请输入性别;;); scanf(%s;, pc->data[pc->sz].sex); printf(;请输入年龄;;); scanf(%d;,&(pc->data[pc->sz].age)); printf(;请输入地址;;); scanf(%s;, pc->data[pc->sz].addr); printf(;请输入电话;;); scanf(%s;, pc->data[pc->sz].tele); pc->sz;;; } printf(;恭喜你;录入成功;;; ;); }
展示联系人
我们需要有一个查看功能;来查看我们录入的联系人;我们创建一个变量令他从0增长到sz-1;我们读取对应位置的信息;就可以打印出对应位置的联系人。
void ShowContact(struct Contact* pc)
{ assert(pc); if (pc->sz == 0) { printf(;您还没有联系人;请您录入 ;); } else { printf(%-20s %-5s %-5s %-30s %-12s ;, ;姓名;, ;年龄;, ;性别;, ;地址;, ;电话;); int i = 0; for (i = 0; i < pc->sz; i;;) { printf(%-20s %-5d %-5s %-30s %-12s ;, pc->data[i].name, pc->data[i].age, pc->data[i].sex, pc->data[i].addr, pc->data[i].tele); } } }
删除联系人
既然我们可以录入联系人;那么我们也应该有删除联系人的功能;我们可以写两个函数;一个是有查找功能的函数;另一个是删除联系人的函数;我们让用户输入需要删除的联系人的名字;通过查找函数判断该联系人是否存在;存在就删除;不存在给出相应的提示。
static int FindByName(struct Contact* pc, char* name)
{ int i = 0; for (i = 0; i < pc->sz; i;;) { if (0 == strcmp(name, pc->data[i].name)) { return i; } } return -1; } void DeleContact(struct Contact* pc) { char name[Max_Name]; printf(;请输入要删除联系人的姓名;;); scanf(%s;, name); int ret = FindByName(pc, name); if (ret == -1) { printf(;您输入的联系人不存在;;; ;); return; } else { int i = ret; for (i = ret; i < pc->sz - 1; i;;) { pc->data[i] = pc->data[i ; 1]; } pc->sz--; } }
当我们找到该联系人时;查找函数返回的就是当前这个姓名联系人的下标;我们将后一个联系人的信息向前覆盖就可以达到删除联系人的目的;删除之后不要忘记;联系人总数需要sz--。
查找联系人
我们需要查找到一个联系人;并且打印他的信息。
static int FindByName(struct Contact* pc, char* name)
{ int i = 0; for (i = 0; i < pc->sz; i;;) { if (0 == strcmp(name, pc->data[i].name)) { return i; } } return -1; } void SarchContact(struct Contact* pc) { char name[Max_Name]; printf(;请输入要查找联系人的姓名;;); scanf(%s;, name); int ret = FindByName(pc, name); if (ret == -1) { printf(;您输入的联系人不存在;;; ;); return; } else { printf(;您要查找的联系人的信息是; ;); printf(%-20s %-5s %-5s %-30s %-12s ;, ;姓名;, ;年龄;, ;性别;, ;地址;, ;电话;); printf(%-20s %-5d %-5s %-30s %-12s ;, pc->data[ret].name, pc->data[ret].age, pc->data[ret].sex, pc->data[ret].addr, pc->data[ret].tele); } }
同样跟删除一样;我们还是使用姓名查找;找到联系人后对他的信息进行打印就可以了。
更改联系人
static int FindByName(struct Contact* pc, char* name)
{ int i = 0; for (i = 0; i < pc->sz; i;;) { if (0 == strcmp(name, pc->data[i].name)) { return i; } } return -1; } void ModifyContact(struct Contact* pc) { char name[Max_Name]; printf(;请输入要更改的联系人的姓名;;); scanf(%s;, name); int ret = FindByName(pc, name); if (ret == -1) { printf(;您要更改的联系人不存在;;; ;); return; } else { printf(;请更改输入姓名;;); scanf(%s;, pc->data[ret].name); printf(;请更改输入性别;;); scanf(%s;, pc->data[ret].sex); printf(;请更改输入年龄;;); scanf(%d;, &(pc->data[ret].age)); printf(;请更改输入地址;;); scanf(%s;, pc->data[ret].addr); printf(;请更改输入电话;;); scanf(%s;, pc->data[ret].tele); } }
与上面的思路大致一样;还是使用姓名找到该联系人;之后对该联系人的信息进行更改就可以了。
通讯录的排序
我们有时会觉得通讯录过于凌乱;需要对通讯录进行排序;排序的依据有很多;这里我们写一种排序;根据年龄的大小对通讯录进行排序。
static int SortByAge(const void* a, const void* b)
{ return ((struct PerInfo*)a)->age - ((struct PerInfo*)b)->age; } void SortContact(struct Contact* pc) { qsort(pc->data, pc->sz, sizeof(struct PerInfo), SortByAge); printf(;已排序完成;;; ;); }
我们直接使用qsort库函数对年龄大小进行快速排序。
完整代码
以上就是就是一个简单通讯录的实现;我们包含了增加;删除;查找;更改;排序等功能;下面是完整的代码
test.c
#define _CRT_SECURE_NO_WARNINGS 1
#include ;contact.h; void menu() { printf(;***************** ;); printf(;******0.exit***** ;); printf(;******1.add****** ;); printf(;******2.del****** ;); printf(;******3.search*** ;); printf(;******4.modify*** ;); printf(;******5.show***** ;); printf(;******6.sort***** ;); printf(;***************** ;); } enum Option { EXIT, ADD, DEL, SEARCH, MODIFY, SHOW, SORT }; int main() { int input = 0; //创建一个通讯录 struct Contact con; //初始化通讯录 InitContact(&con); do { menu(); printf(;请输入你的选择;;); scanf(%d;, &input); switch (input) { case EXIT: printf(;您已退出通讯录;;;;); break; case ADD: AddContact(&con); break; case DEL: DeleContact(&con); break; case SEARCH: SarchContact(&con); break; case MODIFY: ModifyContact(&con); break; case SHOW: ShowContact(&con); break; case SORT: SortContact(&con); break; } } while (input); }
Contact.h
#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h> #include<assert.h> #include<string.h> #include<stdlib.h> #define Max 100 #define Max_Name 20 #define Max_Sex 5 #define Max_Tele 12 #define Max_Addr 30 #define Default_Sz 3 #define Inc_Sz 2 struct PerInfo { char name[Max_Name]; char sex[Max_Sex]; char tele[Max_Tele]; int age; char addr[Max_Addr]; }; struct Contact { struct PerInfo* data; int sz; int capacity; }; //初始化通讯录 void InitContact(struct Contact* pc); //增加通讯人 void AddContact(struct Contact* pc); //展示联系人 void ShowContact(struct Contact* pc); //删除联系人 void DeleContact(struct Contact* pc); //查找联系人 void SarchContact(struct Contact* pc); //更改联系人 void ModifyContact(struct Contact* pc); //根据年龄排序 void SortContact(struct Contact* pc);
Contact.c
#define _CRT_SECURE_NO_WARNINGS 1
#include ;contact.h; 初始化通讯录 静态版本 void InitContact(struct Contact* pc) { assert(pc); pc->sz = 0; memset(pc->data, 0, Max * sizeof(struct PerInfo)); } //增加 静态 void AddContact(struct Contact* pc) { assert(pc); if (pc->sz == Max) { printf(;通讯录已满;无法录入;;; ;); return; } else { printf(;请输入姓名;;); scanf(%s;, pc->data[pc->sz].name); printf(;请输入性别;;); scanf(%s;, pc->data[pc->sz].sex); printf(;请输入年龄;;); scanf(%d;,&(pc->data[pc->sz].age)); printf(;请输入地址;;); scanf(%s;, pc->data[pc->sz].addr); printf(;请输入电话;;); scanf(%s;, pc->data[pc->sz].tele); pc->sz;;; } printf(;恭喜你;录入成功;;; ;); } //展示联系人 void ShowContact(struct Contact* pc) { assert(pc); if (pc->sz == 0) { printf(;您还没有联系人;请您录入 ;); } else { printf(%-20s %-5s %-5s %-30s %-12s ;, ;姓名;, ;年龄;, ;性别;, ;地址;, ;电话;); int i = 0; for (i = 0; i < pc->sz; i;;) { printf(%-20s %-5d %-5s %-30s %-12s ;, pc->data[i].name, pc->data[i].age, pc->data[i].sex, pc->data[i].addr, pc->data[i].tele); } } } //删除联系人 static int FindByName(struct Contact* pc, char* name) { int i = 0; for (i = 0; i < pc->sz; i;;) { if (0 == strcmp(name, pc->data[i].name)) { return i; } } return -1; } void DeleContact(struct Contact* pc) { char name[Max_Name]; printf(;请输入要删除联系人的姓名;;); scanf(%s;, name); int ret = FindByName(pc, name); if (ret == -1) { printf(;您输入的联系人不存在;;; ;); return; } else { int i = ret; for (i = ret; i < pc->sz - 1; i;;) { pc->data[i] = pc->data[i ; 1]; } pc->sz--; } } void SarchContact(struct Contact* pc) { char name[Max_Name]; printf(;请输入要查找联系人的姓名;;); scanf(%s;, name); int ret = FindByName(pc, name); if (ret == -1) { printf(;您输入的联系人不存在;;; ;); return; } else { printf(;您要查找的联系人的信息是; ;); printf(%-20s %-5s %-5s %-30s %-12s ;, ;姓名;, ;年龄;, ;性别;, ;地址;, ;电话;); printf(%-20s %-5d %-5s %-30s %-12s ;, pc->data[ret].name, pc->data[ret].age, pc->data[ret].sex, pc->data[ret].addr, pc->data[ret].tele); } } //更改联系人 void ModifyContact(struct Contact* pc) { char name[Max_Name]; printf(;请输入要更改的联系人的姓名;;); scanf(%s;, name); int ret = FindByName(pc, name); if (ret == -1) { printf(;您要更改的联系人不存在;;; ;); return; } else { printf(;请更改输入姓名;;); scanf(%s;, pc->data[ret].name); printf(;请更改输入性别;;); scanf(%s;, pc->data[ret].sex); printf(;请更改输入年龄;;); scanf(%d;, &(pc->data[ret].age)); printf(;请更改输入地址;;); scanf(%s;, pc->data[ret].addr); printf(;请更改输入电话;;); scanf(%s;, pc->data[ret].tele); } } static int SortByAge(const void* a, const void* b) { return ((struct PerInfo*)a)->age - ((struct PerInfo*)b)->age; } void SortContact(struct Contact* pc) { qsort(pc->data, pc->sz, sizeof(struct PerInfo), SortByAge); printf(;以排序完成;;; ;); }
动态内存分配
上面我们完成了一个简单的通讯录;那么上面的通讯录有没有什么缺点呢?答案是有的;我们开始直接开辟了100个联系人的空间;如果我们没有那么多联系人;那么这些空间是不是就是浪费了;我们希望我们有多少联系人就申请多少内存空间;关闭程序后;这些空间返回给系统。要实现这些功能我们就要学习一下malloc calloc realloc free等库函数。
malloc

上面介绍了这个函数;这个函数向内存申请了一块连续可用的空间;并返回这块空间的指针。
参数是一个无符号整形;就是你要开辟的空间大小
返回值类型;
1.如果开辟成功;返回一个指向开辟好空间的指针。
2.如果开辟失败;则返回一个NULL指针;因此malloc的返回值一定要做检查。
3.返回值的类型是 void* ;所以malloc函数并不知道开辟空间的类型;具体在使用的时候使用者自己来决定;如果参数 size 为0;malloc的行为是标准是未定义的;取决于编译器。
free

如果参数 ptr 指向的空间不是动态开辟的;那free函数的行为是未定义的。
如果参数 ptr 是NULL指针;则函数什么事都不做。
free函数只是将参数指针指向的内存归还给了操作系统;并不会把参数指针置为NULL;为了防止以后访问错误;我们需要在调用free后;手动将指针置为NULL。
我们在一段代码中体会一下malloc free两个库函数的作用
int main()
{ int* p = NULL; p = (int*)malloc(20); if (p != NULL) { int i = 0; for (i = 0; i < 5; i;;) { *(p ; i) = i; printf(%d ;, *(p ; i)); } } free(p); p = NULL; return 0; }

calloc

calloc库函数的作用也是用来动态内存分配的
1.函数的功能是为 num 个大小为 size 的元素开辟一块空间;并且把空间的每个字节初始化为0。
2.与函数 malloc 的区别只在于 calloc 会在返回地址之前把申请的空间的每个字节初始化为全0。
我们可以举个例子看一下malloc与calloc之间的区别;
int main()
{ int* p = (int*)calloc(10, sizeof(int)); if (NULL != p) { } free(p); p = NULL; return 0; }

我们从调试中看见;我们使用calloc开辟的空间被初始化为0;那么我们使用malloc开辟的内存空间呢?
int main()
{ int* p = (int*)malloc(40); if (NULL != p) { } free(p); p = NULL; return 0; }

我们通过调试看见;使用malloc开辟的空间初始值为随机值。
realloc

为了让动态内存管理更加灵活realloc就出现了;有时会我们发现过去申请的空间太小了;有时候我们又会觉得申请的空间过大了;那为了合理的时候内存;我们一定会对内存的大小做灵活的调整。那 realloc 函数就可以做到对动态开辟内存大小的调整。
我们通过上面的介绍了解到了;
void* realloc (void* ptr, size_t size);
1、ptr 是要调整的内存地址
2、size 调整之后新大小
3、返回值为调整之后的内存起始位置。
4、这个函数调整原内存空间大小的基础上;还会将原来内存中的数据移动到 新 的空间。
realloc在调整内存空间的时候存在两种情况;
情况1;原有空间之后又足够大的空间;要扩展的内存就直接在原有内存之后追加空间;原空间的数据不发生变化。
情况2;原有空间之后没有足够大的空间;扩展的方法是;在堆空间上另找一个合适大小的连续空间来使用;这样函数返回的是一个新的内存地址。
我们在代码中使用一下realloc
int main()
{ int* p = (int*)malloc(4); if (NULL != p) { *p = 2; printf(%d ;, *p); } int* ptr = NULL; ptr = (int*)realloc(p, 8); if (ptr != NULL) { p = ptr; int i = 0; for (i = 0; i < 2; i;;) { *(p ; i) = i; printf(%d ;, *(p ; i)); } } free(p); p = NULL; return 0; }

如图我们使用realloc改变了p指针指向的空间大小。
常见的错误
我们在使用动态内存分配时;会出现很多的错误;这里总结一下最常见的一些错误;
1、对NULL指针的解引用操作
2、对动态开辟空间的越界访问
3、对非动态开辟内存使用free释放
4、 使用free释放一块动态开辟内存的一部分
5、对同一块动态内存多次释放
6、动态开辟内存忘记释放;内存泄漏;
通讯录;动态版;
好了我们言归正传;那我们该如果实现我们之前的需求呢?通讯录的大小随着联系人的多少增大或者减小。
struct Contact {
struct PerInfo* data; int sz; int capacity; };
我们更改了通讯录结构体里面的内容;将之前的数组改变为一个结构体指针;增加了一个capacity;这个变量用于对比sz;我们将capacity初始值设为3;sz设为0;当联系人增加时sz;;;当sz == capaciyt时我们就需要增加通讯录的大小。我们的思路大概就是这样;我们在代码中实现一下。
void InitContact(struct Contact* pc)
{ assert(pc); pc->data = (struct PerInfo*)malloc(Default_Sz * sizeof(struct PerInfo)); if (pc->data != NULL) { pc->sz = 0; pc->capacity = Default_Sz; } else { perror(;InitContact();); return; } }
首先初始化;使用malloc开辟空间;将我们sz初始化为0;capacity初始化为3;我们对增加联系人的函数进行一下更改。
void AddContact(struct Contact* pc)
{ assert(pc); if (pc->sz == pc->capacity) { struct PerInfo* ptr = (struct PerInfo*)realloc(pc->data,(Default_Sz);Inc_Sz * sizeof(struct PerInfo)); if (ptr != NULL) { pc->data = ptr; pc->capacity ;= Inc_Sz; printf(;通讯录扩容成功!!! ;); } else { printf(;通讯录扩容失败;;; ;); return; } } printf(;请输入姓名;;); scanf(%s;, pc->data[pc->sz].name); printf(;请输入性别;;); scanf(%s;, pc->data[pc->sz].sex); printf(;请输入年龄;;); scanf(%d;, &(pc->data[pc->sz].age)); printf(;请输入地址;;); scanf(%s;, pc->data[pc->sz].addr); printf(;请输入电话;;); scanf(%s;, pc->data[pc->sz].tele); pc->sz;;; printf(;恭喜你;录入成功;;; ;); }
我们实现了我们的思路;当sz == capacity时我们使用realloc对通讯录进行扩容;这样我们就实现了动态内存的分配;当然我们还需要增加一个销毁函数;当用户选择退出程序时;我们使用free函数对动态申请的内存进行释放。
void DestoryContact(struct Contact* pc)
{ free(pc->data); pc->capacity = Default_Sz; pc->sz = 0; printf(;您以销毁通讯录;;;;); }
这样我们就完成了对通讯录的更改;下面我们来测试一下我们的通讯录的功能吧。





我们也将更改后的源码分享给大家;
test.c
#define _CRT_SECURE_NO_WARNINGS 1
#include ;contact.h; void menu() { printf(;***************** ;); printf(;******0.exit***** ;); printf(;******1.add****** ;); printf(;******2.del****** ;); printf(;******3.search*** ;); printf(;******4.modify*** ;); printf(;******5.show***** ;); printf(;******6.sort***** ;); printf(;***************** ;); } enum Option { EXIT, ADD, DEL, SEARCH, MODIFY, SHOW, SORT }; int main() { int input = 0; //创建一个通讯录 struct Contact con; //初始化通讯录 InitContact(&con); do { menu(); printf(;请输入你的选择;;); scanf(%d;, &input); switch (input) { case EXIT: DestoryContact(&con); break; case ADD: AddContact(&con); break; case DEL: DeleContact(&con); break; case SEARCH: SarchContact(&con); break; case MODIFY: ModifyContact(&con); break; case SHOW: ShowContact(&con); break; case SORT: SortContact(&con); break; } } while (input); }
contact.c
#define _CRT_SECURE_NO_WARNINGS 1
#include ;contact.h; // 初始化通讯录 静态版本 //void InitContact(struct Contact* pc) //{ // assert(pc); // // pc->sz = 0; // memset(pc->data, 0, Max * sizeof(struct PerInfo)); //} //动态版本 void InitContact(struct Contact* pc) { assert(pc); pc->data = (struct PerInfo*)malloc(Default_Sz * sizeof(struct PerInfo)); if (pc->data != NULL) { pc->sz = 0; pc->capacity = Default_Sz; } else { perror(;InitContact();); return; } } //增加 静态 //void AddContact(struct Contact* pc) //{ // assert(pc); // // if (pc->sz == Max) // { // printf(;通讯录已满;无法录入;;; ;); // return; // } // else // { // printf(;请输入姓名;;); // scanf(%s;, pc->data[pc->sz].name); // // printf(;请输入性别;;); // scanf(%s;, pc->data[pc->sz].sex); // // printf(;请输入年龄;;); // scanf(%d;,&(pc->data[pc->sz].age)); // // printf(;请输入地址;;); // scanf(%s;, pc->data[pc->sz].addr); // // printf(;请输入电话;;); // scanf(%s;, pc->data[pc->sz].tele); // // pc->sz;;; // // } // // printf(;恭喜你;录入成功;;; ;); // //} //动态 void AddContact(struct Contact* pc) { assert(pc); if (pc->sz == pc->capacity) { struct PerInfo* ptr = (struct PerInfo*)realloc(pc->data,(Default_Sz);Inc_Sz * sizeof(struct PerInfo)); if (ptr != NULL) { pc->data = ptr; pc->capacity ;= Inc_Sz; printf(;通讯录扩容成功!!! ;); } else { printf(;通讯录扩容失败;;; ;); return; } } printf(;请输入姓名;;); scanf(%s;, pc->data[pc->sz].name); printf(;请输入性别;;); scanf(%s;, pc->data[pc->sz].sex); printf(;请输入年龄;;); scanf(%d;, &(pc->data[pc->sz].age)); printf(;请输入地址;;); scanf(%s;, pc->data[pc->sz].addr); printf(;请输入电话;;); scanf(%s;, pc->data[pc->sz].tele); pc->sz;;; printf(;恭喜你;录入成功;;; ;); } //销毁通讯录 void DestoryContact(struct Contact* pc) { free(pc->data); pc->capacity = Default_Sz; pc->sz = 0; printf(;您以销毁通讯录;;;;); } //展示联系人 void ShowContact(struct Contact* pc) { assert(pc); if (pc->sz == 0) { printf(;您还没有联系人;请您录入 ;); } else { printf(%-20s %-5s %-5s %-30s %-12s ;, ;姓名;, ;年龄;, ;性别;, ;地址;, ;电话;); int i = 0; for (i = 0; i < pc->sz; i;;) { printf(%-20s %-5d %-5s %-30s %-12s ;, pc->data[i].name, pc->data[i].age, pc->data[i].sex, pc->data[i].addr, pc->data[i].tele); } } } //删除联系人 static int FindByName(struct Contact* pc, char* name) { int i = 0; for (i = 0; i < pc->sz; i;;) { if (0 == strcmp(name, pc->data[i].name)) { return i; } } return -1; } void DeleContact(struct Contact* pc) { char name[Max_Name]; printf(;请输入要删除联系人的姓名;;); scanf(%s;, name); int ret = FindByName(pc, name); if (ret == -1) { printf(;您输入的联系人不存在;;; ;); return; } else { int i = ret; for (i = ret; i < pc->sz - 1; i;;) { pc->data[i] = pc->data[i ; 1]; } pc->sz--; } } void SarchContact(struct Contact* pc) { char name[Max_Name]; printf(;请输入要查找联系人的姓名;;); scanf(%s;, name); int ret = FindByName(pc, name); if (ret == -1) { printf(;您输入的联系人不存在;;; ;); return; } else { printf(;您要查找的联系人的信息是; ;); printf(%-20s %-5s %-5s %-30s %-12s ;, ;姓名;, ;年龄;, ;性别;, ;地址;, ;电话;); printf(%-20s %-5d %-5s %-30s %-12s ;, pc->data[ret].name, pc->data[ret].age, pc->data[ret].sex, pc->data[ret].addr, pc->data[ret].tele); } } //更改联系人 void ModifyContact(struct Contact* pc) { char name[Max_Name]; printf(;请输入要更改的联系人的姓名;;); scanf(%s;, name); int ret = FindByName(pc, name); if (ret == -1) { printf(;您要更改的联系人不存在;;; ;); return; } else { printf(;请更改输入姓名;;); scanf(%s;, pc->data[ret].name); printf(;请更改输入性别;;); scanf(%s;, pc->data[ret].sex); printf(;请更改输入年龄;;); scanf(%d;, &(pc->data[ret].age)); printf(;请更改输入地址;;); scanf(%s;, pc->data[ret].addr); printf(;请更改输入电话;;); scanf(%s;, pc->data[ret].tele); } } static int SortByAge(const void* a, const void* b) { return ((struct PerInfo*)a)->age - ((struct PerInfo*)b)->age; } void SortContact(struct Contact* pc) { qsort(pc->data, pc->sz, sizeof(struct PerInfo), SortByAge); printf(;以排序完成;;; ;); }
contact.h
#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h> #include<assert.h> #include<string.h> #include<stdlib.h> #define Max 100 #define Max_Name 20 #define Max_Sex 5 #define Max_Tele 12 #define Max_Addr 30 #define Default_Sz 3 #define Inc_Sz 2 struct PerInfo { char name[Max_Name]; char sex[Max_Sex]; char tele[Max_Tele]; int age; char addr[Max_Addr]; }; struct Contact { struct PerInfo* data; int sz; int capacity; }; //初始化通讯录 void InitContact(struct Contact* pc); //增加通讯人 void AddContact(struct Contact* pc); //展示联系人 void ShowContact(struct Contact* pc); //删除联系人 void DeleContact(struct Contact* pc); //查找联系人 void SarchContact(struct Contact* pc); //更改联系人 void ModifyContact(struct Contact* pc); //根据年龄排序 void SortContact(struct Contact* pc); //摧毁通讯录 void DestoryContact(struct Contact* pc);
加载全部内容