【异世界历险之数据结构世界(通讯录)】

异世界历险之数据结构世界(通讯录)

前言

异世界公历25年3月21日,冒险者小Y走进了草丛,(一阵强劲的音乐)野生的通讯录跳出来了,小Y开始战斗吧!!!

通讯录介绍

通讯录是名字,性别,年龄,地址,电话号码等数据集合,与顺序表的功能不谋而合.

通讯录实现

具体实现方法可以参考顺序表:异世界历险之数据结构世界(顺序表城)

ps:图片中SORT是5,SHOW是6(作者笔误)

1.前置准备

**逻辑解释:

在实现通讯录之前,我们需要定义联系人信息的结构体,并使用宏定义来设置各个字段的最大长度。此外,我们还需要定义通讯录的结构体,包括动态数组、容量和大小等属性。

Contact.h

#pragma once

#define NAME_MAX 6
#define GENDER_MAX 4
#define TEL_MAX 20
#define ADDR_MAX 20//宏定义利于区分和修改

struct personInfo
{
	char name[NAME_MAX];
	char gender[GENDER_MAX];
	int age;
	char tel[TEL_MAX];
	char addr[ADDR_MAX];
};//定义联系人类型,和 int,char等类型类似

typedef struct personInfo peoInfo;//简化类型

struct Contact
{
	peoInfo* data;
	int capacity;
	int size;
};//与顺序表类似,但储存数据类型不同(一个int,一个peoInfo)

typedef struct Contact Contact;

enum OPPTION
{
	EXIT,
	ADD,
	DEL,
	SEARCH,
	MODIFY,
	SORT,
	SHOW
};//枚举类型使代码可读性提高
test.c
# include"Contact.h"

void menu()
{
	printf("**************************\n");
	printf("******1.ADD    2.DEL******\n");
	printf("******3.SEARCH 4.MODIFY***\n");
	printf("******5.SORT   6.SHOW*****\n");
	printf("**********0.EXIT**********\n");
	printf("**************************\n");
}
int main()
{
	int input = 0;
	do
	{
		void menu();
		printf("输入你的选择\n");
		scanf("%d", &input);
		switch(input)
		{
		case ADD:

			break;
		case DEL:

			break;
		case SEARCH:

			break;
		case MODIFY:

			break;
		case SORT:

			break;
		case SHOW:

			break;
		case EXIT:

			break;
		default :
			printf("输入错误,重新输入!!!\n");
			break;
		}

	} while (input);

}//基础界面和操作选择

PS:读者要牢记自定义类型peoInfo和int,char等系统自带类型无异这一前提.

2定义与初始化

逻辑解释:

初始化通讯录的逻辑是将动态数组置为空,并将容量和大小初始化为0。

//初始化函数
void ContactInit(Contact* ps)
{   assert(ps);
	ps-> data = NULL;
	ps->capacity = ps->size = 0;
}

3.添加联系人

**逻辑解释:

添加联系人之前,需要检查动态数组的容量是否足够。如果容量不足,则需要动态扩容。扩容的策略是将容量翻倍,以确保有足够的空间存储新的联系人。

//空间检查函数
void CheckCapacity(Contact*ps)
{
	assert(ps);
	if (ps->capacity ==ps->size)
	{
		int newcapacity = 0;
		newcapacity = ps->capacity == 0 ? 8 : 2 * ps->capacity;//三目操作符
		peoInfo* str = (peoInfo*)malloc(sizeof(peoInfo) * newcapacity);
		if (str == NULL)
		{
			perror("malloc fail !!!");
			exit(1);
		}
		ps->data = str;
		ps->capacity = newcapacity;//模式化处理

	}
}
//添加函数
void ContactAdd(Contact* ps)
{
	assert(ps);
	CheckCapacity(ps);//先判断空间大小,再进行添加
	printf("输入名字:\n");
	scanf("%s", ps->data[ps->size].name);

	printf("输入性别:\n");
	scanf("%s", ps->data[ps->size].gender);

	printf("输入年龄:\n");
	scanf("%d", &ps->data[ps->size].age);

	printf("输入电话号码:\n");
	scanf("%s", ps->data[ps->size].tel);

	printf("输入地址:\n");
	scanf("%s", ps->data[ps->size].addr);

	ps->size++;
}

PS:除年龄外其余的元素都没有取地址,是因为字符串首元素就是地址。

效果展示:添加展示

4.删除联系人

逻辑解释:

