文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

C语言多功能动态通讯录实现示例

2023-01-31 12:04

关注

前言

本文将模块化地介绍如何实现一个动态开辟空间的通讯录,其有以下九个功能:

一、预设置

1,头文件的包含

需要用到的头文件有以下几个

#include<stdio.h>//输入输出
#include<stdlib.h>//使用qsort
#include<string.h>//使用strcmp
#include<Windows.h>//使用systeam(“cls”)
#include<assert.h>//使用assert()

2,联系人的信息格式

在此将每个联系人的信息暂定为五项,分别是姓名、性别、年龄、电话、住址,因为要为后面第八个功能——联系人置顶做准备,因此多加入一个int型变量,用于判断该联系人是否被置顶,像这样:

//创建每个联系人的信息格式
typedef struct
{
	char name[max_name];
	char sex[max_sex];
	int age;
	char tele[max_tele];
	char add[max_add];
	int first;//联系人是否被置顶
}people;//联系人类型

以上代码中以max_开头的数据将在稍后的宏定义中介绍。

3,通讯录的信息格式

创建关于通讯录的信息格式的结构体是为了将当前通讯录人数通讯录当前可以容纳的总人数两个变量放在一个结构体变量里面,便于以后的代码传参,像这样:

//创建通讯录格式
typedef struct
{
	people* peoples;//开辟空间后用来维护空间的指针
	int	sz;//当前人数
	int all;//总容纳人数
}contact;通讯录类型

4,通讯录相关宏定义

为了便于日后修改,使用宏定义一些常量。

#define _CRT_SECURE_NO_WARNINGS 1//博主的环境是VS2019
#define init_num_people 10//通讯录初始的人数
#define oncetime 5//通讯录每次扩容增加的人数
#define max_name 10
#define max_sex 4
#define max_tele 11
#define max_add 40

5,通讯录功能枚举

用可以看出含义的英文单词缩写来代替数字,可以方便我们写代码,像这样:

enum MyEnum//对九种通讯录功能进行枚举
{
	MENU = 1,//菜单
	ADD,//添加
	DEL,//删除
	PRIN,//打印
	FIND,//查找
	CHANGE,//修改
	FIRST,//置顶
	SORT,//排序
	EXIT//退出
};

6,基本主函数

总的思路是创建一个刚刚设置的枚举变量,让用户输入数字代表其选择的功能,利用分支语句进入不同的函数。最后不要忘了释放内存哦。

int main()
{
	//创建通讯录
	contact con;
	//初始化
	init_con(&con);
	enum MyEnum input = 0;
	do
	{
		menu();//打印菜单
		scanf("%d", &input);
			switch (input)
			{
			case MENU:
				system("cls");//清屏后break,自动打印菜单
				break;
			case ADD:
				add_people(&con);//增加联系人
				break;
			case DEL:
				del_people(&con);//删除联系人
				break;
			case PRIN:
				PRIN_CON(&con);//打印通讯录
				break;
			case FIND:
				find_people(&con);//查找联系人
				break;
			case CHANGE:
				change_people(&con);//修改联系人
				break;
			case FIRST:
				fir_people(&con);//设置置顶
				break;
			case SORT:
				sort_people(&con);//联系人排序
				break;
			case EXIT:
				free(con.peoples);
				con.peoples = NULL;
				system("cls");
				printf("退出通讯录!\n");
				break;
			}
	} while (input-EXIT);//只有选择9才退出
	return 0;
}

二、功能函数实现

1,初始化函数

此函数中将为通讯录开辟空间,对值进行初始化。

//初始化
void init_con(contact* con)
{
	assert(con);
	con->peoples = (people*)malloc(init_num_people * sizeof(people));//为联系人信息开辟空间
	if (con->peoples == NULL)
	{
		perror("warning::function::9");//开辟失败报错,显示错误位置
		return 0;
	}
	memset(con->peoples, 0, init_num_people * sizeof(people));//把空间初始化为0
	con->sz = 0;//sz是通讯录当前人数
	con->all = init_num_people;//all是通讯录当前可以容纳的总人数
}

