通讯录动态版本的实现(源码+分析)

通讯录功能

实现的通讯录为一个动态增加版本的通讯录,该通讯录能够通过需求自行的增加存放联系人的数量,主要功能为:
1.能够根据需求(要存多少联系人就给多少空间)存放联系人信息
联系人的信息:姓名+性别+年龄+电话+地址
2.能够增加人的信息
3.能够删除指定人的信息
4.能够查找指定人的信息
5.能够修改指定人的信息
6.能够显示通讯录

关键功能的实现

1.创建和初始化通讯录

创建通讯录:通讯录能够保存联系人的多个信息,所以我们先创建一个结构体,这个结构体能够包含一个人的所有信息,定义为 struct PeoInfo ;紧接着在创建一个通讯录,这个通讯录能够存放联系人,且能够记录通讯录的人数,所以再创建一个嵌套的结构体,定义为 struct Contact
代码如下:
struct PeoInfo(为了后期的使用方便,将其重定义为 PeoInfo )

typedef struct PeoInfo
{
	char name[MAX_NAME];
	char sex[SEX];
	int  age;
	char tele[MAX_TELE];
	char addr[MAX_ADDR];
	
} PeoInfo;

struct Contact(为了后期的使用方便,将其重定义为 Contact )

typedef struct Contact
{
	PeoInfo* data;//结构体指针,指向结构体 PeoInfo
	int sz;//sz用来记录通讯录扩容前联系人的人数
	int capacity;//capacity用来记录扩容后该通讯录的最大容量(即最大能存多少联系人)
}Contact;

初始化通讯录:我们规定通讯录最开始能够存放3人(可自行规定)。
如下:

void InitContact(Contact* pc)
{
	pc->data = (PeoInfo*) malloc(MAX_SZ*sizeof(PeoInfo));//通过动态内存函数来定义存放联系人的数目
	if (pc->data == NULL)
	{
		perror("InitContact");//当开辟内存失败时,打印出错误信息
		return;
	}
	pc->sz = 0;
	pc->capacity = MAX_SZ;
}

2.增加联系人

void AddContact(Contact* pc)
{
	if (pc->sz == pc->capacity)//判断若存储的通讯录人数已达到最大容量,则进行动态增容
	{
	    //通过realloc函数动态的增加通讯录容量
		PeoInfo* ptr=(PeoInfo*)realloc(pc->data, (ADD_CAP + pc->capacity) * sizeof(PeoInfo));
		if (ptr != NULL)
		{
			pc->data = ptr;
			pc->capacity += ADD_CAP;//规定每次当通讯录满时,则增加2个人的容量
			printf("增容成功!\n");
		}
		else
		{
			printf("增容失败\n");
			return;
		}
	}
	printf("请输入姓名:>");
	scanf("%s", pc->data[pc->sz].name);//通过指针来访问结构体成员,下同
	printf("请输入性别:>");
	scanf("%s", pc->data[pc->sz].sex);
	printf("请输入年龄:>");
	scanf("%d", &(pc->data[pc->sz].age));
	printf("请输入电话:>");
	scanf("%s", pc->data[pc->sz].tele);
	printf("请输入地址:>");
	scanf("%s", pc->data[pc->sz].addr);
	pc->sz++;
	printf("增加成功!\n");
}

3.删除联系人

注:在实现删除功能前,需先找到要删除联系人的信息,所以,在删除前要多增加一个函数,该函数用来找到被删除联系人。

static int FindContact(const Contact* pc,char name[])//找到被删除联系人,且该函数用static修饰保证只能在该文件内使用
{
	int i = 0;
	for (i = 0; i < pc->sz; i++)
	{
		if (strcmp(name, (pc->data[i]).name) == 0)
			return i;//返回该联系人在通讯录中的位置
	}
	return -1;
}
void DelContact(Contact* pc)//删除联系人
{
	char name[MAX_NAME] = { 0 };
	printf("请输入要删除的联系人:>");
	scanf("%s", name);
	int x = FindContact(pc,name);
	if (x < 0)
	{
		printf("没找到联系人\n");
	}
	else
	{
		int i = 0;
		for (i = x; x < pc->sz - 1; x++)
		{
			pc->data[x] = pc->data[x + 1];//实现删除的功能即为用后一个联系人的信息覆盖前一个联系人的信息
		}
		pc->sz--;//删除完成后,通讯录减少一人
		printf("删除成功!\n");
	}
}

