通讯录的动态设计

目录

前言

1.主函数

1.1菜单

1.2主体函数的设计

1.3结构体成员的设计

2.通讯录的功能是实现

2.1通讯录的初始化

2.2增加通讯录成员

2.3通讯录成员的删除

2.4通讯录成员的查找

2.5 通讯录成员的修改

2.6通讯录成员的打印 

2.7对通讯录成员的排序 

2.8通讯录的销毁

3.整体代码 

contact.c

contact.h

 test.c


前言

通讯录的设计设计的知识点主要包括:结构体、枚举、指针、等知识点。首先我们要设计出通讯录的整体框架及其功能,其中储存的信息分别是什么。一个人的信息包括:名字、性别、年龄、电话、住址等;通讯录的功能有:增、删、差、改、显示、排序等。我们按照以上思路对通讯录进行实现。

1.主函数

1.1菜单

为了让使用者对本通讯录功能的了解,我们设计出一个菜单方便用户了解并进行使用。

void menu()
{
	printf("******************************************\n");
	printf("*****     1.Add           2. Del     *****\n");
	printf("*****     3.Sreach        4. Modify  *****\n");
	printf("*****     5.Show          6. Sort    *****\n");
	printf("*****     0.Exit                     *****\n");
	printf("******************************************\n");
}

1.2主体函数的设计

基于我们对枚举类型的了解,在函数设计中我们加入枚举类型,以此来增加函数的可读性。

enum
{
	Exit,     //0
	Add,      //1
	Del,      //2
	Sreach,   //3
	Modify,   //4
	Show,     //5
	Sort      //6
};

void test()
{
	menu();
	Contact con;
	InitContact(&con);

	int input = 0;
	do
	{
		printf("请输入要选择的模式:>");
		scanf("%d", &input);
		switch (input)
		{
		case Add:
			AddContact(&con);
			break;
		case Del:
			DelContact(&con);
			break;
		case Sreach:
			SreachContact(&con);
			break;
		case Modify:
			ModifyContact(&con);
			break;
		case Show:
			ShowContact(&con);
			break;
		case Sort:
			SortContact(&con);
			break;
		case Exit:
			printf("退出通讯录\n");
			DestroyContact(&con);
			break;
		default:
			printf("输入错误,请重新输入\n");
			break;
		}
		system("cls");
	} while (input);

}

int main()
{
	test();
	return 0;
}

1.3结构体成员的设计

我们使用结构体,可以结构体中存入多个成员,为了方便代码的书写,加入了typedef对结构体进行重命名。并且在静态创建空间时,为了后续的空间维护,使用了宏来定义一些特殊的数字。也可以使用动态创建空间,避免了空间浪费的问题。

#define MAX 100
#define Name_Max 20
#define Tele_Max 12
#define Sex_Max 5
#define Addr_Max 30

#define INIT_Max 3

typedef struct Informatio
{
	char name[Name_Max];
	int age;
	char tele[Tele_Max];
	char sex[Sex_Max];
	char addr[Addr_Max];
}Infor;

//静态的方法
//typedef struct contact
//{
//	Infor data[MAX];
//	int sz;
//}Contact;

//动态创建
typedef struct contact
{
	Infor *data;
	int capacity;//记录当前容量
	int sz;//记录当前个数
}Contact;

2.通讯录的功能是实现

2.1通讯录的初始化

静态初始化通讯录,使用memset将通讯录的元素设置为0,并将通讯录当前长度设置为0;

动态初始化通讯录,使用malloc函数动态创建空间,将初始空间的大小设为3,同时将长度设置为0,容量设置为3。

初始化通讯录--静态
//void InitContact(Contact* con)
//{
//	memset(con->data, 0,sizeof(con->data));
//	con->sz = 0;  //通讯录中元素的个数
//}

//动态初始化通讯录
void InitContact(Contact* con)
{
	con->data = (Infor*)malloc(INIT_Max * sizeof(Infor));
	if (con->data == NULL)
	{
		return;
	}
	con->sz = 0;                //当前长度
	con->capacity = INIT_Max;  //当前容量
}