2,查找函数

因为通讯录有许多功能(删除,查找,修改,置顶)都需要用到查找,于是写出一个公用函数,用于通过姓名查找通讯录中的联系人,若找到则返回其下标,若找不到则返回sz。

//查找函数,用于通过姓名查找通讯录中的联系人下标,若找到返回下标,若找不到返回sz
int find(contact* con,const char* name)
{
	assert(con);
	int i = 0;
	for (i = 0; i < con->sz; i++)
	{
		if (strcmp(name, con->peoples[i].name) == 0)
		{
			return i;
		}
	}
	return i;
}

3,打印菜单

打印菜单,让用户进行选择。

//打印菜单
void menu()
{
	printf("1,打印主菜单\n");
	printf("2,添加联系人\n");
	printf("3,删除联系人\n");
	printf("4,打印通讯录\n");
	printf("5,查找联系人\n");
	printf("6,修改联系人\n");
	printf("7,置顶联系人\n");
	printf("8,联系人排序\n");
	printf("9,退出通讯录\n");
	printf("请选择:");
}

4,增加联系人

为通讯录添加一个联系人。

//增加联系人
void add_people(contact* con)
{
	assert(con);
	system("cls");//为了美观,清屏
	if (con->sz == con->all)
	{
		people* ptr = (people*)realloc(con->peoples, (con->all+oncetime)*sizeof(people));//增加一次扩容的空间
		if (ptr == NULL)
		{
			perror("worning::function::40");
			return 0;
		}
		con->peoples = ptr;
		ptr = NULL;
		memset(con->peoples + con->sz, 0, oncetime * sizeof(people));//把空间初始化为0
		con->all++;
		printf("\n扩容成功\n");
	}
	printf("请输入姓名:");
	scanf("%s", con->peoples[con->sz].name);
	printf("请输入性别:");
	scanf("%s", con->peoples[con->sz].sex);
	printf("请输入年龄:");
	scanf("%d", &con->peoples[con->sz].age);
	printf("请输入电话:");
	scanf("%s", con->peoples[con->sz].tele);
	printf("请输入住址:");
	scanf("%s", con->peoples[con->sz].add);
	con->sz++;
	system("cls");
	printf("添加成功!\n");
}

5,删除联系人

利用查找函数,找到后删除,不要忘记将后面的联系人信息向前移。

//删除联系人
void del_people(contact* con)
{
	assert(con);
	system("cls");
	if (con->sz == 0)
	{
		printf("您的通讯录目前没有联系人\n");
		return;
	}
	printf("请输入您要删除的联系人姓名:");
	char h[10];
	scanf("%s", h);
	int flag = find(con, h);
	if (flag == con->sz)
	{
		printf("您的通讯录中没有名为“%s”的联系人\n", h);
		return;
	}
	memset(con->peoples + flag, 0, sizeof(people));
	int i = 0;
	for (i = flag; i < con->sz-1; i++)
	{
		people tmp = con->peoples[i];
		con->peoples[i] = con->peoples[i + 1];
		con->peoples[i + 1] = tmp;
	}
	con->sz--;
	system("cls");
	printf("删除成功!\n");
}

6,查找联系人

通讯录人太多了怎么办?没关系,你可以使用查找,该函数后面的打印格式将与打印函数模块相同

//查找联系人
void find_people(contact* con)
{
	system("cls");
	if (con->sz == 0)
	{
		printf("您的通讯录目前没有联系人\n");
		return;
	}
	printf("请输入您要查找的联系人姓名:");
	char h[10];
	scanf("%s", h);
	int flag = find(con, h);
	if (flag == con->sz)
	{
		system("cls");
		printf("您的通讯录中没有名为“%s”的联系人\n", h);
		return;
	}
	printf("********************************************\n");
	printf("姓名     性别    年龄  电话       住址\n");
	printf("%-10s%-8s%-6d%-11s%s\n", con->peoples[flag].name, con->peoples[flag].sex, con->peoples[flag].age,
		con->peoples[flag].tele, con->peoples[flag].add);
	printf("********************************************\n");
}