4.查找联系人

在查找联系人之前,需先知道被查找人在通讯录中的位置,所以在实现查找功能的函数中也需用到 FindContact 函数来寻找联系人所在的位置。

void SearchContact(Contact* pc)
{
	char name[MAX_NAME] = { 0 };
	printf("请输入要查找的联系人:>");
	scanf("%s", name);
	int x = FindContact(pc, name);//x为被查找的联系人的位置
	if (x < 0)
	{
		printf("没找到联系人\n");
	}
	else
	{
		printf("%-20s\t%-5s\t%-5s\t%-12s\t%-20s\t\n", "姓名", "性别", "年龄", "电话", "地址");
		printf("%-20s\t%-5s\t%-5d\t%-12s\t%-20s\t\n",
			pc->data[x].name,
			pc->data[x].sex,
			pc->data[x].age,
			pc->data[x].tele,
			pc->data[x].addr);
	}
}

5.修改联系人

同删除、查找一样,在修改前需知道被修改联系人的位置,用 FindContact 函数来返回位置。

void ModifyContact(Contact* pc)
{
	char name[MAX_NAME] = { 0 };
	printf("请输入要修改的联系人:>");
	scanf("%s", name);
	int x = FindContact(pc, name);//x就为被修改人的位置
	if (x < 0)
	{
		printf("没找到联系人\n");
	}
	else
	{
		printf("请输入姓名:>");
		scanf("%s", pc->data[x].name);
		printf("请输入性别:>");
		scanf("%s", pc->data[x].sex);
		printf("请输入年龄:>");
		scanf("%d", &(pc->data[x].age));
		printf("请输入电话:>");
		scanf("%s", pc->data[x].tele);
		printf("请输入地址:>");
		scanf("%s", pc->data[x].addr);
		printf("修改成功!\n");
	}
}

代码总览

为了更好的实现通讯录,我们将程序分三个文件,分别是:
test.c —— 测试通讯录的模块
contact.h —— 类型定义,函数声明
contact.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      ***\n");
	printf("***        0.Exit       ***\n");
	printf("***************************\n");
}

enum Option //将每个功能的名称定义为一个枚举类型的成员,使辨识度更高
{
	EXIT,
	ADD,
	DEL,
	SEARCH,
	MODIFY,
	PRINT,
};
 
int main()
{
	Contact con;
	InitContact(&con);
	int input = 0;
	do
	{
		menu();
		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 EXIT:
				DestoryContact(&con);//销毁通讯录
				printf("退出通讯录\n");
				break;
			default:
				printf("选择错误,请重新选择:");
				break;
		}
	} while (input);
	return 0;
}

contact.h

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

#define MAX_NAME 20
#define SEX 10
#define MAX_ADDR 100
#define MAX_TELE 12
#define MAX_SZ 3
#define ADD_CAP 2
#define MAX 1000

typedef struct PeoInfo
{
	char name[MAX_NAME];
	char sex[SEX];
	int  age;
	char tele[MAX_TELE];
	char addr[MAX_ADDR];	
} PeoInfo;  //重定义为了使用方便,下同

typedef struct Contact
{
	PeoInfo* data;
	int sz;
	int capacity;
}Contact;  //重定义

void InitContact(Contact* pc);  //初始化通讯录

void AddContact(Contact* pc);  //增加联系人

void PrintContact(const Contact* pc);  //打印通讯录

void DelContact(Contact* pc);  //删除联系人

void SearchContact(Contact* pc);  //查找联系人

void ModifyContact(Contact* pc);  //修改联系人

void DestoryContact(Contact* pc);  //销毁通讯录

contact.c

