首页 > 编程语言 > C语言模拟实现动态通讯录
2021
11-07

C语言模拟实现动态通讯录

1.模拟实现通讯录总体架构一览图

在这里插入图片描述

2.文件执行任务

在这里插入图片描述

3.分模块实现

 测试模块 test.c

1.为了更好地展示,制作一个菜单,在菜单中有 添加,删除,查找,修改,排序,清空,退出的选项。
2.因为起先要进入程序一趟,所以用do····while循环(输入选项来看具体操作,退出还是其他操作)

 #include "contact.h"
void menu()
{

	printf("*****************************************\n");
	printf("********          Contact          ******\n");
	printf("********     1.add     2. del      ******\n");
	printf("********     3.search  4.modify    ******\n");
	printf("********     5.print   6.empty     ******\n");
	printf("********     7.sort    0.exit      ******\n");
	printf("*****************************************\n");

}
enum Option
//为什么要使用枚举
//因为这样可以防止命名污染,而且使用枚举,枚举成员有默认初始值,默认从0开始,这样省去的诸多的代码量
{
	EXIT,
	ADD,
	DEL,
	SEARCH,
	MODIFY,
	PRINT,
	EMPTY,
	SORT,
};
int main()
{
	//先打印菜单,展示通讯录功能
	int input = 0;
	//先进行设置一个通讯录
	//设置每个人的信息
	//初始化通讯录 
	//通讯录中的一个元素
	contact con; 
	//contact 是自定义数据类型,包括一个联系人的基本信息
	InitContact(&con);
	do
	{
		menu();//设置菜单
		printf("请选择>");
		scanf("%d", &input);
		switch (input)
		{
		case ADD:
			//实现添加功能
			AddContact(&con);
			break;
		case DEL:
			//实现删除功能
			DelContact(&con);
			break;
		case SEARCH:
			//实现查找功能
			SearchContact(&con);
			break;
		case MODIFY:
			//实现修改功能
			ModifyContact(&con);
			break;
		case PRINT:
			//显示
			PrintContact(&con);
			break;
		case SORT:
			//实现名字排序
			SortContact(&con);
			break;
		case EMPTY:
			//实现清空
			EmptyContact(&con);
			break;
		case EXIT:
			//退出程序
			ExitContact(&con);
			break;
		default:
			printf("输入错误,请重新输入\n");
		}
	} while (input);
	return 0;
}

头文件 功能函数声明 contact.h

1.声明各类功能函数
2.定义各个常量,把常量定义成通俗易懂的变量,便于在多处使用。
3.定义结构体,自定义类型中,有一个联系人的基本信息。

 #include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define MAX_NAME 20 //定义姓名字符串的大小为20
#define MAX_SEX 10 //定义性别字符串的大小为10
#define MAX_TELE 12 //定义电话字符串的大小为12
#define MAX_ADDR 20 //定义地址字符串的大小为20
#define MAX 1000  //定义通讯录的最大容量为1000
#define IN_NUM 3  //在动态申请空间时默认空间为3
#define SET_NUM 2  //当基本信息大于3份时,开辟两个空间
//设置每一个人的信息
//通讯录规定要求一共有1000个人
typedef struct base
{
	char name[MAX_NAME]; //姓名
	char sex[MAX_SEX];   //性别
	int age;             //年龄
	char tele[MAX_TELE]; //电话
	char addr[MAX_ADDR]; //住址
}base;
//设置1000人的通讯录
//静态版
//typedef struct contact
//{
//	 
//	int sz;           //计算当前通讯录中联系人的个数
//	base data[MAX]; //存放联系人的信息
// 
//}contact;
//动态初始化通讯录
typedef struct contact
{
	//有个结构体类型中需要,监视通讯录人数的一项,还有当联系人为3人时,这时候要进行增容
	int sz;   //计算当前联系人的个数
	base* data; //指向动态申请的空间,存放联系人的信息
	int capciaty; //计算当前通讯录中的最大容量
}contact;

//初始化通讯录
void InitContact(contact* pc);
//添加联系人
void AddContact(contact* pc);
//显示
void PrintContact(contact* pc);
//删除联系人
void DelContact(contact* pc);
//查找联系人
void SearchContact(contact* pc);
//修改信息
void ModifyContact(contact* pc);
//排序联系人信息
void SortContact(contact* pc);
//清空联系人信息
void EmptyContact(contact* pc);
//退出程序时,释放空间
void ExitContact(contact* pc);

功能函数逐一实现

contact.c 1.初始化通讯录

动态申请空间
默认在动态空间中存放3个基本单位信息

 void InitContact(contact* pc)
{

	pc->data = (base*)malloc(sizeof(base) * IN_NUM);

	if (pc->data == NULL)
	//如果空间开辟失败
	//退出程序
	{
		perror("InitContact");
		return;
	}
	//把每个成员都设置为0
	pc->sz = 0;
 
	pc->capciaty = IN_NUM;
}

2.添加联系人

当默认的空间被装满时,然后以后的每一次都开辟两个基本空间

void AddContact(contact* pc)
{
//先判断通讯录中是否满了
	//if (pc->sz == MAX)
	//{
	//	printf("通讯录已满,无法添加\n");
	//	return;
	//}
	//动态判断人的个数是否满足3
	if (pc->sz == pc->capciaty)
	{
		printf("开始增容:\n");
		//从新设置一个指针,存放新开辟的内存
		base* ptr = (base*)realloc(pc->data, (pc->capciaty + SET_NUM) * sizeof(base));
		//判断是否开辟成功
		if (ptr == NULL)
		{
			printf("开辟失败\n");
			perror("AddContact");
			return;
		}
		else
		{
			printf("开辟成功\n");
			//开辟成功的话,把ptr转交给data来维护,这样在内存释放的时候只需要释放pc->data
			pc->data = ptr;
			//增加基本信息数量
			pc->capciaty += SET_NUM;
		}
		printf("增容完毕\n");
	}
	//添加
	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);
	pc->sz++;
	printf("添加成功\n");
}