7,修改联系人

老样子,先查找,找到以后让用户再输入一次。

//修改联系人
void change_people(contact* con)
{
	system("cls");
	if (con->sz == 0)
	{
		printf("您的通讯录目前没有联系人\n");
		return;
	}
	printf("请输入您要修改的联系人姓名:");
	char h[10];
	scanf("%s", h);
	int flag = find(con, h);
	if (flag == con->sz)
	{
		printf("您的通讯录中没有名为“%s”的联系人", h);
		return;
	}
	printf("您想将姓名修改为:");
	scanf("%s", con->peoples[flag].name);
	printf("您想将性别修改为:");
	scanf("%s", con->peoples[flag].sex);
	printf("您想将年龄修改为:");
	scanf("%d", &con->peoples[flag].age);
	printf("您想将电话修改为:");
	scanf("%s", con->peoples[flag].tele);
	printf("您想将住址修改为:");
	scanf("%s", con->peoples[flag].add);
	printf("修改完成!\n");
}

8,设置置顶

将联系人设为通讯录的置顶,无论在任何的排序情况下,都会先打印置顶的联系人。当然,你也可以取消置顶。

//设置置顶
void fir_people(contact* con)
{
	system("cls");
	if (con->sz == 0)
	{
		printf("您的通讯录目前没有联系人\n");
		return;
	}
	printf("请输入您要置顶或取消置顶的联系人姓名:");
	char h[10];
	scanf("%s", h);
	int flag = find(con, h);
	if (flag == con->sz)
	{
		printf("您的通讯录中没有名为“%s”的联系人", h);
		return;
	}
	if (con->peoples[flag].first == 1)//成员变量first为1则已经被置顶
	{
		con->peoples[flag].first = 0;
	}
	else if (con->peoples[flag].first == 0)//成员变量first为0则还没被置顶
	{
		con->peoples[flag].first = 1;
	}
	printf("设置成功!\n");
}

9,联系人排序

在此设置了三种排序方式,排序方法利用qsort。

1,性别(先女后男)

2,年龄(由小到大)

3,电话(由小到大)

//联系人排序
int sex_cmp(const void* str1,const void* str2)//性别排序
{
	people* a = (people*)str1;
	people* b = (people*)str2;
	return -strcmp(a->sex, b->sex);
}
int age_cmp(const void* str1, const void* str2)//年龄排序
{
	people* a = (people*)str1;
	people* b = (people*)str2;
	return (a->age - b->age);
}
int tele_cmp(const void* str1, const void* str2)//电话排序
{
	people* a = (people*)str1;
	people* b = (people*)str2;
	return strcmp(a->tele, b->tele);
}
void sort_people(contact* con)
{
	system("cls");
	printf("请选择排序标准\n");
	printf("1,性别\n");
	printf("2,年龄\n");
	printf("3,电话\n");
	printf("请选择:");
	int n = 0;
	scanf("%d", &n);
	if(n==1)
		qsort(con->peoples, con->sz, sizeof(people), sex_cmp);
	else if(n==2)
		qsort(con->peoples, con->sz, sizeof(people), age_cmp);
	else if(n==3)
		qsort(con->peoples, con->sz, sizeof(people), tele_cmp);
	printf("排序成功!\n");
	PRIN_CON(con);
}

10,联系人打印

打印所有的联系人,因为有置顶功能的存在,需要遍历两次,第一次打印被置顶的联系人,第二次打印没有被置顶的联系人,像这样:

//打印通讯录
void PRIN_CON(contact* con)
{
	system("cls");
	if (con->sz == 0)
	{
		printf("您的通讯录目前没有联系人\n");
		return;
	}
	printf("********************************************\n");
	printf("姓名     性别    年龄  电话        住址\n");
	int i = 0;
	for (i = 0; i < con->sz; i++)
	{
		if(con->peoples[i].first==1)
		printf("%-10s%-8s%-6d%-11s%s\n", con->peoples[i].name, con->peoples[i].sex, con->peoples[i].age, 
			con->peoples[i].tele, con->peoples[i].add);
	}
	for (i = 0; i < con->sz; i++)
	{
		if (con->peoples[i].first != 1)
			printf("%-10s%-8s%-6d%-11s%s\n", con->peoples[i].name, con->peoples[i].sex, con->peoples[i].age,
				con->peoples[i].tele, con->peoples[i].add);
	}
	printf("********************************************\n");
}

至于这打印格式,保持一致即可。

三、优化思路

1,查找函数优化

利用strstr实现对信息的检索,就不必死板地搜索全名了,例如你可以搜索“张三”,以此检索在姓名、地址、简介等所有包括“张三”的信息并返回其联系人的信息。

2,额外功能优化

可以额外增加收藏夹,黑名单,群组等等功能,在联系人信息格式里面多加几个变量即可,只是在打印的时候需要多加注意一些相悖的功能,例如进入黑名单后应自动取消置顶、收藏等。且打印时不再打印黑名单内的联系人。

3,打印优化

设置更多的打印方法,例如单独打印黑名单,单独打印置顶,单独打印收藏夹等等。亦可以设置打印打印联系人的某项信息,例如只打印姓名,只打印电话等等。

四、源代码

下面放出源代码,可以直接用哦

1,head.h

#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<Windows.h>
#include<assert.h>
#define init_num_people 10//通讯录初始的人数
#define oncetime 5//通讯录每次扩容增加的人数
#define max_name 10
#define max_sex 4
#define max_tele 11
#define max_add 40
enum MyEnum//对九种通讯录功能进行枚举
{
	MENU = 1,
	ADD,
	DEL,
	PRIN,
	FIND,
	CHANGE,
	FIRST,
	SORT,
	EXIT
};
//创建每个联系人的信息格式
typedef struct
{
	char name[max_name];
	char sex[max_sex];
	int age;
	char tele[max_tele];
	char add[max_add];
	int first;//联系人是否被置顶
}people;
//创建通讯录格式
typedef struct
{
	people* peoples;//用来维护联系人信息的指针
	int	sz;//当前人数
	int all;//总容纳人数
}contact;
//功能函数
void init_con(contact* con);//初始化
void menu();//打印菜单
void PRIN_CON(contact* con);//打印通讯录
void find_people(contact* con);//查找联系人
void change_people(contact* con);//修改联系人
void fir_people(contact* con);//设置置顶
void sort_people(contact* con);//联系人排序
//常用函数
int find(contact* con, const char* name);//查找函数,参数2为需要查找的姓名,若找到返回下标,找不到返回sz

2,sour.c

#include"head.h"
int main()
{
	//创建通讯录
	contact con;
	//初始化
	init_con(&con);
	enum MyEnum input = 0;
	do
	{
		//打印菜单
		menu();
		scanf("%d", &input);
			switch (input)
			{
			case MENU:
				system("cls");//清屏后break,自动打印菜单
				break;
			case ADD:
				add_people(&con);//增加联系人
				break;
			case DEL:
				del_people(&con);//删除联系人
				break;
			case PRIN:
				PRIN_CON(&con);//打印通讯录
				break;
			case FIND:
				find_people(&con);//查找联系人
				break;
			case CHANGE:
				change_people(&con);//修改联系人
				break;
			case FIRST:
				fir_people(&con);//设置置顶
				break;
			case SORT:
				sort_people(&con);//联系人排序
				break;
			case EXIT:
				free(con.peoples);
				con.peoples = NULL;
				system("cls");
				printf("退出通讯录!\n");
				break;
			}
	} while (input-EXIT);//只有选择9才退出
	return 0;
}

3,function.c

