目录
导读:
一、主函数
1. 打印功能菜单
2. 用枚举常量列举功能给功能赋值(0-5)
3. main主函数
二、头文件
三、通讯录各功能的实现
1. 初始化通讯录
2. 增加联系人
3. 展示所有联系人信息
4. 删除指定联系人
5. 查询指定联系人信息
6. 修改指定联系人信息
7. 销毁通讯录
四、各模块全部代码
1. 主函数
2. 头文件
3. 功能实现
五、代码运行展示
1. 添加联系人
2. 展示联系人信息
3. 查找联系人
4. 修改联系人并展示
5. 删除联系人并展示
6. 退出通讯录
导读:
通讯录中所涉及到的动态内存管理相关知识在:
C语言动态内存管理(malloc, calloc,realloc)详解-CSDN博客
柔性数组:
柔性数组详解-CSDN博客
结构体等自定义类型相关知识:
结构体、枚举以及联合类型在内存中的存储与大小计算-CSDN博客
还有之前写过的一个简易的三子棋游戏:
三子棋小游戏代码实现_流浪者与猴的博客-CSDN博客
该通讯录功能为增、删、查、改以及展示目前存放的所有联系人信息,更多功能以及优化等待博主后续的努力
该代码分三个模块:主函数(test_16.c)、具体功能的实现(contact.c)、以及函数的声明(contact.h)
一、主函数
在开头引用contact.h头文件,函数内涵所用到的所有函数以及结构体声明
#include "contact.h"
1. 打印功能菜单
void menu()
{
printf("***************************************\n");
printf("**** 1.add 2.del **********\n");
printf("**** 3.search 4.modify **********\n");
printf("**** 5.show 0.exit **********\n");
printf("***************************************\n");
}
2. 用枚举常量列举功能给功能赋值(0-5)
enum Option //列举出通讯录功能
{
EXIT,
ADD,
DEL,
SEARCH,
MODIFY,
SHOW,
};
3. main主函数
使用do...while循环以及switch来实现功能的反复使用,其中的结构体和函数声明在自身创的头文件中,再开头以及引用
int main()
{
int input = 0;
Contact con;//结构体
InitContact(&con);//初始化通讯录
do
{
menu();
printf("请输入你的选择:>");
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 EXIT:
DestroyContact(&con);//销毁空间
printf("退出\n");
break;
default:
printf("输入错误,请重新输入\n");
break;
}
} while (input);
return 0;
}
二、头文件
头文件中包括库函数、各功能函数、结构体等声明,以供在其他模块更好的使用
#pragma once
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define NAME_MAX 20
#define SEX_MAX 5
#define TELE_MAX 12
#define ADDR_MAX 30
#define MAX 100
#define DEFAULT_SZ 3
#define DEFAULT_INC 2
//类型的声明
typedef struct PeoInfo
{
char name[NAME_MAX];
int age;
char sex[SEX_MAX];
char tele[TELE_MAX];
char addr[ADDR_MAX];
}PeoInfo;
//静态
//typedef struct Contact
//{
// PeoInfo data[MAX];//存放数据
// int sz;//记录当前通讯录中存在的人的信息个数
//}Contact;
//动态
typedef struct Contact
{
PeoInfo* data;//存放数据
int sz;//记录当前通讯录中存在的人的信息个数
int capacity;//记录的是通讯录的当前容量
}Contact;
//初始化通讯录
void InitContact(Contact* pc);
//增加联系人
void AddContact(Contact* pc);
//显示所有联系人
void ShowContact(Contact* pc);
//删除指定联系人
void DelContact(Contact* pc);
//查找指定联系人
void SearchContact(Contact* pc);
//修改指定联系人
void ModifyContact(Contact* pc);
//销毁通讯录
void DestroyContact(Contact* pc);
三、通讯录各功能的实现
1. 初始化通讯录
void InitContact(Contact* pc)
{
assert(pc);
pc->sz = 0; //初始通讯录个人信息为0
pc->capacity = DEFAULT_SZ; // 通讯录初始容量为3
pc->data = calloc(pc->capacity, sizeof(PeoInfo));//为存放数据开辟内存
if (pc->data == NULL)
{
perror("calloc");//如果没有开辟成功返回报错信息
return;
}
memset(pc->data, 0, sizeof(pc->data));//开辟成功,把数据初始化为0
}
2. 增加联系人
在增加联系人前,需要检查通讯录的容量是否够用,这里单独分装成一个函数,来实现容量的检查以及扩展
void CheckCapacity(Contact* pc) //检查容量大小
{
if (pc->sz == pc->capacity)//增加的当前人的数量与容量相等
{
PeoInfo* ptr = (PeoInfo*)realloc(pc->data, (pc->capacity + DEFAULT_INC) * sizeof(PeoInfo));//给data重新开辟空间
if (ptr != NULL)
{
pc->data = ptr;//开辟成功则把空间赋给data
pc->capacity += DEFAULT_INC;//让容量自增2个
printf("增容成功\n");
}
else
{
perror("AddContact->realloc");//开辟失败返回报错信息
return;
}
}
}
void AddContact(Contact* pc)//增加联系人
{
assert(pc);
CheckCapacity(pc);//查看容量,容量不够则增加
//增加信息
printf("请输入名字:");
scanf("%s", pc->data[pc->sz].name);
printf("请输入年龄:");
scanf("%d", &pc->data[pc->sz].age);
printf("请输入性别:");
scanf("%s", pc->data[pc->sz].sex);
printf("请输入电话:");
scanf("%s", pc->data[pc->sz].tele);
printf("请输入地址:");
scanf("%s", pc->data[pc->sz].addr);
pc->sz++;
printf("增加成功\n");
}
3. 展示所有联系人信息
void ShowContact(Contact* pc)//展示所有联系人信息
{
assert(pc);
if (pc->sz == 0)
{
printf("通讯录为空,无需打印\n");
return;
}
int i = 0;
//名字 年龄 性别 电话 地址
printf("%-20s%-5s%-5s%-12s%-30s\n", "名字", "年龄", "性别", "电话", "地址");
for (i = 0; i < pc->sz; i++)
{
//打印每个人信息
printf("%-20s%-5d%-5s%-12s%-30s\n",
pc->data[i].name, pc->data[i].age, pc->data[i].sex, pc->data[i].tele, pc->data[i].addr);
}
}
4. 删除指定联系人
删除联系人需要对通讯录进行查找,所有这里我们也时再次分装一个函数用来查找联系人,后续联系人信息的修改以及查询某个联系人同样需要此函数
int FindByName(Contact* pc, char name[])
{
assert(pc);
int i = 0;
for (i = 0; i < pc->sz; i++)//进入循环逐个查找
{
if (strcmp(pc->data[i].name, name) == 0)
{
return i;
}
}
return -1;//找不到
}
开始删除
void DelContact(Contact* pc)//删除指定联系人
{
char name[NAME_MAX];
assert(pc);
if (pc->sz == 0)//如果当前通讯录并没有增加任何联系人,则返回
{
printf("通讯录为空,无法删除\n");
return;
}
//找到联系人
printf("输入删除人的名字:");
scanf("%s", name);
//找到名字为name的人
int ret = FindByName(pc, name);
if (ret == -1)
{
printf("要删除得到人不存在\n");
return;
}
//删除这个人
int i = 0;
for (i = ret; i < pc->sz-1; i++)
{
pc->data[i] = pc->data[i + 1];
}
pc->sz--;
printf("删除成功\n");
}
5. 查询指定联系人信息
这里也用了查找函数
void SearchContact(Contact* pc)//查询联系人
{
assert(pc);
char name[NAME_MAX];
printf("输入查找人的名字:");
scanf("%s", name);
//找到名字为name的人
int ret = FindByName(pc, name);
if (ret == -1)
{
printf("要查找的人不存在\n");
return;
}
//显示出来
printf("%-20s%-5s%-5s%-12s%-30s\n", "名字", "年龄", "性别", "电话", "地址");
printf("%-20s%-5d%-5s%-12s%-30s\n",
pc->data[ret].name, pc->data[ret].age, pc->data[ret].sex, pc->data[ret].tele, pc->data[ret].addr);
}
6. 修改指定联系人信息
void ModifyContact(Contact* pc)修改指定联系人
{
assert(pc);
char name[NAME_MAX];
printf("输入要修改人的名字:");
scanf("%s", name);
//找到名字为name的人
int ret = FindByName(pc, name);
if (ret == -1)
{
printf("要修改的人不存在\n");
return;
}
//修改
printf("请输入名字:");
scanf("%s", pc->data[ret].name);
printf("请输入年龄:");
scanf("%d", &pc->data[ret].age);
printf("请输入性别:");
scanf("%s", pc->data[ret].sex);
printf("请输入电话:");
scanf("%s", pc->data[ret].tele);
printf("请输入地址:");
scanf("%s", pc->data[ret].addr);
}
7. 销毁通讯录
开辟的内存使用后需要进行释放
void DestroyContact(Contact* pc)//开辟的内存使用后需要进行释放
{
free(pc->data);
pc->data = NULL;
pc->capacity = 0;
pc->sz = 0;
}
四、各模块全部代码
1. 主函数
#define _CRT_SECURE_NO_WARNINGS
#include "contact.h"
//测试通讯录的基本功能
void menu()
{
printf("***************************************\n");
printf("**** 1.add 2.del **********\n");
printf("**** 3.search 4.modify **********\n");
printf("**** 5.show 0.exit **********\n");
printf("***************************************\n");
}
enum Option //列举出通讯录功能
{
EXIT,
ADD,
DEL,
SEARCH,
MODIFY,
SHOW,
};
int main()
{
int input = 0;
Contact con;//结构体
InitContact(&con);//初始化通讯录
do
{
menu();
printf("请输入你的选择:>");
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 EXIT:
DestroyContact(&con);//销毁空间
printf("退出\n");
break;
default:
printf("输入错误,请重新输入\n");
break;
}
} while (input);
return 0;
}
2. 头文件
#pragma once
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define NAME_MAX 20
#define SEX_MAX 5
#define TELE_MAX 12
#define ADDR_MAX 30
#define MAX 100
#define DEFAULT_SZ 3
#define DEFAULT_INC 2
//类型的声明
typedef struct PeoInfo
{
char name[NAME_MAX];
int age;
char sex[SEX_MAX];
char tele[TELE_MAX];
char addr[ADDR_MAX];
}PeoInfo;
//静态
//typedef struct Contact
//{
// PeoInfo data[MAX];//存放数据
// int sz;//记录当前通讯录中存在的人的信息个数
//}Contact;
//动态
typedef struct Contact
{
PeoInfo* data;//存放数据
int sz;//记录当前通讯录中存在的人的信息个数
int capacity;//记录的是通讯录的当前容量
}Contact;
//初始化通讯录
void InitContact(Contact* pc);
//增加联系人
void AddContact(Contact* pc);
//显示所有联系人
void ShowContact(Contact* pc);
//删除指定联系人
void DelContact(Contact* pc);
//查找指定联系人
void SearchContact(Contact* pc);
//修改指定联系人
void ModifyContact(Contact* pc);
//销毁通讯录
void DestroyContact(Contact* pc);
3. 功能实现
#define _CRT_SECURE_NO_WARNINGS
#include "contact.h"
//静态
//void InitContact(Contact* pc)
//{
// assert(pc);
// pc->sz = 0;
// memset(pc->data, 0, sizeof(pc->data));
//}
//动态
void InitContact(Contact* pc)
{
assert(pc);
pc->sz = 0; //初始通讯录个人信息为0
pc->capacity = DEFAULT_SZ; // 通讯录初始容量为3
pc->data = calloc(pc->capacity, sizeof(PeoInfo));//为存放数据开辟内存
if (pc->data == NULL)
{
perror("calloc");//如果没有开辟成功返回报错信息
return;
}
memset(pc->data, 0, sizeof(pc->data));//开辟成功,把数据初始化为0
}
//静态版本
//void AddContact(Contact* pc)
//{
// assert(pc);
// if (pc->sz == MAX)
// {
// printf("通讯录已满,无法增加\n");
// return;
// }
// //增加信息
// printf("请输入名字:");
// scanf("%s", pc->data[pc->sz].name);
// printf("请输入年龄:");
// scanf("%d", &pc->data[pc->sz].age);
// printf("请输入性别:");
// scanf("%s", pc->data[pc->sz].sex);
// printf("请输入电话:");
// scanf("%s", pc->data[pc->sz].tele);
// printf("请输入地址:");
// scanf("%s", pc->data[pc->sz].addr);
//
// pc->sz++;
// printf("增加成功\n");
//}
void CheckCapacity(Contact* pc) //检查容量大小
{
if (pc->sz == pc->capacity)//增加的当前人的数量与容量相等
{
PeoInfo* ptr = (PeoInfo*)realloc(pc->data, (pc->capacity + DEFAULT_INC) * sizeof(PeoInfo));//给data重新开辟空间
if (ptr != NULL)
{
pc->data = ptr;//开辟成功则把空间赋给data
pc->capacity += DEFAULT_INC;//让容量自增2个
printf("增容成功\n");
}
else
{
perror("AddContact->realloc");//开辟失败返回报错信息
return;
}
}
}
void DestroyContact(Contact* pc)//开辟的内存使用后需要进行释放
{
free(pc->data);
pc->data = NULL;
pc->capacity = 0;
pc->sz = 0;
}
void AddContact(Contact* pc)//增加联系人
{
assert(pc);
CheckCapacity(pc);//查看容量,容量不够则增加
//增加信息
printf("请输入名字:");
scanf("%s", pc->data[pc->sz].name);
printf("请输入年龄:");
scanf("%d", &pc->data[pc->sz].age);
printf("请输入性别:");
scanf("%s", pc->data[pc->sz].sex);
printf("请输入电话:");
scanf("%s", pc->data[pc->sz].tele);
printf("请输入地址:");
scanf("%s", pc->data[pc->sz].addr);
pc->sz++;
printf("增加成功\n");
}
void ShowContact(Contact* pc)//展示所有联系人信息
{
assert(pc);
if (pc->sz == 0)
{
printf("通讯录为空,无需打印\n");
return;
}
int i = 0;
//名字 年龄 性别 电话 地址
printf("%-20s%-5s%-5s%-12s%-30s\n", "名字", "年龄", "性别", "电话", "地址");
for (i = 0; i < pc->sz; i++)
{
//打印每个人信息
printf("%-20s%-5d%-5s%-12s%-30s\n",
pc->data[i].name, pc->data[i].age, pc->data[i].sex, pc->data[i].tele, pc->data[i].addr);
}
}
int FindByName(Contact* pc, char name[])
{
assert(pc);
int i = 0;
for (i = 0; i < pc->sz; i++)//进入循环逐个查找
{
if (strcmp(pc->data[i].name, name) == 0)
{
return i;
}
}
return -1;//找不到
}
void DelContact(Contact* pc)//删除指定联系人
{
char name[NAME_MAX];
assert(pc);
if (pc->sz == 0)//如果当前通讯录并没有增加任何联系人,则返回
{
printf("通讯录为空,无法删除\n");
return;
}
//找到联系人
printf("输入删除人的名字:");
scanf("%s", name);
//找到名字为name的人
int ret = FindByName(pc, name);
if (ret == -1)
{
printf("要删除得到人不存在\n");
return;
}
//删除这个人
int i = 0;
for (i = ret; i < pc->sz-1; i++)
{
pc->data[i] = pc->data[i + 1];
}
pc->sz--;
printf("删除成功\n");
}
void SearchContact(Contact* pc)//查询指定联系人
{
assert(pc);
char name[NAME_MAX];
printf("输入查找人的名字:");
scanf("%s", name);
//找到名字为name的人
int ret = FindByName(pc, name);
if (ret == -1)
{
printf("要查找的人不存在\n");
return;
}
//显示出来
printf("%-20s%-5s%-5s%-12s%-30s\n", "名字", "年龄", "性别", "电话", "地址");
printf("%-20s%-5d%-5s%-12s%-30s\n",
pc->data[ret].name, pc->data[ret].age, pc->data[ret].sex, pc->data[ret].tele, pc->data[ret].addr);
}
void ModifyContact(Contact* pc)修改指定联系人
{
assert(pc);
char name[NAME_MAX];
printf("输入要修改人的名字:");
scanf("%s", name);
//找到名字为name的人
int ret = FindByName(pc, name);
if (ret == -1)
{
printf("要修改的人不存在\n");
return;
}
//修改
printf("请输入名字:");
scanf("%s", pc->data[ret].name);
printf("请输入年龄:");
scanf("%d", &pc->data[ret].age);
printf("请输入性别:");
scanf("%s", pc->data[ret].sex);
printf("请输入电话:");
scanf("%s", pc->data[ret].tele);
printf("请输入地址:");
scanf("%s", pc->data[ret].addr);
}