摘要:二静态通讯录接口函数实现文件名功能通讯录函数接口的实现宏定义,头文件,接口函数的声明函数接口测试静态通讯录的基本结构通讯录是一个结构体。
前言:之前,博主已经写过两个有意思的小项目:三子棋和扫雷,接下来,博主继续更新一个小项目-通讯录,包括3种版本,静态版,动态版,文件保存版。接下来,我们先讲解如何实现静态版。
目录
静态通讯录:使用的是定长数组,即数组的长度不能发生改变。我们可以设置通讯录可以记录的成员个数为1000个。
文件名 | 功能 |
Contact.c | 通讯录函数接口的实现 |
Contact.h | 宏定义,头文件,接口函数的声明 |
test.c | 函数接口测试 |
通讯录是一个结构体。
包含:1.通讯录成员数组,每一个通讯录成员又是一个结构体,包括:地址,姓名,年龄,性别,地址,电话。
2.标志通讯录成员个数的变量。
注意:为了方便后序更改通讯录的各种大小,推荐使用宏定义
//注意宏定义后面不要跟分号!!!!不然会有问题#define NAME_MAX 30 //名字最大长度#define SEX_MAX 5 //性别最大长度#define TELE_MAX 12 //电话最大长度#define ADDR_MAX 30 //地址最大长度#define MAX 1000 //通讯录数组的成员总数typedef struct PeoInfo{ char name[NAME_MAX]; int age; char sex[SEX_MAX]; char addr[ADDR_MAX]; char tele[TELE_MAX];}PeoInfo;struct Contact //通讯录{ PeoInfo data[MAX]; //结构体成员数组 int size; //标志通讯录中所含成员个数, 控制数组下标};
enum Option{ EXIT, ADD, DEL, SEARCH, MODIFY, SHOW, DESTORY,};void menu(){ printf("******************************/n"); printf("**** 1. add 2. del *****/n"); printf("**** 3. search 4. modify****/n"); printf("**** 5. show 6. Destory ***/n"); printf("**** 0. exit **/n"); printf("******************************/n");}int main(){ int input = 0; struct Contact con; //创建通讯录,内含MAX个结构体成员 InitContact(&con); //初始化通讯录 do { menu(); printf("请选择->/n"); scanf("%d", &input); switch (input) { case ADD: ADDContact(&con); break; case DEL: DelContact(&con); break; case SEARCH: SearchContact(&con); break; case MODIFY: ModifyContact(&con); break; case SHOW : ShowContact(&con); break; case DESTORY: DesContact(&con); break; case EXIT: printf("退出成功!欢迎再次使用!/n"); break; default: printf("选择错误,请重新选择/n"); break; } } while (input); return 0;}
使用memset初始化通讯录成员数组
写法1:每个成员的大小*成员个数
void InitContact(struct Contact* ps){ assert(ps); //最初没有数据 memset(ps->data, 0, sizeof(PeoInfo) * MAX); //通讯录成员数组初始化为0 ps->size = 0;//默认成员为0}
写法2:数组多带带放在sizeof内部->计算的是整个数组的大小
//写法2void InitContact(struct Contact* ps){ memset(ps->data, 0, sizeof(ps->data)); //ps->data拿到了通讯录中PenInfo数组的数组名//数组名多带带放在sizeof内部,计算的是整个数组的大小 ps->size = 0;}
为了更直观,我们可以把标题也进行打印。通过遍历通讯录成员数组,即可把成员打印出来。
//这是右对齐 如果想要左对齐-> -%30d前面加符号 在%前面数字加负号void ShowContact(struct Contact* ps){ int i = 0; //打印标题 printf("%15s/t%5s/t%8s/t%15s/t%30s/t/n/n", "name", "age", "sex", "tele", "addr"); //打印数组中每个结构体成员的内容 for (i = 0; i < ps->size; i++) { printf("%15s/t%5d/t%8s/t%15s/t%30s/n", ps->data[i].name, ps->data[i].age, ps->data[i].sex, ps->data[i].tele, ps->data[i].addr); }}
写法1:直接对通讯录成员数组进行操作
void ADDContact(struct Contact* ps){ //先判断通讯录是否满了 if (ps->size == MAX) { printf("通讯录已满/n"); } else { printf("请输入名字:"); scanf("%s", ps->data[ps->size].name); //数组名不用& printf("请输入年龄: "); scanf("%d", &(ps->data[ps->size].age)); printf("请输入地址:"); scanf("%s", ps->data[ps->size].addr); printf("请输入号码:"); scanf("%s", ps->data[ps->size].tele); printf("请输入性别:"); scanf("%s", ps->data[ps->size].sex); printf("添加成功/n"); ps->size++; //添加了一个成员,size++ }}
写法2:先创建一个临时结构体成员,然后赋值后,赋给通讯录结构体数组中ps->size位置
//增加成员的写法2:void ADDContact(struct Contact* ps){ PeoInfo tmp = { 0 }; //先判断通讯录是否满了 if (ps->size == MAX) { printf("通讯录已满/n"); } else { printf("请输入名字:"); scanf("%s", tmp.name); //数组名不用& printf("请输入年龄: "); scanf("%d", &(tmp.age)); printf("请输入地址:"); scanf("%s", tmp.addr); printf("请输入号码:"); scanf("%s", tmp.tele); printf("请输入性别:"); scanf("%s", tmp.sex); ps->data[ps->size] = tmp; printf("添加成功/n"); ps->size++; }}
因为size 标志的是通讯录中的成员个数,所以只要判断size是否为0即可知道通讯录是否为空
//如果为空,判断成立,返回1bool EmptyContact(struct Contact* ps){ return ps->size == 0;}
因为后续删除指定联系人,更改指定联系人的信息都需要进行查找,所以可以把查找函数多带带封装
找到了,返回对应的下标,找不到返回-1
因为不作修改,所以可以加上const修饰
方法:遍历结构体成员数组进行查找
int FindContactByName(const struct Contact* ps,const char*name ){ //遍历查找 int i = 0; for(i = 0;i< ps->size;i++) { if( strcmp(name,ps->data[i].name) == 0) { //返回下标 return i; } } return -1;}
注意:删除联系人->从该位置开始后面的数据往前覆盖
如通讯录为空,则不删除,直接返回.
void DelContact(struct Contact* ps){ if (EmptyContact(ps)) { printf("通讯录为空,无法删除/n"); return ; } char name[NAME_MAX] = { 0 }; //用来存储要删除的指定联系人的名字 printf("请输入要删除人得名字:>"); scanf("%s",name); //查找 int pos = FindContactByName(ps, name); if (pos == -1) { printf("指定的联系人不存在/n"); } else { //删除操作 //从pos位置开始,后面的往前覆盖 int i = 0; for (i = pos; i < ps->size - 1; i++) { ps->data[i] = ps->data[i + 1]; } //删除了元素,size-- ps->size--; printf("删除成功/n"); }}
方法:输入要查找的联系人名字,调用查找函数进行查找,若找到,返回对应下标,就把该下标对应的联系人对应信息打印出来
void SearchContact(const struct Contact* ps){ char name[NAME_MAX] = {0}; printf("输入要查找的联系人:>"); scanf("%s",name); int pos =FindContactByName(ps,name); if(pos == -1) { printf("要查找的联系人不存在/n"); } else { // 打印该联系人对应的信息 //打印标题 printf("%15s/t%5s/t%8s/t%15s/t%30s/t/n/n", "name", "age", "sex", "tele", "addr"); printf("%15s/t%5d/t%8s/t%15s/t%30s/n", ps->data[pos].name, ps->data[pos].age, ps->data[pos].sex, ps->data[pos].tele, ps->data[pos].addr); } }}
方法:输入要查找的联系人名字,调用查找函数进行查找,找到了返回对应下标,然后修改对应数组下标的内容
void ModifyContact(struct Contact* ps){ char name[NAME_MAX] = { 0 }; printf("请输入要修改人名字:>"); scanf("%s", name); int pos = FindContactByName(ps, name); if (-1 == pos) { printf("查无此人/n"); } else { printf("请输入新名字:"); scanf("%s", ps->data[pos].name); //数组名不用& printf("请输入新年龄: "); scanf("%d", &(ps->data[pos].age)); printf("请输入新地址:"); scanf("%s", ps->data[pos].addr); printf("请输入新号码:"); scanf("%s", ps->data[pos].tele); printf("请输入新性别:"); scanf("%s", ps->data[pos].sex); }}
相当于字符串比较->使用strcmp
这里可以使用两种方法:冒泡排序或者qsort排序
关于qsort:qsort函数详解
比较的是通讯录成员数组中的成员名字!!!
void SortContact(struct Contact* pcon){ int i, j; struct PeoInfo tmp; for(i = 0; i < pcon->sz - 1; i++) { for(j = 0; j < pcon->sz - 1 - i; j++) { if(0 < strcmp(pcon->data[j].name, pcon->data[j + 1].name)) { tmp = pcon->data[j]; pcon->data[j] = pcon->data[j + 1]; pcon->data[j + 1] = tmp; } } }}
void SortContactByName(struct Contact* ps){ qsort(ps->data, ps->size, sizeof(ps->data[0]), cmp_ContactByName);}int cmp_ContactByName(const void* e1, const void* e2){ return strcmp( ((struct PeoInfo*)e1)->name, ((struct PeoInfo*)e2)->name);}//注意// ((struct PeoInfo*)e1)->name 要括起来,// (struct PeoInfo*)e1->name 这样写是错误的
注意排序的是通讯录里面的成员数组ps->data:每个元素的类型为struct PenInfo ( 结构体成员类型)要排序的个数为ps->size
size标志的是通讯录成员个数
比较函数:比较的是成员的年龄
void SortContact(struct Contact* ps){ qsort(ps->data, ps->size, sizeof(ps->data[0]), cmp_ContactbyAge);}int cmp_ContactbyAge(const void* e1, const void* e2){ return ((struct PeoInfo*)e1)->age - ((struct PeoInfo*)e2)->age;}
清空通讯录:相当于堆通讯录重新初始化.
void ClearContact(Contact* pcon){ InitContact(pcon);}
成员有限:容易造成空间浪费/空间不够的情况。
为了解决这个问题,下一篇文章,博主将会带大家了解动态通讯录.
很感谢你能看到这里,~如果感觉对你有帮助,欢迎给博主一个三连呀~
文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。
转载请注明本文地址:https://www.ucloud.cn/yun/121541.html
摘要:那么我们首先来改造储存空间也就是通讯录结构体静态版本人信息存放在数组中统计存放的人数动态版本统计存放的人数有效容量我们将原本的结构体数组改为一个结构体指针,以此来维护用以储存个人信息的空间。 上一期我们编写了一个C语言版本的简易通讯录,但是我们的之前的通讯录是没有记忆功能的,也就是说,一旦关...
摘要:之前的通讯录在程序退出后内部的数据就会消失,再次打开程序后只能重新输入数据,为此我们增加了一个保存功能来保存信息。 前言: 由于之前实现的通讯录在存储方面只能支持静态的1000人的存储量,但是如果联系人较少,则会造成较大的内存浪费。而当联系人一旦超过1000时,就不能再继续存储信息了。因...
❤️C语言通讯录管理系统(简易版)❤️ ?一、通讯录?二、菜单实现和用户交互?三、主函数⭐️⭐️1.enum选项⭐️⭐️2.switch判断 ?四、定义联系人和通讯录⭐️⭐️1.定义联系人结构体⭐️⭐️2.定义通讯录结构体⭐️⭐️3.定义结构体变量 ?五、通讯录初始化?六、新增联系人?七、查找联系人?八、删除联系人?九、修改联系人?十、查看所有联系人?十一、清空所有联系人?十二、以名字排序所有...
摘要:前言我们需要用语言模拟一个通讯录可以用来存储个人的信息每个人的信息包括姓名电话性别住址年龄功能包括新增联系人查找联系人删除联系人修改联系人查看所有联系人以名字排序所有联系人注此版本不包含其他内容,后续会出更加全面的升级版本通讯录语言简易版 前言: 我们需要用C语言模拟一个通讯录可以用来存...
阅读 1845·2021-11-22 15:25
阅读 3910·2021-11-17 09:33
阅读 2506·2021-10-12 10:12
阅读 1800·2021-10-09 09:44
阅读 3233·2021-10-08 10:04
阅读 1312·2021-09-29 09:35
阅读 1945·2019-08-30 12:57
阅读 1301·2019-08-29 16:22