删除联系人需要先通过名字查找目标联系人。如果找到,则将目标联系人之后的所有联系人向前移动一位,覆盖目标联系人,然后减少通讯录的大小。

//查找函数
int ContactFind(Contact* ps, char name[])
{
	for (int i = 0; i < ps->size; i++)
	{
		if (strcmp(ps->data[i].name,name)==0)//字符串只能strcmp函数比较
		{
			return i;
		}
	}
	return -1;
}
//删除函数
void ContactDel(Contact* ps)
{
	if (ps->size == 0)
	{  
		printf("联系人为空,无法删除!!!\n");
		return;
	}
	printf("请输入删除人员名字:\n");//使用名字查找
	char name[NAME_MAX];
	scanf("%s", name);
	int pos = ContactFind(ps,name);//查找函数
	if (pos == -1)
	{
		printf("删除的人不存在!!!\n");
	}
	else
	{
		for (int i = pos; i < ps ->size-1; i++)
		{
			ps->data[i] = ps->data[i + 1];
		}//前进一位,覆盖要删除对象
		ps->size--;
		printf("删除成功!!!\n");
	}
}

效果展示:删除展示

5.查找联系人

逻辑解释:

查找联系人通过名字进行匹配。如果找到,则打印该联系人的详细信息;否则提示未找到。

//查找函数
void ContactSearch(Contact* ps)
{
	if (ps->size == 0)
	{
		printf("联系人为空,无法查找!!!\n");
		return;
    }
	printf("请输入要查找的名字:\n");
	char name[NAME_MAX];
	scanf("%s", name);
	int pos = ContactFind(ps, name);
	if (pos == -1)
	{
		printf("没有该联系人!!!\n");
	}
	else
	{   
		printf("%-6s\t%-4s\t%-5s\t%-12s\t%-30s\n", "名字", "性别", "年龄", "电话", "地址");
		printf("%-6s\t%-4s\t%-5d\t%-12s\t%-30s\n",
			ps->data[pos].name,
			ps->data[pos].gender,
			ps->data[pos].age,
			ps->data[pos].tel,
			ps->data[pos].addr
		);
	}
}

效果展示:
查找函数

6.修改联系人

逻辑解释:

修改联系人信息需要先通过名字查找目标联系人。如果找到,则更新该联系人的所有信息。

//修改函数
void ContactModify(Contact* ps)
{
	if (ps->size == 0)
	{
		printf("联系人为空,无法修改!!!\n");
		return;
	}
	printf("请输入要修改的名字:\n");
	char name[NAME_MAX];
	scanf("%s", name);
	int pos = ContactFind(ps, name);
	if (pos == -1)
	{
		printf("没有该联系人\n");
		return;
	}
	else
	{
		printf("开始修改…………\n");
		printf("请输入名字:\n");
		scanf("%s", ps->data[pos].name);

		printf("请输入年龄:\n");
		scanf("%d", &ps->data[pos].age);

		printf("请输入性别:\n");
		scanf("%s", ps->data[pos].gender);

		printf("请输入电话:\n");
		scanf("%s", ps->data[pos].tel);

		printf("请输入地址:\n");
		scanf("%s", ps->data[pos].addr);

		printf("成功输入联系人!!!\n");
	}
}

效果展示:
修改展示

7.排序联系人

逻辑解释:

排序功能使用快速排序算法,可以根据名字或年龄对联系人进行排序。

//比较
void cmp_name(const void* str1,const void* str2)
{
	return strcmp(((peoInfo*)str1)->name, ((peoInfo*)str2)->name);
}

void cmp_age(const void* str1, void* str2)
{
	return ((peoInfo*)str1)->age - ((peoInfo*)str2)->age;
}
//排序函数
void ContactSort(Contact* ps)
{
	 assert(ps);
	if (ps->size == 0)
	{
		printf("联系人为空,无法排序!!!\n");
		return;
	}
	qsort(ps->data, ps->size, sizeof(peoInfo), cmp_name);//快速排序(name)
	printf("排序成功!!!\n");
	//qsort(ps, ps->size, sizeof(peoInfo), cmp_age);//快速排序(age)
	//………………

}

效果展示:
排序展示

8.展开联系人列表

逻辑解释:

展示所有联系人的信息,按照名字、性别、年龄、电话和地址的顺序打印。

