【C语言】实现一个通讯录(动态扩容)

目录

定义通讯录结构体

通讯录初始化

检查空间大小

新增联系人信息

通过姓名查找联系人

删除指定联系人信息

打印所有联系人信息

查找指定联系人信息

删除指定联系人信息

清空所有联系人信息

通过名字排序联系人

         完整代码:

通讯录可以用来存储1000个人的信息,每个人的信息包括:姓名、性别、年龄、电话、住址

功能:

  • 添加联系人信息
  • 删除指定联系人信息
  • 查找指定联系人信息
  • 修改指定联系人信息
  • 显示所有联系人信息
  • 清空所有联系人
  • 以名字排序所有联系人

固定大小通讯录  <-这是静态大小的通讯录

这个动态大小的通讯录可以先开辟较小的空间,后根据需求再开辟所需要的空间,更节约内存空间

写这个通讯录需要对结构体成员访问、动态内存分配的知识有一定的了解


定义通讯录结构体

#define NAME_MAX 20
#define SEX_MAX 5
#define AGE_MAX 3
#define TELE_MAX 12
#define ADDR_MAX 20
#define BASIC 5

//单个联系人信息
typedef struct PeoInfo
{
	char name[NAME_MAX];
	char sex[SEX_MAX];
	char age[AGE_MAX];
	char tele[TELE_MAX];
	char addr[ADDR_MAX];
}PeoInfo;

typedef struct Contact
{
	PeoInfo* data;
	int sz;           //已存联系人数量
	int capacity;     //此通讯录最大可存联系人数量
}Contact;

通讯录初始化

先开辟自定义的BASIC个联系人空间

//通讯录初始化
void init_contact(Contact* pc)
{
	assert(pc);

	pc->capacity = BASIC;
	pc->sz = 0;
	pc->data = (PeoInfo*)malloc(pc->capacity * sizeof(PeoInfo));

	if (pc->data == NULL)
	{
		perror("init_contact:malloc");
		return;
	}
	
	memset(pc->data,0, pc->capacity * sizeof(PeoInfo));
}

检查空间大小

这里判断sz==capacity-1,而不是sz==capacity,是因为data数组的最后一项pc->data[pc->capacity]要为空,用作后面的排序时用的的临时数据。所以通讯录的实际可用大小为capacity-1

//检查通讯录大小是否已满,满则扩容
void check_capacity(Contact* pc)
{
	assert(pc);

	if (pc->sz == pc->capacity - 1)
	{
		PeoInfo* temp = realloc(pc->data, (pc->capacity + 2) * sizeof(PeoInfo));
		if (temp == NULL)
		{
			perror("check_capacity:");
			return;
		}
		else
		{
			pc->data = temp;
			pc->capacity += 2;
		}
	}
}

新增联系人信息

这里和静态通讯录相似,只是在新增之前要检查通讯录大小是否足够大,要调用check_capacity函数

//新增联系人信息
void add_contact(Contact* pc)
{
	assert(pc);
	check_capacity(pc);

	printf("请输入姓名:");
	scanf("%s", pc->data[pc->sz].name);
	printf("请输入性别:");
	scanf("%s", pc->data[pc->sz].sex);
	printf("请输入年龄:");
	scanf("%s", pc->data[pc->sz].age);
	printf("请输入电话:");
	scanf("%s", pc->data[pc->sz].tele);
	printf("请输入住址:");
	scanf("%s", pc->data[pc->sz].addr);

	pc->sz++;  //联系人数目变化
}

通过姓名查找联系人

//查找是否有此联系人,有则返回下标
int find_name(Contact* pc, char* name)
{
	assert(pc);

	int ret = 0;
	for (int i = 0; i < pc->sz; i++)
	{
		if (0 == strcmp(name, pc->data[i].name))
		{
			return i;
		}
		else if (i == pc->sz)
		{
			return -1;
		}
	}
	return -1;
}

删除指定联系人信息

这里和静态通讯录相似

//删除指定联系人信息
void delete_contact(Contact* pc)
{
	assert(pc);

	char dname[NAME_MAX];
	printf("请输入删除的联系人姓名:");
	scanf("%s", dname);

	if (find_name(pc, dname) != -1)
	{
		//用后一个联系人的信息替换掉前一个联系人的信息
		for (int j = find_name(pc, dname); j < pc->sz - 1; j++)
		{
			pc->data[j] = pc->data[j + 1];
		}

		pc->sz--;

		printf("删除成功\n\n");
	}
	else
	{
		printf("找不到该联系人\n\n");
	}
}

