用动态顺序表通讯录的实现(c语言)

本文中的代码都在Visual Studio(版本为2022)软件中运行,在使用scanf函数记得在第一行写下面的代码:

#define _CRT_SECURE_NO_WARNINGS 
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

//定义各类型的大小,方便后续修改                         
#define NAME_MAX 50									
#define GENDER_MAX 10									
#define PHONE_MAX 20										
#define ADDRESS_MAX 50									

//创建存放联系人信息的结构体
struct PersonInfo
{
	char name[NAME_MAX];            //姓名
	char gender[GENDER_MAX];        //性别
	int age;                        //年龄
	char phone[PHONE_MAX];          //电话号码
	char address[ADDRESS_MAX];      //地址
};

typedef struct PersonInfo SLDataType;   //将存放个人信息的结构体起一个别名

struct SeqList                //创建顺序表结构体
{
	SLDataType* arr;          //结构体指针,该指针指向的是一片以结构体为元素的连续的空间,即以结构体为元素的数组
	int size;                 //结构体指针指向空间的有效数据,即结构体中有效元素(已经存放人信息的结构体)的数量
	int capacity;			  //结构体指针指向空间的最大容量,即可以存放元素数量的最大值。
};

typedef struct SeqList contact;    //将顺序表结构体起一个别名

//通讯录的初始化
void InitContact(contact* con)
{
	con->arr = NULL;
	con->size = 0;
	con->capacity = 0;
}

//检查空间是否足够
void CheckCapacity(contact* con)
{
	//空间不够,进行扩容
	if (con->size == con->capacity)
	{
		int newCapacity = con->capacity == 0 ? 4 : 2 * con->capacity;  //扩容后元素个数
		SLDataType* tmp = (SLDataType*)realloc(con->arr, newCapacity * sizeof(SLDataType));  //realloc第二个参数的单位是字节,故在进行扩容时
		if (tmp == NULL)																	 //应将扩容后的元素的个数与一个元素所占空间的大小相乘
		{										//扩容时有可能扩容不成功,故先创建一个临时变量接收realloc的返回值
			perror("扩容失败");
			exit(1);
		}
		con->arr = tmp;							//扩容成功后再将临时变量赋值给arr
		con->capacity = newCapacity;
	}
}

//添加联系人
void AddContact(contact* con)
{
	//先检查空间是否足够
	CheckCapacity(con);
	//空间足够
	printf("请输入要添加用户的姓名:");
	scanf("%s", con->arr[con->size].name);
	printf("请输入要添加用户的性别:");
	scanf("%s", con->arr[con->size].gender);
	printf("请输入要添加用户的年龄:");
	scanf("%d", &con->arr[con->size].age);
	printf("请输入要添加用户的电话:");
	scanf("%s", con->arr[con->size].phone);
	printf("请输入要添加用户的地址:");
	scanf("%s", con->arr[con->size].address);

	printf("添加成功\n");
	con->size++;        //每添加一名联系人的数据,有效元素的个数加1
}

//通过电话号码查找联系人
int ByPhoneSearch(contact* con)                //这里的查找不是菜单栏中的查找
{                                              //是在删除、修改联系人之前进行的查找
	char phone[PHONE_MAX] = "";
	printf("请输入要删除或修改的联系人的电话:");
	scanf("%s", phone);

	for (int i = 0; i < con->size; i++)
	{
		if (strcmp(con->arr[i].phone, phone) == 0)   //con是一个结构体指针变量,
		{                                            //存放的是一个指向结构体数组的结构体指针
			return i;								 //结构体指针指向的结构体中有两个整形类型
		}											 //一个记录有效元素数量的整数
													//一个说明结构体数组所能容纳元素数量的最大值

	}		//con->arr[i].phone 表示 结构体变量con 成员中的 结构体指针arr指向的结构体数组中下标为i的结构体成员中的变量phone
	return -1;
}


//删除联系人
void DeleteContact(contact* con)
{
	if (con->arr != NULL)     //删除之前判断通讯录中是否有数据,即结构体数组中是否有有效的元素
	{
		int numReturn = 0;
		numReturn = ByPhoneSearch(con);     //通过查找判断是否有该联系人的信息
		if (numReturn != -1)
		{
			for (int i = numReturn; i < con->size; i++)
			{
				con->arr[i] = con->arr[i + 1];
			}
			con->size--;
			printf("删除成功\n");
		}
		else
		{
			printf("通讯录中没有此联系人的信息,无法删除\n");
		}
	}
	else
	{
		printf("通讯录里没有数据,不能删除\n");
	}
}


