C语言实现小游戏/项目|C语言实现通讯录(动态版)

前言:
前面我们已经了解过了C语言实现通讯录( 静态版),接下来,我们了解一下动态版的通讯录是怎么实现的。
目录
一.动态通讯录和静态通讯录的区别
二.动态通讯录接口函数实现
动态通讯录基本结构
1.初始化
2.增容
3.打印成员
4.删除成员
5.增加成员
6.查找成员信息
7.查找成员是否存在
8.修改成员信息
9.按名字排序通讯录成员
10.按年龄排序通讯录成员
11.释放通讯录
三.源码
Contact.c
Contact.h
test.c
一.动态通讯录和静态通讯录的区别

静态通讯录:通讯录成员数组是一个定长数组.当数组大小过大时,可能会造成空间的浪费。当数组大小过小时,存储不了太多的成员。
动态通讯录:使用的是动态数组。指针指向一个动态开辟的数组。当空间不够时,可以进行扩容,这样的话就不会造成空间的浪费。
二.动态通讯录接口函数实现
文件名 功能
Contact.c 通讯录函数接口的实现
Contact.h 宏定义,头文件,接口函数的声明
test.c 函数接口测试
动态通讯录基本结构
与静态通讯录的不同点:指针指向动态开辟的数组,空间不够可以扩容!
#define NAME_MAX 20 #define ADD_MAX 20 #define SEX_MAX 5 #define INIT_MIN 3 #define TEL_MAX 12//通讯录成员 struct PeoInfo { char name[NAME_MAX]; char add[ADD_MAX]; char sex[SEX_MAX]; char tel[TEL_MAX]; int age; }; //动态通讯录 struct Contact { struct PeoInfo* data; //指向动态开辟的通讯录成员数组 int size; //标志成员个数 int capacity; //容量大小,不够则扩容 };

1.初始化 【C语言实现小游戏/项目|C语言实现通讯录(动态版)】动态开辟空间,先给3个成员大小。不够则每次增加两个成员。
//初始化 void InitContact(struct Contact* pc) { assert(pc); //先为通讯录初始化INIT_MIN个元素 struct PeoInfo* tmp = (struct PeoInfo*)malloc(sizeof(struct PeoInfo) * INIT_MIN); if (tmp == NULL) { printf("动态开辟失败\n"); return; } else { pc->data = https://www.it610.com/article/tmp; pc->size = 0; //最初通讯录为空 pc->capacity = INIT_MIN; } }

2.增容 一次增加两个成员,要重新调整通讯录成员数组的空间->使用realloc函数
注意:容量也需要改变,增加两个成员->容量+2
//通讯录增容 void ByNewcapacity(struct Contact* pc) { assert(pc); struct PeoInfo* tmp = (struct PeoInfo*)realloc(pc->data, sizeof(struct PeoInfo)*(pc->capacity +2)); if (tmp == NULL) { printf("增容失败\n"); return; } else { printf("增容成功\n"); pc->data = https://www.it610.com/article/tmp; pc->capacity += 2; } }

3.打印成员 遍历动态开辟的数组进行打印即可,pc->size的大小即为成员个数
//打印 void ShowContact(struct Contact* pc) { assert(pc); int i = 0; printf("%20s\t%20s\t%5s\t%12s\t%5s\n", "name", "add", "age", "tel", "sex"); for (i = 0; i < pc->size; i++) { printf("%20s\t%20s\t%5d\t%12s\t%5s\t", pc->data[i].name, pc->data[i].add, pc->data[i].age, pc->data[i].tel, pc->data[i].sex); printf("\n"); }}

4.删除成员 思路:在要删除成员的位置:后面的成员往前覆盖
//删除 void DelContact(struct Contact* pc) { assert(pc); char name[20] = { 0 }; printf("请输入要删除的成员的名字\n"); scanf("%s", name); int pos = FindContact(pc,name); if (pos == -1) { printf("成员不存在\n"); } else { int i = 0; for (i = pos; i < pc->size - 1; i++) { //后面的成员往前覆盖 pc->data[i] = pc->data[i + 1]; } printf("删除成功\n"); //通讯录成员-1 pc->size--; }}