//展示函数
void ContactShow(Contact* ps)
{
	assert(ps);
	printf("%-6s\t%-4s\t%-5s\t%-12s\t%-30s\n", "名字", "性别", "年龄", "电话", "地址");
	for (int i = 0; i < ps->size; i++)
	{   
		printf("%-6s\t%-4s\t%-5d\t%-12s\t%-30s\n",
			ps->data[i].name,
			ps->data[i].gender,
			ps->data[i].age,
			ps->data[i].tel,
			ps->data[i].addr
		);

	}
}

9.销毁联系人

逻辑解释:

销毁功能释放动态数组的内存,并将通讯录重置为空。

void ContactDestory(Contact* ps)
{
	if (ps->data)
	{
		free(ps->data);
	}
	ps->data = NULL;
	ps->capacity = ps->size = 0;

}

总结(代码展示)

Contact.h
#pragma once
# include<stdio.h>
# include<assert.h>
# include<stdlib.h>
# include<string.h>
#define NAME_MAX 10
#define GENDER_MAX 8
#define TEL_MAX 20
#define ADDR_MAX 20//宏定义利于区分和修改

struct personInfo
{
	char name[NAME_MAX];
	char gender[GENDER_MAX];
	int age;
	char tel[TEL_MAX];
	char addr[ADDR_MAX];
};//定义联系人类型,和 int,char等类型类似

typedef struct personInfo peoInfo;//简化类型

struct Contact
{
	peoInfo* data;
	int capacity;
	int size;
};//与顺序表类似,但储存数据类型不同(一个int,一个peoInfo)

typedef struct Contact Contact;

enum OPPTION
{
	EXIT,
	ADD,
	DEL,
	SEARCH,
	MODIFY,
	SORT,
	SHOW
};//枚举类型使代码可读性提高

//初始化
void ContactInit(Contact* ps);

//添加
void ContactAdd(Contact* ps);

//删除
void ContactDel(Contact* ps); 

//修改
void ContactSearch(Contact* ps);

//查找
void ContactSearch(Contact* ps);

//排序
void ContactSort(Contact* ps);

//展示
void ContactShow(Contact* ps);

//销毁

void ContactDestory(Contact* ps);


Contact.c
#include"Contact.h"

//初始化函数
void ContactInit(Contact* ps)
{
	assert(ps);
	ps-> data = NULL;
	ps->capacity = ps->size = 0;
}


//空间检查函数
void CheckCapacity(Contact*ps)
{
	assert(ps);
	if (ps->capacity ==ps->size)
	{
		int newcapacity = 0;
		newcapacity = ps->capacity == 0 ? 8 : 2 * ps->capacity;//三目操作符
		peoInfo* str = (peoInfo*)malloc(sizeof(peoInfo) * newcapacity);
		if (str == NULL)
		{
			perror("malloc fail !!!");
			exit(1);
		}
		ps->data = str;
		ps->capacity = newcapacity;//模式化处理

	}
}

//寻找函数
int ContactFind(Contact* ps, char name[])
{
	for (int i = 0; i < ps->size; i++)
	{
		if (strcmp(ps->data[i].name,name)==0)//字符串只能strcmp函数比较
		{
			return i;
		}
	}
	return -1;
}


//排序
void cmp_name(const void* str1,const void* str2)
{
	return strcmp(((peoInfo*)str1)->name, ((peoInfo*)str2)->name);
}

void cmp_age(const void* str1, void* str2)
{
	return ((peoInfo*)str1)->age - ((peoInfo*)str2)->age;
}

//添加函数
void ContactAdd(Contact* ps)
{
	assert(ps);
	CheckCapacity(ps);
	printf("输入名字:\n");
	scanf("%s", ps->data[ps->size].name);

	printf("输入性别:\n");
	scanf("%s", ps->data[ps->size].gender);

	printf("输入年龄:\n");
	scanf("%d", &ps->data[ps->size].age);

	printf("输入电话号码:\n");
	scanf("%s", ps->data[ps->size].tel);

	printf("输入地址:\n");
	scanf("%s", ps->data[ps->size].addr);

	ps->size++;
}



//展示函数
void ContactShow(Contact* ps)
{
	assert(ps);
	printf("%-6s\t%-4s\t%-5s\t%-12s\t%-30s\n", "名字", "性别", "年龄", "电话", "地址");
	for (int i = 0; i < ps->size; i++)
	{   
		printf("%-6s\t%-4s\t%-5d\t%-12s\t%-30s\n",
			ps->data[i].name,
			ps->data[i].gender,
			ps->data[i].age,
			ps->data[i].tel,
			ps->data[i].addr
		);

	}
}