打印所有联系人信息

这里和静态通讯录相似

//打印通讯录
void print_contact(Contact* pc)
{
	assert(pc);

	printf("%-20s %-5s %-5s %-15s %-20s\n", "姓名", "性别", "年龄", "电话号码", "住址");

	for (int i = 0; i < pc->sz; i++)
	{
		printf("%-20s %-5s %-5s %-15s %-20s\n", pc->data[i].name, pc->data[i].sex, pc->data[i].age, pc->data[i].tele, pc->data[i].addr);
	}
	printf("\n");
}

查找指定联系人信息

这里和静态通讯录相似

//查找指定联系人信息
void search_contact(Contact* pc)
{
	assert(pc);

	char sname[NAME_MAX];
	printf("请输入联系人姓名:");
	scanf("%s", sname);

	int ret = find_name(pc, sname);

	if (ret != -1)
	{
		printf("%-20s %-5s %-5s %-15s %-20s\n", "姓名", "性别", "年龄", "电话号码", "住址");
		printf("%-20s %-5s %-5s %-15s %-20s\n\n", pc->data[ret].name, pc->data[ret].sex, pc->data[ret].age, pc->data[ret].tele, pc->data[ret].addr);

	}
	else
	{
		printf("找不到此联系人\n\n");
	}
}

删除指定联系人信息

这里和静态通讯录相似

//修改指定联系人信息
void modify_contact(Contact* pc)
{
	assert(pc);

	char mname[NAME_MAX];
	printf("请输入需要修改的联系人:");
	scanf("%s", mname);

	int ret = find_name(pc, mname);
	if (ret != -1)
	{
		printf("请输入新的联系人信息:\n");
		printf("姓名:");
		scanf("%s", pc->data[ret].name);
		printf("性别:");
		scanf("%s", pc->data[ret].sex);
		printf("年龄:");
		scanf("%s", pc->data[ret].age);
		printf("电话:");
		scanf("%s", pc->data[ret].tele);
		printf("住址:");
		scanf("%s", pc->data[ret].addr);
		printf("修改成功\n\n");
	}
	else
	{
		printf("此联系人不存在\n\n");
	}
}

清空所有联系人信息

//清空所有联系人
void clean_contact(Contact* pc)
{
	assert(pc);

	printf("请确认清空所有联系人:\n");
	printf("1->YES		2->NO\n");

	int judge = 0;
	scanf("%d", &judge);

	if (judge == 1)
	{
		free_contact(pc);
		printf("已清空\n\n");
	}
	else
	{
		return;
	}
}

通过名字排序联系人

冒泡排序

//按名字排序联系人
void sort_contact(Contact* pc)
{
	assert(pc);

	int upordown = 0;
	printf("请选择排序方式:\n");
	printf("1->升序  2->降序\n");
	scanf("%d", &upordown);

	if (upordown == 1)
	{
		for (int i = 0; i < pc->sz - 1; i++)
			for (int j = 0; j < pc->sz - 1 - i; j++)
			{
				if (strcmp(pc->data[j].name, pc->data[j + 1].name) > 0)
				{
					pc->data[pc->capacity - 1] = pc->data[j];
					pc->data[j] = pc->data[j + 1];
					pc->data[j + 1] = pc->data[pc->capacity - 1];
				}
			}
		printf("已按姓名升序排列\n\n");
	}
	else if (upordown == 2)
	{
		for (int i = 0; i < pc->sz - 1; i++)
			for (int j = 0; j < pc->sz - 1 - i; j++)
			{
				if (strcmp(pc->data[j].name, pc->data[j + 1].name) < 0)
				{
					pc->data[pc->capacity - 1] = pc->data[j];
					pc->data[j] = pc->data[j + 1];
					pc->data[j + 1] = pc->data[pc->capacity - 1];
				}
			}
		printf("已按姓名降序排列\n\n");
	}
	else
	{
		printf("输入错误\n");
		return;
	}
}

完整代码:

头文件

#define _CRT_SECURE_NO_WARNINGS 1

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

#define NAME_MAX 20
#define SEX_MAX 5
#define AGE_MAX 3
#define TELE_MAX 12
#define ADDR_MAX 20
#define BASIC 5