#include"contact.h"
void InitContact(Contact* pc)
{
	pc->data = (PeoInfo*) malloc(MAX_SZ*sizeof(PeoInfo));
	if (pc->data == NULL)
	{
		perror("InitContact");
		return;
	}
	pc->sz = 0;
	pc->capacity = MAX_SZ;
}

void DestoryContact(Contact* pc)
{
	free(pc->data);
	pc->data = NULL;
	pc->sz = 0;
	pc->capacity = 0;
}

void AddContact(Contact* pc)
{
	if (pc->sz == pc->capacity)
	{
		PeoInfo* ptr=(PeoInfo*)realloc(pc->data, (ADD_CAP + pc->capacity) * sizeof(PeoInfo));
		if (ptr != NULL)
		{
			pc->data = ptr;
			pc->capacity += ADD_CAP;
			printf("增容成功!\n");
		}
		else
		{
			printf("增容失败\n");
			return;
		}
	}
	printf("请输入姓名:>");
	scanf("%s", pc->data[pc->sz].name);
	printf("请输入性别:>");
	scanf("%s", pc->data[pc->sz].sex);
	printf("请输入年龄:>");
	scanf("%d", &(pc->data[pc->sz].age));
	printf("请输入电话:>");
	scanf("%s", pc->data[pc->sz].tele);
	printf("请输入地址:>");
	scanf("%s", pc->data[pc->sz].addr);
	pc->sz++;
	printf("增加成功!\n");
}

void PrintContact(const Contact* pc)
{
	printf("%-20s\t%-5s\t%-5s\t%-12s\t%-20s\t\n", "姓名", "性别", "年龄", "电话", "地址");
	int i = 0;
	for (i = 0; i < pc->sz; i++)
	{
		printf("%-20s\t%-5s\t%-5d\t%-12s\t%-20s\t\n",
			pc->data[i].name,
			pc->data[i].sex,
			pc->data[i].age,
			pc->data[i].tele,
			pc->data[i].addr);
	}
}

static int FindContact(const Contact* pc,char name[])
{
	int i = 0;
	for (i = 0; i < pc->sz; i++)
	{
		if (strcmp(name, (pc->data[i]).name) == 0)
			return i;
	}
	return -1;
}
void DelContact(Contact* pc)
{
	char name[MAX_NAME] = { 0 };
	printf("请输入要删除的联系人:>");
	scanf("%s", name);
	int x = FindContact(pc,name);
	if (x < 0)
	{
		printf("没找到联系人\n");
	}
	else
	{
		int i = 0;
		for (i = x; x < pc->sz - 1; x++)
		{
			pc->data[x] = pc->data[x + 1];
		}
		pc->sz--;
		printf("删除成功!\n");
	}
}

void SearchContact(Contact* pc)
{
	char name[MAX_NAME] = { 0 };
	printf("请输入要查找的联系人:>");
	scanf("%s", name);
	int x = FindContact(pc, name);
	if (x < 0)
	{
		printf("没找到联系人\n");
	}
	else
	{
		printf("%-20s\t%-5s\t%-5s\t%-12s\t%-20s\t\n", "姓名", "性别", "年龄", "电话", "地址");
		printf("%-20s\t%-5s\t%-5d\t%-12s\t%-20s\t\n",
			pc->data[x].name,
			pc->data[x].sex,
			pc->data[x].age,
			pc->data[x].tele,
			pc->data[x].addr);
	}
}

void ModifyContact(Contact* pc)
{
	char name[MAX_NAME] = { 0 };
	printf("请输入要修改的联系人:>");
	scanf("%s", name);
	int x = FindContact(pc, name);
	if (x < 0)
	{
		printf("没找到联系人\n");
	}
	else
	{
		printf("请输入姓名:>");
		scanf("%s", pc->data[x].name);
		printf("请输入性别:>");
		scanf("%s", pc->data[x].sex);
		printf("请输入年龄:>");
		scanf("%d", &(pc->data[x].age));
		printf("请输入电话:>");
		scanf("%s", pc->data[x].tele);
		printf("请输入地址:>");
		scanf("%s", pc->data[x].addr);
		printf("修改成功!\n");
	}
}

运行效果

在这里插入图片描述

  • 47
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 28
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值