//删除函数
void ContactDel(Contact* ps)
{
	if (ps->size == 0)
	{  
		printf("联系人为空,无法删除!!!\n");
		return;
	}
	printf("请输入删除人员名字:\n");//使用名字查找
	char name[NAME_MAX];
	scanf("%s", name);
	int pos = ContactFind(ps,name);
	if (pos == -1)
	{
		printf("删除的人不存在!!!\n");
	}
	else
	{
		for (int i = pos; i < ps ->size-1; i++)
		{
			ps->data[i] = ps->data[i + 1];
		}
		ps->size--;
		printf("删除成功!!!\n");
	}
}

//查找函数
void ContactSearch(Contact* ps)
{
	if (ps->size == 0)
	{
		printf("联系人为空,无法查找!!!\n");
		return;
    }
	printf("请输入要查找的名字:\n");
	char name[NAME_MAX];
	scanf("%s", name);
	int pos = ContactFind(ps, name);
	if (pos == -1)
	{
		printf("没有该联系人!!!\n");
	}
	else
	{   
		printf("%-6s\t%-4s\t%-5s\t%-12s\t%-30s\n", "名字", "性别", "年龄", "电话", "地址");
		printf("%-6s\t%-4s\t%-5d\t%-12s\t%-30s\n",
			ps->data[pos].name,
			ps->data[pos].gender,
			ps->data[pos].age,
			ps->data[pos].tel,
			ps->data[pos].addr
		);
	}
}


//修改函数
void ContactModify(Contact* ps)
{
	if (ps->size == 0)
	{
		printf("联系人为空,无法修改!!!\n");
		return;
	}
	printf("请输入要修改的名字:\n");
	char name[NAME_MAX];
	scanf("%s", name);
	int pos = ContactFind(ps, name);
	if (pos == -1)
	{
		printf("没有该联系人\n");
		return;
	}
	else
	{
		printf("开始修改…………\n");
		printf("请输入名字:\n");
		scanf("%s", ps->data[pos].name);

		printf("请输入年龄:\n");
		scanf("%d", &ps->data[pos].age);

		printf("请输入性别:\n");
		scanf("%s", ps->data[pos].gender);

		printf("请输入电话:\n");
		scanf("%s", ps->data[pos].tel);

		printf("请输入地址:\n");
		scanf("%s", ps->data[pos].addr);

		printf("成功输入联系人!!!\n");
	}
}


//排序函数
void ContactSort(Contact* ps)
{
	 assert(ps);
	if (ps->size == 0)
	{
		printf("联系人为空,无法排序!!!\n");
		return;
	}
	qsort(ps->data, ps->size, sizeof(peoInfo), cmp_name);//快速排序(name)
	printf("排序成功!!!\n");
	//qsort(ps, ps->size, sizeof(peoInfo), cmp_age);//快速排序(age)
	//………………

}


//销毁

void ContactDestory(Contact* ps)
{
	if (ps->data)
	{
		free(ps->data);
	}
	ps->data = NULL;
	ps->capacity = ps->size = 0;

}
test.c
# include"Contact.h"

void menu()
{
	
	printf("**************************\n");
	printf("******1.ADD    2.DEL******\n");
	printf("******3.SEARCH 4.MODIFY***\n");
	printf("******6.SORT   6.SHOW*****\n");
	printf("**********0.EXIT**********\n");
	printf("**************************\n");
}
int main()
{
	int input = 0;
	Contact plist;
	ContactInit(&plist);
	do
	{
		 menu();
		printf("输入你的选择:\n");
		scanf("%d", &input);
		switch(input)
		{
		case ADD:
			ContactAdd(&plist);
			break;
		case DEL:
			ContactDel(&plist);
			break;
		case SEARCH:
			ContactSearch(&plist);
			break;
		case MODIFY:
			ContactModify(&plist);
			break;
		case SORT:
			ContactSort(&plist);
			break;
		case SHOW:
			ContactShow(&plist);
			break;
		case EXIT:
			printf("退出程序……\n");
			ContactDestory(&plist);
			break;
		default :
			printf("输入错误,重新输入!!!\n");
			break;
		}

	} while (input);

}

通讯录的实现基于顺序表的原理,通过动态数组存储联系人信息,并提供了添加、删除、查找、修改、排序和展示等功能。这些功能的实现依赖于动态内存管理和字符串操作等基础技术。

后记

经过艰苦卓绝的战斗,通讯录残血了,小Y扔出了精灵球,(精灵球摇了几下–叮的一声),小Y成功捕获了通讯录!!!

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值