c语言实现静态与动态通讯录

Posted aaaaaaaWoLan

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了c语言实现静态与动态通讯录相关的知识,希望对你有一定的参考价值。

通讯录实现1.0(静态版本)

contact.h:包括函数的声明,#define定义的一些常用数字以及结构体的定义

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

//将这些信息的最大值用宏的方式定义,之后便于修改
#define MAX_NAME 10
#define MAX_SEX  5
#define MAX_TELE 12
#define MAX_ADDRESS 10
#define MAX_PEOPLE 1000

typedef struct contactinfo//创建联系人,联系人信息包括:姓名、性别、年龄、电话、住址
{
	char name[MAX_NAME];
	char sex[MAX_SEX];
	int age;
	char tele[MAX_TELE];
	char address[MAX_ADDRESS];
}info;

typedef struct contacts//创建通讯录,包括1000个联系人,sz表示当前含有联系人的个数
{
	info con[MAX_PEOPLE];
	int sz;
}contacts;

//初始化通讯录
void InitContact(contacts* c);

//添加联系人
void add_contact(contacts* c);

//删除联系人
void del_contact(contacts* c);

//展示通讯录
void print_contacts(contacts* c);

//寻找联系人
void search_contact(contacts* c);

//修改联系人信息
void modify_contact(contacts* c);

//清空通讯录
void clean_contacts(contacts* c);

//联系人排序
void sort_contacts(contacts* c);

contact.c:函数的具体实现

#define  _CRT_SECURE_NO_WARNINGS  1
#include"contact.h"

void InitContact(contacts* c)//初始化通讯录
{
	memset(c->con, 0, MAX_PEOPLE*sizeof(c->con[0]));
	c->sz = 0;
}


void add_contact(contacts* c)//添加的信息包括姓名、性别、年龄、电话、住址
{
	if (c->sz == MAX_PEOPLE)//判断通讯录是否已满
	{
		printf("通讯录已满!\\n");
		return;
	}
	printf("请输入姓名\\n");
	scanf("%s", c->con[c->sz].name);
	printf("请输入性别\\n");
	scanf("%s", c->con[c->sz].sex);
	printf("请输入年龄\\n");
	scanf("%d", &c->con[c->sz].age);
	printf("请输入电话\\n");
	scanf("%s", c->con[c->sz].tele);
	printf("请输入住址\\n");
	scanf("%s", c->con[c->sz].address);
	c->sz++;
	printf("添加成功!\\n");

}

static int find_people(contacts* c)//用名字来查找相应联系人,多个通讯录操作会用到该函数
{
	char name[MAX_NAME];
	scanf("%s", name);
	int i = 0;
	for (i = 0; i < c->sz; i++)
	{
		if ((strcmp(name, c->con[i].name)) == 0)
			return i;//若找到则返回对应下标
	}
	return -1;//未找到则返回-1
}

void del_contact(contacts* c) //需要先查找联系人,才能删除相应的联系人
{
	//先判断通讯录是否为空
	if (c->sz == 0)
	{
		printf("通讯录为空!\\n");
			return;
	}
	printf("请输入要删除的联系人姓名!\\n");
	int ret = find_people(c);
	if (ret == -1)
	{
		printf("未找到该联系人!\\n");
		return;
	}
	else
	{
		int i = 0;
		for (i = ret; i < c->sz - 1; i++)//将要删除联系人之后的联系人信息向前覆盖
		{
			c->con[i] = c->con[i + 1];
		}
		c->sz--;//此时虽然sz--了,但通讯录里含有的是sz+1个联系人,但进行通讯录添加联系人等操作时,不会用到第sz+1个联系人
		printf("删除成功!\\n");
	}

}

void print_contacts(contacts* c)
{
	if (c->sz == 0)
	{
		printf("通讯录为空!\\n");
		return;
	}
	printf("通讯录内容如下:\\n");
	printf("%-10s\\t%-5s\\t%-5s\\t%-12s\\t%-10s\\n", "姓名", "性别", "年龄", "电话", "住址");
	int i = 0;
	for (i = 0; i < c->sz; i++)//循环打印通讯录内容
	{
		printf("%-10s\\t%-5s\\t%-5d\\t%-12s\\t%-10s\\n", c->con[i].name, 
			                                        c->con[i].sex, 
			                                        c->con[i].age, 
			                                        c->con[i].tele, 
			                                        c->con[i].address);
	}
}