2.2增加通讯录成员

在增加通讯录成员的过程中我们首先要对通讯录的容量进行检查,静态数组检查当前长度与最大长度的对比,如果两个相等,直接退出,而动态数组则检查当前长度与容量,如果两个相等,使用realloc函数对容量进行扩充。容量没有问题的情况下,将要添加的输入到当前sz的位置。


//检查容量
void Check_Contact(Contact* con)
{
	if (con->sz == con->capacity)
	{
		Infor* ptr = realloc(con->data, (con->capacity + 2) * sizeof(Infor));
		if (ptr == NULL)
		{
			printf("增容失败\n");
		}
		else
		{
			con->data = ptr;
			con->capacity += 2;
			printf("增容成功\n");
		}
	}
}



//增加通讯录
void AddContact(Contact* con)
{
	assert(con);
	Check_Contact(con);
	printf("请输入名字:>");
	scanf("%s", con->data[con->sz].name);
	printf("请输入年龄:>");
	scanf("%d", &(con->data[con->sz].age));
	printf("请输入性别:>");
	scanf("%s", con->data[con->sz].sex);
	printf("请输入电话:>");
	scanf("%s", con->data[con->sz].tele);
	printf("请输入地址:>");
	scanf("%s", con->data[con->sz].addr);

	con->sz++;//长度++
	printf("成功增加联系人\n");

}

2.3通讯录成员的删除

在删除成员时,优先考虑通讯录当前是否为空,为空直接退出,不为空创建一个字符数组用来储存要删除成员的姓名,封装一个FindByName函数用于查找当前通讯录中是否有此成员,找到要删除的成员,将其后面的所有成员向前移动一位将其覆盖,并将sz减1。

//查找通讯录的成员
static int FindByName(const Contact* con, char name[])
{
	int i = 0;
	for (i = 0; i < con->sz; i++)
	{
		if (strcmp(con->data[i].name, name) == 0)
		{
			return i;//找到了
		}
	}
	return -1;//找不到
}

//删除通讯录中的元素
void DelContact(Contact* con)
{
	if (con->sz == 0)
	{
		printf("通讯录为空,无法删除\n");
		return;
	}
	assert(con);
	char name[Name_Max] = { 0 }; //储存要删除成员的名字
	printf("请输入要删除人的名字:>");
	scanf("%s", name);
	int ret = FindByName(con, name);
	if (ret == -1)
	{
		printf("查无此人\n");
		return;
	}
	for (int i=ret; i < con->sz-1; i++)
	{
		con->data[i] = con->data[i + 1];
	}
	con->sz--;
	printf("删除成功\n");
}

2.4通讯录成员的查找

使用封装好的FindByName函数对通讯录中的元素进行查找,并返回查找到的元素长度,在屏幕中打印出来。

//查找通讯录的人员
void SreachContact(Contact* con)
{
	assert(con);

	char name[Name_Max] = { 0 };
	printf("请输入要查找人的名字:>");
	scanf("%s", name);
	int ret = FindByName(con, name);
	if (ret == -1)
		printf("要查找的人不存在\n");
	else
	{
		printf("%-10s\t%-5s\t%-5s\t%-12s\t%-30s\n", "名字", "年龄", "性别", "电话", "地址");
		//打印数据
		printf("%-10s\t%-5d\t%-5s\t%-12s\t%-30s\n",
			con->data[ret].name,
			con->data[ret].age,
			con->data[ret].sex,
			con->data[ret].tele,
			con->data[ret].addr);
	}
}

2.5 通讯录成员的修改

在上面通讯录查找的基础上,找到要查找人员所在的长度将其中的所有内容将其修改,也可以建立一个菜单,写上通讯录中的姓名、地址等精准打击修改,可参照2.7通讯录的排序。