#include"head.h"
//初始化
void init_con(contact* con)
{
	assert(con);
	con->peoples = (people*)malloc(init_num_people * sizeof(people));//为联系人信息开辟空间
	if (con->peoples == NULL)
	{
		perror("warning::function::9");//开辟失败报错,显示错误位置
		return 0;
	}
	memset(con->peoples, 0, init_num_people * sizeof(people));//把空间初始化为0
	con->sz = 0;
	con->all = init_num_people;
}
//打印菜单
void menu()
{
	printf("1,打印主菜单\n");
	printf("2,添加联系人\n");
	printf("3,删除联系人\n");
	printf("4,打印通讯录\n");
	printf("5,查找联系人\n");
	printf("6,修改联系人\n");
	printf("7,置顶联系人\n");
	printf("8,联系人排序\n");
	printf("9,退出通讯录\n");
	printf("请选择:");
}
//增加联系人
void add_people(contact* con)
{
	assert(con);
	system("cls");//为了美观,清屏
	if (con->sz == con->all)
	{
		people* ptr = (people*)realloc(con->peoples, (con->all+oncetime)*sizeof(people));//增加一次扩容的空间
		if (ptr == NULL)
		{
			perror("worning::function::40");
			return 0;
		}
		con->peoples = ptr;
		ptr = NULL;
		memset(con->peoples + con->sz, 0, oncetime * sizeof(people));//把空间初始化为0
		con->all++;
		printf("\n扩容成功\n");
	}
	printf("请输入姓名:");
	scanf("%s", con->peoples[con->sz].name);
	printf("请输入性别:");
	scanf("%s", con->peoples[con->sz].sex);
	printf("请输入年龄:");
	scanf("%d", &con->peoples[con->sz].age);
	printf("请输入电话:");
	scanf("%s", con->peoples[con->sz].tele);
	printf("请输入住址:");
	scanf("%s", con->peoples[con->sz].add);
	con->sz++;
	system("cls");
	printf("添加成功!\n");
}
//查找函数,用于通过姓名查找通讯录中的联系人下标,若找到返回下标,若找不到返回sz
int find(contact* con,const char* name)
{
	assert(con);
	int i = 0;
	for (i = 0; i < con->sz; i++)
	{
		if (strcmp(name, con->peoples[i].name) == 0)
		{
			return i;
		}
	}
	return i;
}
//删除联系人
void del_people(contact* con)
{
	assert(con);
	system("cls");
	if (con->sz == 0)
	{
		printf("您的通讯录目前没有联系人\n");
		return;
	}
	printf("请输入您要删除的联系人姓名:");
	char h[10];
	scanf("%s", h);
	int flag = find(con, h);
	if (flag == con->sz)
	{
		printf("您的通讯录中没有名为“%s”的联系人\n", h);
		return;
	}
	memset(con->peoples + flag, 0, sizeof(people));
	int i = 0;
	for (i = flag; i < con->sz-1; i++)
	{
		people tmp = con->peoples[i];
		con->peoples[i] = con->peoples[i + 1];
		con->peoples[i + 1] = tmp;
	}
	con->sz--;
	system("cls");
	printf("删除成功!\n");
}
//打印通讯录
void PRIN_CON(contact* con)
{
	system("cls");
	if (con->sz == 0)
	{
		printf("您的通讯录目前没有联系人\n");
		return;
	}
	printf("********************************************\n");
	printf("姓名     性别    年龄  电话        住址\n");
	int i = 0;
	for (i = 0; i < con->sz; i++)
	{
		if(con->peoples[i].first==1)
		printf("%-10s%-8s%-6d%-11s%s\n", con->peoples[i].name, con->peoples[i].sex, con->peoples[i].age, 
			con->peoples[i].tele, con->peoples[i].add);
	}
	for (i = 0; i < con->sz; i++)
	{
		if (con->peoples[i].first != 1)
			printf("%-10s%-8s%-6d%-11s%s\n", con->peoples[i].name, con->peoples[i].sex, con->peoples[i].age,
				con->peoples[i].tele, con->peoples[i].add);
	}
	printf("********************************************\n");
}
//查找联系人
void find_people(contact* con)
{
	system("cls");
	if (con->sz == 0)
	{
		printf("您的通讯录目前没有联系人\n");
		return;
	}
	printf("请输入您要查找的联系人姓名:");
	char h[10];
	scanf("%s", h);
	int flag = find(con, h);
	if (flag == con->sz)
	{
		system("cls");
		printf("您的通讯录中没有名为“%s”的联系人\n", h);
		return;
	}
	printf("********************************************\n");
	printf("姓名     性别    年龄  电话        住址\n");
	printf("%-10s%-8s%-6d%-11s%s\n", con->peoples[flag].name, con->peoples[flag].sex, con->peoples[flag].age,
		con->peoples[flag].tele, con->peoples[flag].add);
	printf("********************************************\n");
}
//修改联系人
void change_people(contact* con)
{
	system("cls");
	if (con->sz == 0)
	{
		printf("您的通讯录目前没有联系人\n");
		return;
	}
	printf("请输入您要修改的联系人姓名:");
	char h[10];
	scanf("%s", h);
	int flag = find(con, h);
	if (flag == con->sz)
	{
		printf("您的通讯录中没有名为“%s”的联系人", h);
		return;
	}
	printf("您想将姓名修改为:");
	scanf("%s", con->peoples[flag].name);
	printf("您想将性别修改为:");
	scanf("%s", con->peoples[flag].sex);
	printf("您想将年龄修改为:");
	scanf("%d", &con->peoples[flag].age);
	printf("您想将电话修改为:");
	scanf("%s", con->peoples[flag].tele);
	printf("您想将住址修改为:");
	scanf("%s", con->peoples[flag].add);
	printf("修改完成!\n");
}
//设置置顶
void fir_people(contact* con)
{
	system("cls");
	if (con->sz == 0)
	{
		printf("您的通讯录目前没有联系人\n");
		return;
	}
	printf("请输入您要置顶或取消置顶的联系人姓名:");
	char h[10];
	scanf("%s", h);
	int flag = find(con, h);
	if (flag == con->sz)
	{
		printf("您的通讯录中没有名为“%s”的联系人", h);
		return;
	}
	if (con->peoples[flag].first == 1)
	{
		con->peoples[flag].first = 0;
	}
	else if (con->peoples[flag].first == 0)
	{
		con->peoples[flag].first = 1;
	}
	printf("设置成功!\n");
}
//联系人排序
int sex_cmp(const void* str1,const void* str2)//性别排序
{
	people* a = (people*)str1;
	people* b = (people*)str2;
	return -strcmp(a->sex, b->sex);
}
int age_cmp(const void* str1, const void* str2)//年龄排序
{
	people* a = (people*)str1;
	people* b = (people*)str2;
	return (a->age - b->age);
}
int tele_cmp(const void* str1, const void* str2)//电话排序
{
	people* a = (people*)str1;
	people* b = (people*)str2;
	return strcmp(a->tele, b->tele);
}
void sort_people(contact* con)
{
	system("cls");
	printf("请选择排序标准\n");
	printf("1,性别\n");
	printf("2,年龄\n");
	printf("3,电话\n");
	printf("请选择:");
	int n = 0;
	scanf("%d", &n);
	if(n==1)
		qsort(con->peoples, con->sz, sizeof(people), sex_cmp);
	else if(n==2)
		qsort(con->peoples, con->sz, sizeof(people), age_cmp);
	else if(n==3)
		qsort(con->peoples, con->sz, sizeof(people), tele_cmp);
	printf("排序成功!\n");
	PRIN_CON(con);
}

以上就是C语言多功能动态通讯录实现示例的详细内容,更多关于C语言多功能动态通讯录的资料请关注编程网其它相关文章!

阅读原文内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     813人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     354人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     318人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     435人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     224人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-后端开发
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