3.显示联系人信息

逐一打印联系人信息,注意之间的距离(保持美观)

 //显示
void PrintContact(contact* pc)
{
	//显示标题
	printf("%-20s %-10s %-5s %-15s %-20s\n", "姓名", "性别", "年龄", "电话", "住址");
	int i = 0;
	for (i = 0; i < pc->sz; i++)
	{
		printf("%-20s %-10s %-5d %-15s %-20s\n", 
		    pc->data[i].name,
			pc->data[i].sex,
			pc->data[i].age,
			pc->data[i].tele,
			pc->data[i].addr);
	}
}

4.删除联系人

在删除联系人之前,首先要查找要删除联系人的名字,然后进行删除,注意如何删除
让删除的这个单位的后一个单位去覆盖这个删除的单位(这样原来要删除的地方变成了后面一个值) i = i+1
当通讯录中有被删除着的名字时,返回这个单位的下标
当通讯录中没有时,返回-1

 //查找联系人
static int Find_name(contact* pc, char name[])
{
	int i = 0;
	for ( i = 0; i < pc->sz; i++)
	{
		if (strcmp(pc->data[i].name, name) == 0)
		{
			return i;
		}
	}
	return -1;
}
//删除联系人
void DelContact(contact* pc)
{
	//如果通讯录是空的
	if (pc->sz == 0)
	{
		printf("通讯为空,无需删除\n");
		return;
	}
//下进行查找被删除联系人的名字
	char name[MAX_NAME];
	printf("请输入要删除联系人的名字:");
	scanf("%s", name);
	int ret = Find_name(pc, name);
	if (ret == -1)
	{
		printf("该联系人不存在\n");
		return;
	}
	//删除
	//删除项后边的一项,覆盖前面的一项
	for (int i = ret; i < pc->sz; i++)
	{
		pc->data[i] = pc->data[i + 1];
	}
	pc->sz--;
	printf("删除成功\n");
}

4.查找联系人

在删除联系人的时候有查找函数,在这里直接引用,并打印。这个人的信息。

 //查找联系人
void SearchContact(contact* pc)
{
	char name[MAX_NAME];
	printf("请输入要查找联系人的名字:");
	scanf("%s", name);
	int ret = Find_name(pc, name);
	if (ret == -1)
	{
		printf("该联系人不存在\n");
		return;
	}
	printf("%-20s %-10s %-5s %-15s %-20s\n", "姓名", "性别", "年龄", "电话", "住址");
	printf("%-20s %-10s %-5d %-15s %-20s\n", pc->data[ret].name,
			pc->data[ret].sex,
			pc->data[ret].age,
			pc->data[ret].tele,
			pc->data[ret].addr);
}

5.修该联系人信息

还是现在通讯录中查找这个联系人,在进行输入修改

 //修改信息
void ModifyContact(contact* pc)
{
	char name[MAX_NAME];
	printf("请输入要修改联系人的名字:");
	scanf("%s", name);
	int ret = Find_name(pc, name);
	if (ret == -1)
	{
		printf("该联系人不存在\n");
		return;
	}
	printf("姓名是>");
	scanf("%s", pc->data[ret].name);
	printf("年龄是>");
	scanf("%d", &pc->data[ret].age);
	printf("性别>");
	scanf("%s", pc->data[ret].sex);
	printf("电话>");
	scanf("%s", pc->data[ret].tele);
	printf("住址>");
	scanf("%s", pc->data[ret].addr);
}

6.排序联系人姓名

利用冒泡排序对联系人的名字进行排序(也可以使用快排)

 //排序
//交换名字,但是名字要和联系人的信息匹配
//先比较名字,根据名字的大小,再排序
static void SwapByname(base* pa, base* pb)
{
	base b;
	b = *pa;
	*pa = *pb;
	*pb = b;
}
void SortContact(contact* pc)
{
	printf("开始排序\n");
  //使用冒泡排序对联系人的名字进行排序
	int i = 0;
	int j = 0;
	for (i = 0; i < pc->sz; i++)
	{
		for (j = 0; j < pc-> sz - i - 1; j++)
		{
			if (strcmp(pc->data[j].name, pc->data[j + 1].name) > 0)
			{
				 //实现交换姓名
				SwapByname(&pc->data[j], &pc->data[j + 1]);
			}
		}
	}
	printf("排序结束\n");
}

7.清空联系人

在这里直接使用sz?,就可以删除

 //清空
void EmptyContact(contact* pc)
{
//如果原来的通讯录是空的就无须清空
	if (pc->sz == 0)
	{
		printf("通讯录为空,无需清空\n");
		return;
	}
	 
	printf("开始清除数据:\n");
	int num = pc->sz;
	for (int i = 0; i < num; i++)
	{
		pc->sz--;
	}
	printf("清空完毕\n");
}

8.退出通讯录

手动开辟,手动释放

 //退出程序,释放空间
void ExitContact(contact* pc)
{
	//释放空间
	free(pc->data);
	pc->data = NULL;
	pc->sz = 0;
	pc->capciaty = 0;
}

运行展示:

在这里插入图片描述

到此这篇关于C语言模拟实现动态通讯录的文章就介绍到这了,更多相关C语言 动态通讯录内容请搜索自学编程网以前的文章或继续浏览下面的相关文章希望大家以后多多支持自学编程网!

编程技巧