void ModifyContact(Contact* con)
{
	assert(con);
	char name[Name_Max] = { 0 };
	printf("请输入修改人的名字:>");
	scanf("%s", name);
	int ret = FindByName(con, name);
	if (ret == -1)
		printf("要查找的人不存在\n");
	else
	{
		printf("请输入名字:>");
		scanf("%s", con->data[ret].name);
		printf("请输入年龄:>");
		scanf("%d", &(con->data[ret].age));
		printf("请输入性别:>");
		scanf("%s", con->data[ret].sex);
		printf("请输入电话:>");
		scanf("%s", con->data[ret].tele);
		printf("请输入地址:>");
		scanf("%s", con->data[ret].addr);



		printf("修改成功\n");
	}
}

2.6通讯录成员的打印 

用for循环将通讯录的元素进行打印。

void ShowContact(Contact* con)
{
	assert(con);
	//打印标题
	printf("%-10s\t%-5s\t%-10s\t%-12s\t%-30s\n", "名字", "年龄", "性别", "电话", "地址");
	for (int i = 0; i < con->sz; i++)
	{
		printf("%-10s\t%-5d\t%-10s\t%-12s\t%-30s\n", 
			con->data[i].name,
			con->data[i].age,
			con->data[i].sex,
			con->data[i].tele,
			con->data[i].addr);
	}
}

2.7对通讯录成员的排序 

在其中建立菜单,让用户选择想要的排序方式,使用qsort对通讯录中的元素进行排序。

//按照年龄
int cmp_age(void* str1,void* str2)
{
	//return *(char*)str1 - *(char*)str2;
	return *(int*)str1 - *(int*)str2;
}

//按照姓名
int cmp_name(void* str1, void* str2)
{
	return *(char*)str1 - *(char*)str2;
}

//按照地址
int  cmp_addr(void* str1, void* str2)
{
	return *(char*)str1 - *(char*)str2;
}

void menu1()
{
	printf("****************************\n");
	printf("******     1.name     ******\n");
	printf("******     2.age      ******\n");
	printf("******     3.addr     ******\n");
	printf("******     0.exit     ******\n");
	printf("****************************\n");

}

//排序
void SortContact(Contact* con)
{
	//qsort(con->data, con->sz, sizeof(con->data[0]), cmp_age);
	menu1();
	int input = 0;
	printf("请输入要排序的模式:>");
	scanf("%d", &input);
	switch (input)
	{
	case 1://姓名
		qsort(con->data, con->sz, sizeof(con->data[0]), cmp_name);
		break;
	case 2://年龄
		qsort(con->data, con->sz, sizeof(con->data[0]), cmp_age);
		break;
	case 3://住址
		qsort(con->data, con->sz, sizeof(con->data[0]), cmp_addr);
		break;
	case 0:
		break;
	default:
		printf("输入错误!!!\n");
		break;
	}
	ShowContact(con);
}

2.8通讯录的销毁

我们在使用malloc和realloc动态创建通讯录的空间后,在结束程序时要对创建的空间进行销毁,并将指针指向NULL,否则就会造成内存泄露。

void DestroyContact(Contact* pc)
{
	free(pc->data);
	pc->data = NULL;
	pc->capacity = 0;
	pc->sz = 0;
}

3.整体代码 

contact.c

#define _CRT_SECURE_NO_WARNINGS 1
#include"contact.h"

初始化通讯录--静态
//void InitContact(Contact* con)
//{
//	memset(con->data, 0,sizeof(con->data));
//	con->sz = 0;
//}

//动态初始化通讯录
void InitContact(Contact* con)
{
	con->data = (Infor*)malloc(INIT_Max * sizeof(Infor));
	if (con->data == NULL)
	{
		return;
	}
	con->sz = 0;
	con->capacity = INIT_Max;
}