void search_contact(contacts* c)
{
	if (c->sz == 0)
	{
		printf("通讯录为空!\\n");
		return;
	}
	printf("请输入要查找的联系人姓名!\\n");
	int i = find_people(c);
	if (i == -1)
	{
		printf("未找到该联系人!\\n");
		return;
	}
	else
	{
		printf("该联系人信息如下:\\n");
		printf("%-10s\\t%-5s\\t%-5s\\t%-12s\\t%-10s\\n", "姓名", "性别", "年龄", "电话", "住址");
		printf("%-10s\\t%-5s\\t%-5d\\t%-12s\\t%-10s\\n", c->con[i].name,
			c->con[i].sex,
			c->con[i].age,
			c->con[i].tele,
			c->con[i].address);
	}
}


void modify_contact(contacts* c)
{
	if (c->sz == 0)
	{
		printf("通讯录为空!\\n");
		return;
	}
	printf("请输入要修改的联系人姓名!\\n");
	int i = find_people(c);
	if (i == -1)
	{
		printf("未找到该联系人!\\n");
		return;
	}
	else
		//这里的修改联系人是对联系人的所有信息进行修改,如果只想修改一项或几项信息,可以采取类似菜单的方式,用do...while,switch case语句及枚举进行修改
	{
		printf("请输入姓名\\n");
		scanf("%s", c->con[c->sz].name);
		printf("请输入性别\\n");
		scanf("%s", c->con[c->sz].sex);
		printf("请输入年龄\\n");
		scanf("%d", &c->con[c->sz].age);
		printf("请输入电话\\n");
		scanf("%s", c->con[c->sz].tele);
		printf("请输入住址\\n");
		scanf("%s", c->con[c->sz].address);
		printf("修改成功!\\n");
	}
}



void clean_contacts(contacts * c)//清空联系人也就是对通讯录进行初始化
{
	if (c->sz == 0)
	{
		printf("通讯录已为空!\\n");
		return;
	}
		InitContact(c);
		printf("清空成功!\\n");
}

void sort_contacts(contacts* c)//按照姓名排序,类似冒泡排序
{
	if (c->sz == 0)
	{
		printf("通讯录为空!\\n");
		return;
	}
	int i = 0;
	for (i = 0; i < c->sz - 1; i++)
	{
		int j = 0;
		for (j = 0; j < c->sz - 1 - i; j++)
		{
			if (strcmp(c->con[j].name, c->con[j + 1].name) > 0)
			{
				info tmp = c->con[j];
				c->con[j] = c->con[j + 1];
				c->con[j + 1] = tmp;
			}
		}
	}
	printf("排序成功!\\n");
	print_contacts(c);
}

test.c:通讯录的操作选择的实现

#include"contact.h"

void menu()//制作菜单
{
	printf("**********************************************\\n");
	printf("********* 1.ADD              2.DEL     *******\\n");
	printf("********* 3.SEARCH           4.MODIFY  *******\\n");
	printf("********* 5.PRINT            6.CLEAN   *******\\n");
	printf("********* 7.SORT             0.EXIT    *******\\n");
	printf("**********************************************\\n");
}

enum option//利用枚举来方便选择
{
	EXIT,
	ADD,
	DEL,
	SEARCH,
	MODIFY,
	PRINT,
	CLEAN,
	SORT
};

int main()
{
	int input = 0;
	contacts c;
	InitContact(&c);
	do {
		menu();
		printf("请选择:\\n");
		scanf("%d", &input);

		switch (input)
		{
		case ADD:
			add_contact(&c);
			break;
		case DEL:
			del_contact(&c);
			break;
		case SEARCH:
			search_contact(&c);
			break;
		case MODIFY:
			modify_contact(&c);
			break;
		case PRINT:
			print_contacts(&c);
			break;
		case CLEAN:
			clean_contacts(&c);
			break;
		case SORT:
			sort_contacts(&c);
			break;
		case EXIT:
			break;
			default:
				printf("输入错误,请重新输入\\n");
				break;

		}
	} while (input);
	return 0;
}

通讯类实现2.0(利用动态内存开辟节省空间)

主要改动:

1.由创建1000个结构体的结构体数组变成了由结构体指针指向的动态内存空间存储联系人

并设置容量,初始容量为3个联系人,一次增容增加2个联系人,当sz等于容量capacity时,就需要增容,增容在添加联系人函数中实现

//静态版本
//typedef struct contacts//创建通讯录,包括1000个联系人,sz表示当前含有联系人的个数
//{
//	info con[MAX_PEOPLE];
//	int sz;
//}contacts;

//动态版本
typedef struct contacts//创建通讯录
{
	info *con;//利用con指向动态开辟的空间,联系人信息存放至该空间
	int sz;//sz表示当前含有联系人的个数
	int capacity;//capacity表示当前动态内存空间的容量
}contacts;

2.初始化通讯录。

静态版本的初始化只需要把通讯录所有元素置零,而动态版本需要开辟初始空间,并将capacity赋值初始通讯录容量

//静态版本
//void InitContact(contacts* c)//初始化通讯录
//{
//	memset(c->con, 0, MAX_PEOPLE*sizeof(c->con[0]));
//	c->sz = 0;
//}

//动态版本
void InitContact(contacts* c)//初始化通讯录
{
	c->con = (info*)calloc(sizeof(info) * Init_Capacity);//给通讯录的初始大小设置成三个联系人
	c->sz = 0;
	c->capacity = Init_Capacity;//容量大小也初始为3
}

3.添加人联系人时,静态版本无需增容,当sz等于最大容量时,需要删除联系人才能继续添加联系人(当然一般也添加不到1000个联系人),动态版本则是先判断sz是否等于capacity,如果相等,说明联系人已满,需要增容,用realloc函数进行增容

//静态版本
//void add_contact(contacts* c)//添加的信息包括姓名、性别、年龄、电话、住址
//{
//	if (c->sz == MAX_PEOPLE)//判断通讯录是否已满
//	{
//		printf("通讯录已满!\\n");
//		return;
//	}
//	printf("请输入姓名\\n");
//	scanf("%s", c->con[c->sz].name);
//	printf("请输入性别\\n");
//	scanf("%s", c->con[c->sz].sex);
//	printf("请输入年龄\\n");
//	scanf("%d", &c->con[c->sz].age);
//	printf("请输入电话\\n");
//	scanf("%s", c->con[c->sz].tele);
//	printf("请输入住址\\n");
//	scanf("%s", c->con[c->sz].address);
//	c->sz++;
//	printf("添加成功!\\n");
//
//}

//动态版本
void add_contact(contacts* c)//添加的信息包括姓名、性别、年龄、电话、住址
{
	if (c->sz == c->capacity)//判断通讯录是否已满
	{
		//增容
		info* ptr = realloc(c->con, (c->capacity + ADD_Capacity) * sizeof(info));
		if (ptr != NULL)
		{
			printf("增容成功!\\n");
			c->con = ptr;
			c->capacity += ADD_Capacity;
		}
		else
		{
			printf("通讯录已满!\\n");
			return;
		}
		
	}
	printf("请输入姓名\\n");
	scanf("%s", c->con[c->sz].name);
	printf("请输入性别\\n");
	scanf("%s", c->con[c->sz].sex);
	printf("请输入年龄\\n");
	scanf("%d", &c->con[c->sz].age);
	printf("请输入电话\\n");
	scanf("%s", c->con[c->sz].tele);
	printf("请输入住址\\n");
	scanf("%s", c->con[c->sz].address);
	c->sz++;
	printf("添加成功!\\n");

}

4.退出联系人操作时,静态版本不需要做什么,而动态版本则需要释放已开辟的动态内存空间,并且将指针置空

			//静态版本
		//case EXIT:
		//	break;
			//动态版本
		case EXIT:
			free(c.con);//退出后及时返回内存,并把con置空
			c.con = NULL;
			break;

以上是关于c语言实现静态与动态通讯录的主要内容,如果未能解决你的问题,请参考以下文章

C语言进阶通讯录(静态/动态)

C语言手撕通讯录(静态动态双版本)——万字实战详解

c语言 通讯录系统 增删改查 排序 动态内存开辟及文件保存与读取

c语言 通讯录系统 增删改查 排序 动态内存开辟及文件保存与读取

c语言 数据结构线性表

c语言 数据结构线性表