enum
{
	EXIT,   //0
	ADD,
	DELE,
	SEARCH,
	MODIFY,
	PRINT,
	CLEAN,
	SORT,
};

//单个联系人信息
typedef struct PeoInfo
{
	char name[NAME_MAX];
	char sex[SEX_MAX];
	char age[AGE_MAX];
	char tele[TELE_MAX];
	char addr[ADDR_MAX];
}PeoInfo;

typedef struct Contact
{
	PeoInfo* data;
	int sz;           //已存联系人数量
	int capacity;     //此通讯录最大可存联系人数量
}Contact;

//初始化
void init_contact(Contact* pc);
//新增联系人信息
void add_contact(Contact* pc);
//打印通讯录
void print_contact(Contact* pc);
//查找是否有此联系人,有则返回下标
int find_name(Contact* pc, char* name);
//删除指定联系人信息
void delete_contact(Contact* pc);
//查找指定联系人信息
void search_contact(Contact* pc);
//修改指定联系人信息
void modify_contact(Contact* pc);
//清空所有联系人
void clean_contact(Contact* pc);
//按名字排序联系人
void sort_contact(Contact* pc);

功能函数

#define _CRT_SECURE_NO_WARNINGS 1

#include"contact2.0.h"

//通讯录初始化
void init_contact(Contact* pc)
{
	assert(pc);

	pc->capacity = BASIC;
	pc->sz = 0;
	pc->data = (PeoInfo*)malloc(pc->capacity * sizeof(PeoInfo));

	if (pc->data == NULL)
	{
		perror("init_contact:malloc");
		return;
	}
	
	memset(pc->data,0, pc->capacity * sizeof(PeoInfo));
}

//检查通讯录大小是否已满,满则扩容
void check_capacity(Contact* pc)
{
	assert(pc);

	if (pc->sz == pc->capacity - 1)
	{
		PeoInfo* temp = realloc(pc->data, (pc->capacity + 2) * sizeof(PeoInfo));
		if (temp == NULL)
		{
			perror("check_capacity:");
			return;
		}
		else
		{
			pc->data = temp;
			pc->capacity += 2;
		}
	}
}

//内存释放
void free_contact(Contact* pc)
{
	assert(pc);

	free(pc->data);

	pc->data = NULL;
	pc -> sz = 0;
	pc -> capacity = 0;

}

//新增联系人信息
void add_contact(Contact* pc)
{
	assert(pc);
	check_capacity(pc);

	printf("请输入姓名:");
	scanf("%s", pc->data[pc->sz].name);
	printf("请输入性别:");
	scanf("%s", pc->data[pc->sz].sex);
	printf("请输入年龄:");
	scanf("%s", pc->data[pc->sz].age);
	printf("请输入电话:");
	scanf("%s", pc->data[pc->sz].tele);
	printf("请输入住址:");
	scanf("%s", pc->data[pc->sz].addr);

	pc->sz++;  //联系人数目变化
}


//打印通讯录
void print_contact(Contact* pc)
{
	assert(pc);

	printf("%-20s %-5s %-5s %-15s %-20s\n", "姓名", "性别", "年龄", "电话号码", "住址");

	for (int i = 0; i < pc->sz; i++)
	{
		printf("%-20s %-5s %-5s %-15s %-20s\n", pc->data[i].name, pc->data[i].sex, pc->data[i].age, pc->data[i].tele, pc->data[i].addr);
	}
	printf("\n");
}


//查找是否有此联系人,有则返回下标
int find_name(Contact* pc, char* name)
{
	assert(pc);

	int ret = 0;
	for (int i = 0; i < pc->sz; i++)
	{
		if (0 == strcmp(name, pc->data[i].name))
		{
			return i;
		}
		else if (i == pc->sz)
		{
			return -1;
		}
	}
	return -1;
}

//删除指定联系人信息
void delete_contact(Contact* pc)
{
	assert(pc);

	char dname[NAME_MAX];
	printf("请输入删除的联系人姓名:");
	scanf("%s", dname);

	if (find_name(pc, dname) != -1)
	{
		//用后一个联系人的信息替换掉前一个联系人的信息
		for (int j = find_name(pc, dname); j < pc->sz - 1; j++)
		{
			pc->data[j] = pc->data[j + 1];
		}

		pc->sz--;

		printf("删除成功\n\n");
	}
	else
	{
		printf("找不到该联系人\n\n");
	}
}