//检查容量
void Check_Contact(Contact* con)
{
	if (con->sz == con->capacity)
	{
		Infor* ptr = realloc(con->data, (con->capacity + 2) * sizeof(Infor));
		if (ptr == NULL)
		{
			printf("增容失败\n");
		}
		else
		{
			con->data = ptr;
			con->capacity += 2;
			printf("增容成功\n");
		}
	}
}

//增加通讯录
void AddContact(Contact* con)
{
	assert(con);
	Check_Contact(con);
	printf("请输入名字:>");
	scanf("%s", con->data[con->sz].name);
	printf("请输入年龄:>");
	scanf("%d", &(con->data[con->sz].age));
	printf("请输入性别:>");
	scanf("%s", con->data[con->sz].sex);
	printf("请输入电话:>");
	scanf("%s", con->data[con->sz].tele);
	printf("请输入地址:>");
	scanf("%s", con->data[con->sz].addr);
	//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);

	con->sz++;

	printf("成功增加联系人\n");

}

//判断字符串是否为空
int FindContact(Contact* con)
{
	if (con->sz == 0)
	{
		return 0;
	}
	return 1;
}

//打印通讯录
void ShowContact(Contact* con)
{
	assert(con);
	//打印标题
	printf("%-10s\t%-5s\t%-10s\t%-12s\t%-30s\n", "名字", "年龄", "性别", "电话", "地址");
	for (int i = 0; i < con->sz; i++)
	{
		printf("%-10s\t%-5d\t%-10s\t%-12s\t%-30s\n", 
			con->data[i].name,
			con->data[i].age,
			con->data[i].sex,
			con->data[i].tele,
			con->data[i].addr);
	}
}

static int FindByName(const Contact* con, char name[])
{
	int i = 0;
	for (i = 0; i < con->sz; i++)
	{
		if (strcmp(con->data[i].name, name) == 0)
		{
			return i;//找到了
		}
	}
	return -1;//找不到
}

//删除通讯录中的元素
void DelContact(Contact* con)
{
	if (con->sz == 0)
	{
		printf("通讯录为空,无法删除\n");
		return;
	}
	assert(con);
	char name[Name_Max] = { 0 };
	printf("请输入要删除人的名字:>");
	scanf("%s", name);
	int ret = FindByName(con, name);
	if (ret == -1)
	{
		printf("查无此人\n");
		return;
	}
	for (int i=ret; i < con->sz-1; i++)
	{
		con->data[i] = con->data[i + 1];
	}
	con->sz--;
	printf("删除成功\n");
}

//查找通讯录的人员
void SreachContact(Contact* con)
{
	assert(con);

	char name[Name_Max] = { 0 };
	printf("请输入要查找人的名字:>");
	scanf("%s", name);
	int ret = FindByName(con, name);
	if (ret == -1)
		printf("要查找的人不存在\n");
	else
	{
		printf("%-10s\t%-5s\t%-5s\t%-12s\t%-30s\n", "名字", "年龄", "性别", "电话", "地址");
		//打印数据
		printf("%-10s\t%-5d\t%-5s\t%-12s\t%-30s\n",
			con->data[ret].name,
			con->data[ret].age,
			con->data[ret].sex,
			con->data[ret].tele,
			con->data[ret].addr);
	}
}

//修改通讯录信息
void ModifyContact(Contact* con)
{
	assert(con);
	char name[Name_Max] = { 0 };
	printf("请输入修改人的名字:>");
	scanf("%s", name);
	int ret = FindByName(con, name);
	if (ret == -1)
		printf("要查找的人不存在\n");
	else
	{
		printf("请输入名字:>");
		scanf("%s", con->data[ret].name);
		printf("请输入年龄:>");
		scanf("%d", &(con->data[ret].age));
		printf("请输入性别:>");
		scanf("%s", con->data[ret].sex);
		printf("请输入电话:>");
		scanf("%s", con->data[ret].tele);
		printf("请输入地址:>");
		scanf("%s", con->data[ret].addr);



		printf("修改成功\n");
	}
}

int cmp_age(void* str1,void* str2)
{
	//return *(char*)str1 - *(char*)str2;
	return *(int*)str1 - *(int*)str2;
}