5.增加成员 注意:增加成员时:要判断容量是否满了
当容量和size大小一样时,说明通讯录满了,增容
void AddContact(struct Contact* pc) { assert(pc); //先判断通讯录是否满了,满了则增容 if (pc->size == pc->capacity) { //增容 ByNewcapacity(pc); } //增加成员 printf("请输入姓名:>"); scanf("%s", pc->data[pc->size].name); ; printf("请输入性别:>"); scanf("%s", pc->data[pc->size].sex); printf("请输入年龄:>"); scanf("%d", &(pc->data[pc->size].age)); printf("请输入电话号码:>"); scanf("%s", pc->data[pc->size].tel); printf("请输入地址:>"); scanf("%s", pc->data[pc->size].add); //增加了成员,size++ pc->size++; }

6.查找成员信息 输入名字,调用查找函数,找到了返回下标,则打印下标对应成员的信息。
//查找成员信息 void SeaContact(struct Contact* pc) { printf("请输入要查找的成员名字\n"); char name[20] = { 0 }; scanf("%s", name); int i = FindContact(pc, name); if (i == -1) { printf("该成员不存在\n"); } else { //打印该成员的信息 //打印标题 printf("%20s\t%20s\t%5s\t%12s\t%5s\n", "name", "add", "age", "tel", "sex"); printf("%20s\t%20s\t%5d\t%12s\t%5s\t", pc->data[i].name, pc->data[i].add, pc->data[i].age, pc->data[i].tel, pc->data[i].sex); printf("\n"); } }

7.查找成员是否存在 遍历通讯录成员数组进行名字比对,找到了返回对应的下标
//查找成员是否存在,存在则返回其在通讯录成员数组的下标,不存在则返回-1 int FindContact(struct Contact* pc,char* name) { assert(pc); //遍历查找 int i = 0; for (i = 0; i < pc->size; i++) { if (strcmp(pc->data[i].name, name) == 0) { return i; } } //找不到 printf("找不到\n"); return -1; }

8.修改成员信息 输入名字,调用查找函数,找到了返回下标,修改对应成员的信息。
//修改成员信息 void ModifyContact(struct Contact* ps) { if (ps->size == 0) { printf("通讯录为空,请先增加成员\n"); } char name[NAME_MAX] = { 0 }; printf("请输入要修改人名字:>"); scanf("%s", name); int pos = FindContact(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].add); printf("请输入新号码:"); scanf("%s", ps->data[pos].tel); printf("请输入新性别:"); scanf("%s", ps->data[pos].sex); } }

9.按名字排序通讯录成员 方法1:qsort函数
不知道的可以看一下我以前写过的文章:qsort函数详解
注意:此时写的比较函数,比较的是通讯录成员,所以e1和e2强转的类型为:struct PenInfo*
而不是struct Contact*
void SortContactByName(struct Contact* ps) { qsort(ps->data, ps->size, sizeof(ps->data[0]), cmp_ByName); } int cmp_ByName(const void* e1, const void* e2) { return strcmp(((struct PeoInfo*)e1)->name, ((struct PeoInfo*)e2)->name); }

方法2:冒泡排序
要排序的是通讯录成员数组,可以按名字排序->strcmp
void SortContactByName(struct Contact* ps) { int i = 0; int j = 0; struct PeoInfo tmp; for (i = 0; i < ps->size-1; i++) { for (j = 0; j < ps->size - i - 1; j++) { if (strcmp(ps->data[j].name, ps->data[j + 1].name) > 0) { tmp = ps->data[j]; ps->data[j] = ps->data[j + 1]; ps->data[j + 1] = tmp; } } } }


10.按年龄排序通讯录成员 和按名字排序同理
方法1:qsort函数
返回值为:两个指针指向的年龄直接相减的结果
void SortContactByAge(struct Contact* ps) { qsort(ps->data, ps->size, sizeof(ps->data[0]), cmp_ByAge); } int cmp_ByAge(const void* e1, const void* e2) { return ((struct PeoInfo*)e1)->age - ((struct PeoInfo*)e2)->age; }

方法2:冒泡排序
void SortContactByAge(struct Contact* ps) { int i = 0; int j = 0; struct PeoInfo tmp; for (i = 0; i < ps->size - 1; i++) { for (j = 0; j < ps->size - i-1; j++) { if ( (ps->data[j].age) - (ps->data[j + 1].age) > 0) { tmp = ps->data[j]; ps->data[j] = ps->data[j + 1]; ps->data[j + 1] = tmp; } } } }

11.释放通讯录 因为通讯录内的成员数组是动态开辟的,所以使用完要进行释放,并把指针置空。防止内存泄漏
void FreeContact(struct Contact* pc) { assert(pc); free(pc->data); pc->data = https://www.it610.com/article/NULL; pc->capacity = 0; pc->size = 0; }

三.源码 Contact.c
#define _CRT_SECURE_NO_WARNINGS 1 #pragma once #include"Contact.h"//初始化 void InitContact(struct Contact* pc) { assert(pc); //先为通讯录初始化INIT_MIN个元素 struct PeoInfo* tmp = (struct PeoInfo*)malloc(sizeof(struct PeoInfo) * INIT_MIN); if (tmp == NULL) { printf("动态开辟失败\n"); return; } else { pc->data = https://www.it610.com/article/tmp; pc->size = 0; //最初通讯录为空 pc->capacity = INIT_MIN; } }//打印 void ShowContact(struct Contact* pc) { assert(pc); int i = 0; printf("%20s\t%20s\t%5s\t%12s\t%5s\n", "name", "add", "age", "tel", "sex"); for (i = 0; i < pc->size; i++) { printf("%20s\t%20s\t%5d\t%12s\t%5s\t", pc->data[i].name, pc->data[i].add, pc->data[i].age, pc->data[i].tel, pc->data[i].sex); printf("\n"); }}//删除 void DelContact(struct Contact* pc) { assert(pc); char name[20] = { 0 }; printf("请输入要删除的成员的名字\n"); scanf("%s", name); int pos = FindContact(pc,name); if (pos == -1) { printf("成员不存在\n"); } else { int i = 0; for (i = pos; i < pc->size - 1; i++) { //后面的成员往前覆盖 pc->data[i] = pc->data[i + 1]; } printf("删除成功\n"); //通讯录成员-1 pc->size--; }}//增加成员 void AddContact(struct Contact* pc) { assert(pc); //先判断通讯录是否满了,满了则增容 if (pc->size == pc->capacity) { //增容 ByNewcapacity(pc); } //增加成员 printf("请输入姓名:>"); scanf("%s", pc->data[pc->size].name); ; printf("请输入性别:>"); scanf("%s", pc->data[pc->size].sex); printf("请输入年龄:>"); scanf("%d", &(pc->data[pc->size].age)); printf("请输入电话号码:>"); scanf("%s", pc->data[pc->size].tel); printf("请输入地址:>"); scanf("%s", pc->data[pc->size].add); //增加了成员,size++ pc->size++; }//查找成员信息 void SeaContact(struct Contact* pc) { printf("请输入要查找的成员名字\n"); char name[20] = { 0 }; scanf("%s", name); int i = FindContact(pc, name); if (i == -1) { printf("该成员不存在\n"); } else { //打印该成员的信息 //打印标题 printf("%20s\t%20s\t%5s\t%12s\t%5s\n", "name", "add", "age", "tel", "sex"); printf("%20s\t%20s\t%5d\t%12s\t%5s\t", pc->data[i].name, pc->data[i].add, pc->data[i].age, pc->data[i].tel, pc->data[i].sex); printf("\n"); } }//查找成员是否存在,存在则返回其在通讯录成员数组的下标,不存在则返回-1 int FindContact(struct Contact* pc,char* name) { assert(pc); //遍历查找 int i = 0; for (i = 0; i < pc->size; i++) { if (strcmp(pc->data[i].name, name) == 0) { return i; } } //找不到 printf("找不到\n"); return -1; }//判断通讯录是否为空 //如果size为0,说明通讯录为空 bool EmptyContact(struct Contact* pc) { return pc->size == 0; }//通讯录增容 void ByNewcapacity(struct Contact* pc) { assert(pc); struct PeoInfo* tmp = (struct PeoInfo*)realloc(pc->data, sizeof(struct PeoInfo)*(pc->capacity +2)); if (tmp == NULL) { printf("增容失败\n"); return; } else { printf("增容成功\n"); pc->data = https://www.it610.com/article/tmp; pc->capacity += 2; } } //通讯录释放 void FreeContact(struct Contact* pc) { assert(pc); free(pc->data); pc->data = https://www.it610.com/article/NULL; pc->capacity = 0; pc->size = 0; } //修改成员信息 void ModifyContact(struct Contact* ps) { if (ps->size == 0) { printf("通讯录为空,请先增加成员\n"); } char name[NAME_MAX] = { 0 }; printf("请输入要修改人名字:>"); scanf("%s", name); int pos = FindContact(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].add); printf("请输入新号码:"); scanf("%s", ps->data[pos].tel); printf("请输入新性别:"); scanf("%s", ps->data[pos].sex); } }

Contact.h
#define _CRT_SECURE_NO_WARNINGS 1 #pragma once #include #include #include #include #include #define NAME_MAX 20 #define ADD_MAX 20 #define SEX_MAX 5 #define INIT_MIN 3 #define TEL_MAX 12//通讯录成员 struct PeoInfo { char name[NAME_MAX]; char add[ADD_MAX]; char sex[SEX_MAX]; char tel[TEL_MAX]; int age; }; //动态通讯录 struct Contact { struct PeoInfo* data; //指向动态开辟的通讯录成员数组 int size; //标志成员个数 int capacity; //容量大小,不够则扩容 }; //初始化 void InitContact(struct Contact* pc); //打印 void ShowContact(struct Contact* pc); //删除 void DelContact(struct Contact* pc); //增加成员 void AddContact(struct Contact* pc); //查找成员信息 void SeaContact(struct Contact* pc); //查找成员是否存在,存在则返回其在通讯录成员数组的下标,不存在则返回-1 int FindContact(struct Contact* pc,char* name); //判断通讯录是否为空 bool EmptyContact(struct Contact* pc); //通讯录增容 void ByNewcapacity(struct Contact* pc); //释放空间 void FreeContact(struct Contact* pc); //修改指定联系人信息 void ModifyContact(struct Contact* ps);

test.c
#define _CRT_SECURE_NO_WARNINGS 1 #pragma once #include"Contact.h" void menu() { printf("***********************\n"); printf("***** 1.ADD2.SHOW*\n"); printf("***** 3.Del4.FIND*\n"); printf("***** 5.Modift 0.exit *\n"); printf("***********************\n"); } enum Option { EXIT, ADD, SHOW, DEL, FIND, MODIFY, }; int main() { int input = 0; struct Contact con; InitContact(&con); do { menu(); printf("请输入你的选择:>"); scanf("%d", &input); switch (input) { case ADD: AddContact(&con); break; case DEL: DelContact(&con); break; case FIND: SeaContact(&con); break; case EXIT: printf("欢迎下次使用\n"); return; case SHOW: ShowContact(&con); break; case MODIFY: ModifyContact(&con); break; default : printf("选择错误,重新选择\n"); break; } } while (input); return 0; }

如果感觉此文章对你有帮助,欢迎各位大佬留个三连呀~

    推荐阅读