//查找指定联系人信息
void search_contact(Contact* pc)
{
	assert(pc);

	char sname[NAME_MAX];
	printf("请输入联系人姓名:");
	scanf("%s", sname);

	int ret = find_name(pc, sname);

	if (ret != -1)
	{
		printf("%-20s %-5s %-5s %-15s %-20s\n", "姓名", "性别", "年龄", "电话号码", "住址");
		printf("%-20s %-5s %-5s %-15s %-20s\n\n", pc->data[ret].name, pc->data[ret].sex, pc->data[ret].age, pc->data[ret].tele, pc->data[ret].addr);

	}
	else
	{
		printf("找不到此联系人\n\n");
	}
}

//修改指定联系人信息
void modify_contact(Contact* pc)
{
	assert(pc);

	char mname[NAME_MAX];
	printf("请输入需要修改的联系人:");
	scanf("%s", mname);

	int ret = find_name(pc, mname);
	if (ret != -1)
	{
		printf("请输入新的联系人信息:\n");
		printf("姓名:");
		scanf("%s", pc->data[ret].name);
		printf("性别:");
		scanf("%s", pc->data[ret].sex);
		printf("年龄:");
		scanf("%s", pc->data[ret].age);
		printf("电话:");
		scanf("%s", pc->data[ret].tele);
		printf("住址:");
		scanf("%s", pc->data[ret].addr);
		printf("修改成功\n\n");
	}
	else
	{
		printf("此联系人不存在\n\n");
	}
}

//清空所有联系人
void clean_contact(Contact* pc)
{
	assert(pc);

	printf("请确认清空所有联系人:\n");
	printf("1->YES		2->NO\n");

	int judge = 0;
	scanf("%d", &judge);

	if (judge == 1)
	{
		free_contact(pc);
		printf("已清空\n\n");
	}
	else
	{
		return;
	}
}

//按名字排序联系人
void sort_contact(Contact* pc)
{
	assert(pc);

	int upordown = 0;
	printf("请选择排序方式:\n");
	printf("1->升序  2->降序\n");
	scanf("%d", &upordown);

	if (upordown == 1)
	{
		for (int i = 0; i < pc->sz - 1; i++)
			for (int j = 0; j < pc->sz - 1 - i; j++)
			{
				if (strcmp(pc->data[j].name, pc->data[j + 1].name) > 0)
				{
					pc->data[pc->capacity - 1] = pc->data[j];
					pc->data[j] = pc->data[j + 1];
					pc->data[j + 1] = pc->data[pc->capacity - 1];
				}
			}
		printf("已按姓名升序排列\n\n");
	}
	else if (upordown == 2)
	{
		for (int i = 0; i < pc->sz - 1; i++)
			for (int j = 0; j < pc->sz - 1 - i; j++)
			{
				if (strcmp(pc->data[j].name, pc->data[j + 1].name) < 0)
				{
					pc->data[pc->capacity - 1] = pc->data[j];
					pc->data[j] = pc->data[j + 1];
					pc->data[j + 1] = pc->data[pc->capacity - 1];
				}
			}
		printf("已按姓名降序排列\n\n");
	}
	else
	{
		printf("输入错误\n");
		return;
	}
}

主函数

#define _CRT_SECURE_NO_WARNINGS 1

#include"contact2.0.h"

void menu(void)
{
	printf("*********CONTACT*********\n");
	printf("*** 1.Add    2.Dele   ***\n");
	printf("*** 3.Search 4.Modify ***\n");
	printf("*** 5.Print  6.Clean  ***\n");
	printf("*** 7.Sort   0.Exit   ***\n");
	printf("*************************\n");
}

void test(void)
{
	int input = 0;

	Contact con;          //创建通讯录
	init_contact(&con);   //初始化
	
	do
	{
		menu();

		printf("请选择:");
		scanf("%d", &input);
		switch (input)
		{
		case ADD:
			add_contact(&con);
			break;
		case DELE:
			delete_contact(&con);
			break;
		case SEARCH:
			search_contact(&con);
			break;
		case MODIFY:
			modify_contact(&con);
			break;
		case PRINT:
			print_contact(&con);
			break;
		case CLEAN:
			clean_contact(&con);
			break;
		case SORT:
			sort_contact(&con);
			break;
		case EXIT:
			free_contact(&con);
			break;
		default:
			printf("选择错误\n");
			break;
		}
	} while (input);
}

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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值