int cmp_name(void* str1, void* str2)
{
	return *(char*)str1 - *(char*)str2;
}

int  cmp_addr(void* str1, void* str2)
{
	return *(char*)str1 - *(char*)str2;
}
void menu1()
{
	printf("****************************\n");
	printf("******     1.name     ******\n");
	printf("******     2.age      ******\n");
	printf("******     3.addr     ******\n");
	printf("******     0.exit     ******\n");
	printf("****************************\n");

}
//排序
void SortContact(Contact* con)
{
	//qsort(con->data, con->sz, sizeof(con->data[0]), cmp_age);
	menu1();
	int input = 0;
	printf("请输入要排序的模式:>");
	scanf("%d", &input);
	switch (input)
	{
	case 1://姓名
		qsort(con->data, con->sz, sizeof(con->data[0]), cmp_name);
		break;
	case 2://年龄
		qsort(con->data, con->sz, sizeof(con->data[0]), cmp_age);
		break;
	case 3://住址
		qsort(con->data, con->sz, sizeof(con->data[0]), cmp_addr);
		break;
	case 0:
		break;
	default:
		printf("输入错误!!!\n");
		break;
	}
	ShowContact(con);
}

void DestroyContact(Contact* pc)
{
	free(pc->data);
	pc->data = NULL;
	pc->capacity = 0;
	pc->sz = 0;
}

contact.h

#pragma once


#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<assert.h>

#define MAX 100
#define Name_Max 20
#define Tele_Max 12
#define Sex_Max 5
#define Addr_Max 30

#define INIT_Max 3



typedef struct Informatio
{
	char name[Name_Max];
	int age;
	char tele[Tele_Max];
	char sex[Sex_Max];
	char addr[Addr_Max];
}Infor;

//静态的方法
//typedef struct contact
//{
//	Infor data[MAX];
//	int sz;
//}Contact;

//动态创建
typedef struct contact
{
	Infor *data;
	int capacity;//记录当前容量
	int sz;//记录当前个数
}Contact;

enum
{
	Exit,     //0
	Add,      //1
	Del,      //2
	Sreach,   //3
	Modify,   //4
	Show,     //5
	Sort      //6
};

//初始化通讯录
void InitContact(Contact* con);
//通讯录增加
void AddContact(Contact* con);
//打印通讯录
void ShowContact(Contact* con);
//删除通讯录中的元素
void DelContact(Contact* con);
//查找通讯录的人员
void SreachContact(Contact* con);
//修改通讯录信息
void ModifyContact(Contact* con);
//排序
void SortContact(Contact* con);
//通讯录的销毁
void DestroyContact(Contact* pc);


 test.c

#define _CRT_SECURE_NO_WARNINGS 1

#include"contact.h"

void menu()
{
	printf("******************************************\n");
	printf("*****     1.Add           2. Del     *****\n");
	printf("*****     3.Sreach        4. Modify  *****\n");
	printf("*****     5.Show          6. Sort    *****\n");
	printf("*****     0.Exit                     *****\n");
	printf("******************************************\n");
}

void test()
{
	menu();
	Contact con;
	InitContact(&con);

	int input = 0;
	do
	{
		printf("请输入要选择的模式:>");
		scanf("%d", &input);
		switch (input)
		{
		case Add:
			AddContact(&con);
			break;
		case Del:
			DelContact(&con);
			break;
		case Sreach:
			SreachContact(&con);
			break;
		case Modify:
			ModifyContact(&con);
			break;
		case Show:
			ShowContact(&con);
			break;
		case Sort:
			SortContact(&con);
			ShowContact(&con);
			break;
		case Exit:
			printf("退出通讯录\n");
			DestroyContact(&con);
			break;
		default:
			printf("输入错误,请重新输入\n");
			break;
		}
	} while (input);

}
int main()
{
	test();
	return 0;
}

  • 5
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 6
    评论
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值