//通过名字查找联系人
int ByNameSearch(contact* con)
{
	char name[NAME_MAX] = "";
	printf("请输入你要查找的联系人的名字:");
	scanf("%s", name);
	for (int i = 0; i < con->size; i++)
	{
		if (strcmp(con->arr[i].name, name) == 0)
		{
			return i;
		}
	}
	return -1;
}


//查找联系人(通过姓名)
void SearchContact(contact* con)
{

	if (con->arr != NULL)        //查找之前判断通讯录中是否有数据,即结构体数组中是否有有效的元素
	{
		int numReturn = 0;
		numReturn = ByNameSearch(con);
		if (numReturn != -1)
		{
			printf("查找成功\n");
			printf("%-7s %-7s %-7s %-20s %-30s\n", "姓名", "性别", "年龄", "电话", "地址");
			printf("%-7s ", con->arr[numReturn].name);
			printf("%-7s ", con->arr[numReturn].gender);
			printf("%-7d ", con->arr[numReturn].age);
			printf("%-20s ", con->arr[numReturn].phone);
			printf("%-30s \n", con->arr[numReturn].address);
		}
		else
		{
			printf("通讯录中没有此人的信息\n");
		}
	}
	else
	{
		printf("通讯录中没有数据,无法查找\n");
	}
}

//修改联系人的信息
void ModifyContact(contact* con)
{
	if (con->arr != NULL)         //修改之前判断通讯录中是否有数据,即结构体数组中是否有有效的元素
	{
		int numReturn = 0;
		numReturn = ByPhoneSearch(con);  //通过查找判断是否有该联系人的信息
		if (numReturn != -1)
		{
			printf("请输入修改后的名字:");
			scanf("%s", con->arr[numReturn].name);
			printf("请输入修改后的性别:");
			scanf("%s", con->arr[numReturn].gender);
			printf("请输入修改后的年龄:");
			scanf("%d", &con->arr[numReturn].age);
			printf("请输入修改后的电话:");
			scanf("%s", con->arr[numReturn].phone);
			printf("请输入修改后的地址:");
			scanf("%s", con->arr[numReturn].address);

			printf("修改成功\n");
		}
		else
		{
			printf("通讯录中没有此联系人,无法修改\n");
		}
	}
	else
	{
		printf("通讯录里没有数据,不能修改\n");
	}
}

//展示通讯录中的信息
void DisplayContact(contact* con)
{
	if (con->arr != NULL)
	{
		//调整展示通讯录信息的格式
		printf("%-7s %-7s %-7s %-20s %-30s\n", "姓名", "性别", "年龄", "电话", "地址");
		for (int i = 0; i < con->size; i++)
		{
			printf("%-7s ", con->arr[i].name);
			printf("%-7s ", con->arr[i].gender);
			printf("%-7d ", con->arr[i].age);
			printf("%-20s ", con->arr[i].phone);
			printf("%-30s\n", con->arr[i].address);

		}
	}
}

//菜单,根据选择数字的不同,执行相应的函数
void menu()
{
	printf("*****************************************\n");
	printf("********1.添加联系人 2.删除联系人********\n");
	printf("********3.查找联系人 4.修改联系人********\n");
	printf("********5.展示联系人 0. 退   出  ********\n");
	printf("*****************************************\n");
}

int main()
{
	contact con;       //创建结构体变量
	InitContact(&con); //初始化结构体
	int option = -1;   //创建整型变量用于输入选择的数字
	do
	{											//使用do while循环,执行某一功能之后,菜单继续显示直到你选择的数字为0
		menu();
		printf("请输入你要选择的数字:");
		scanf("%d", &option);
		switch (option)
		{
		case 1:
			AddContact(&con);       //初始化
			break;
		case 2:
			DeleteContact(&con);    //删除
			break;
		case 3:
			SearchContact(&con);     //查找
			break;
		case 4:
			ModifyContact(&con);     //修改
			break;
		case 5:
			DisplayContact(&con);    //展示
			break;
		case 0:
			printf("退出成功");
			break;
		default:
			printf("输入错误,请重新选择\n");
		}
	} while (option);      //option为0时,循环才终止

	return 0;
}

个人总结:

通讯录用来存放联系人信息,而联系人信息需要多种类型来储存,故创建用来存放联系人信息的结构体。
通讯录中的联系人有多位,可以创建指向结构体数组的结构体指针来存放不同联系人的信息,此外,还要创建两个整形变量,一个表示有效元素的个数,一个表示结构体数组所能容纳元素个数的最大值,以此判断结构体数组的空间是否足够,同时也能简化后续的相关操作。
通讯录中的功能有添加联系人、删除联系人信息、查找联系人信息、修改联系人信息、展示联系人信息,故可用菜单、switch语句和一个整型变量来判断执行哪个函数(实现某一功能)再用上do while循环就能实现对选择功能的循环,直到选择的数字为0时退出循环

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值