简单通讯录的实现

这次我们来实现一个简单的通讯录

目录

1.基本框架及的实现

2.相关结构体的实现

3.通讯录的初始化

4.新建联系人

5.显示所有联系人信息

 6.删除联系人

7.查找指定联系人

8.修改联系人信息

9.对联系人进行排序

10.完整代码


既然是通讯录,我们要实现以下内容

1.我们要储存的是人的信息,我们要有人的姓名,年龄,性别,地址,电话等等

2.我们的通讯录要能储存很多人的信息,比如100个

3.通讯录的功能:增加联系人,删除联系人,查找联系人,修改联系人信息,显示所有联系人,还可以写一个排序功能(按年龄,名字排序等等)

我们还是使用工程化的写法来完成

1.基本框架及菜单的实现

 我们先来实现基本框架,我们先要有一个菜单,来显示我们的功能

void menu() {
	printf("*****************************\n");
	printf("*****1. 新建联系人     ******\n");
	printf("*****2. 删除联系人     ******\n");
	printf("*****3. 查找联系人     ******\n");
	printf("*****4. 修改联系人信息 ******\n");
	printf("*****5. 联系人列表     ******\n");
	printf("*****6. 联系人列表排序 ******\n");
	printf("*****0. 退出通讯录     ******\n");
	printf("*****************************\n");
}
int main() {
	int input=0;
	do {
		menu();
		printf("请选择:>");
		scanf("%d", &input);
		switch (input) {
		case 1:
			break;
		case 2:
			break;
		case 3:
			break;
		case 4:
			break;
		case 5:
			break;
		case 6:
			break;
		case 0:
			printf("退出通讯录!\n");
			break;
		default:
			printf("选择错误!请重新选择!\n");
			break;
		}
	} while (input);
}

并且我们启动通讯录后要每次都能打印出功能列表,我们使用do-while语句来完成,并且使用switch来完成我们的框架,菜单按照自己的喜好进行打印即可

2.相关结构体的实现

typedef struct PeoInfo {
	char name[20];//名字
	int age;//年龄
	char sex[5];//性别
	char addr[30];//住址
	char tele[12];//电话
}PeoInfo;

typedef struct Contact {
	PeoInfo data[100];//存放人的信息
	int sz;//当前存放信息数量
}Contact;

我们先创建人的信息结构体PeoInfo,接着因为我们要存放100个人信息,我们创建通讯录的结构体Contact,接着我们就可以创建通讯录了,有了通讯录后,我们需要对他进行初始化,所以我们在.h文件里对其进行声明,在.c文件里实现

3.通讯录的初始化

void InitContact(Contact* pc){//初始化通讯录
	assert(pc);
	pc->sz = 0;
	memset(pc->data, 0,sizeof(pc->data));
}

我们将sz先置为0,再使用memset函数对其进行填充,因为我们传的是结构体的地址,我们通过地址找到结构体的数组,此时我们用sizeof计算出的就是整个数组的大小,我们将这块空间初始化为0

4.新建联系人

在完成新建联系人前,我们先将我们的代码的通用性提高,使用#define来完成

#define MAX 100//最大联系人数量
#define NAME_MAX 20//最大名字字符数
#define SEX_MAX 5//最大性别字符数
#define ADDR_MAX 30//最大住址字符数
#define TELE_MAX 12//最大电话字符数

typedef struct PeoInfo {
	char name[NAME_MAX];//名字
	int age;//年龄
	char sex[SEX_MAX];//性别
	char addr[ADDR_MAX];//住址
	char tele[TELE_MAX];//电话
}PeoInfo;

typedef struct Contact {
	PeoInfo data[MAX];//存放人的信息
	int sz;//当前存放信息数量
}Contact;

这样修改可以大大增加代码的可维护性,比如我们未来想要让通讯录里可以有200个联系人,只需修改MAX的值为200即可

//新建联系人
void AddContact(Contact* pc) {
	assert(pc);
	if (pc->sz == MAX) {
		printf("通讯录已满,无法添加!\n");
		return;
	}
	//添加一个联系人
	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].addr);
	printf("请输入电话:>");
	scanf("%s", pc->data[pc->sz].tele);
	pc->sz++;
}

接着就是我们的新建联系人了,我们首先要判断通讯录是否已满,已满的话我们输出信息,并退出,接着就是添加联系人,因为除了年龄外其他都是数组,数组名就是地址,所以不需要取地址,而年龄作为整数是需要取地址的,最后别忘了让sz++

5.显示所有联系人信息

当我们新建一个联系人后,我们想要对程序进行检测,就需要打印出我们的数据,所以我们先完成显示联系人的信息

//显示通讯录中所有联系人信息
void ShowContact(const Contact* pc) {
	assert(pc);
	int i = 0;
	printf("%-20s\t%-4s\t%-5s\t%-20s\t%-12s\n","姓名","年龄","性别","住址","电话号码");
	for (i = 0; i < pc->sz; i++) {
		printf("%-20s\t%-4d\t%-5s\t%-20s\t%-12s\n",pc->data[i].name,
			pc->data[i].age,
			pc->data[i].sex,
			pc->data[i].addr,
			pc->data[i].tele);
	}
}

我们使用左对齐来保证美观,使用for循环打印即可,并且因为是打印,我们不会修改信息,所以可以加上const,我们来测试一下

 6.删除联系人

我们的删除联系人可以通过输入一个名字,然后删除该联系人信息

我们的删除方法有两种,一种是将后续数组的联系人全部往前挪动一位,然后使sz-1,第二种是可以让最后一位联系人直接覆盖当前联系人的位置,然后sz-1,第一种不会打乱顺序,但是效率低,第二种效率高,但是会打乱顺序,大家自行判断选择即可,我这里选择第一种

//删除联系人
void DelContact(Contact* pc) {
	assert(pc);
	char name[NAME_MAX] = { 0 };
	if (pc->sz == 0) {
		printf("通讯录为空!无法删除!\n");
		return;
	}
	//查找需要删除的人
	printf("请输入需要删除联系人的姓名:>");
	scanf("%s", name);
	int i = 0;
	int del = 0;
	for (i = 0; i < pc->sz; i++) {
		if(strcmp(pc->data[i].name, name) == 0) {
			del = i;
			break;
		}
	}
	//删除
	for (i = del; i < pc->sz - 1; i++) {
		pc->data[i] = pc->data[i + 1];
	}
	pc->sz--;
	printf("删除联系人成功!\n");
}

我们先要判断通讯录是否为空,不为空我们才能进行删除操作,接着我们通过strcmp进行依次比较,找到需要删除的联系人的下标,然后将后续联系人往前移动,移动时要注意,我们的终止条件是i<pc->sz-1,这样我们可以把最后一位联系人也往前移动一位,此时数组里有两个最后一位联系人,但我们只需将sz-1即可让数组无法访问到多出来的最后一位

我们发现我们后续要实现的查找和修改,还有我们已经实现的删除,都需要对数组进行查找,我们可以查找封装成一个函数多次使用,提高代码的复用性

//根据名字查找
FindByName(const 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) {
	assert(pc);
	char name[NAME_MAX] = { 0 };
	if (pc->sz == 0) {
		printf("通讯录为空!无法删除!\n");
		return;
	}
	//查找需要删除的人
	printf("请输入需要删除联系人的姓名:>");
	scanf("%s", name);
	int ret = FindByName(pc, name);
	if (ret == -1) {
		printf("该联系人不存在!\n");
		return;
	}
	//删除
	int i = 0;
	for (i = ret; i < pc->sz - 1; i++) {
		pc->data[i] = pc->data[i + 1];
	}
	pc->sz--;
	printf("删除联系人成功!\n");
}

7.查找指定联系人

//查找联系人
void SearchContact(const Contact* pc) {
	assert(pc);
	char name[NAME_MAX] = { 0 };
	printf("请输入要查找的联系人的姓名:>");
	scanf("%s", name);
	int pos = FindByName(pc, name);
	if (pos == -1) {
		printf("该联系人不存在!\n");
		return;
	}
	printf("%-20s\t%-4s\t%-5s\t%-20s\t%-12s\n", "姓名", "年龄", "性别", "住址", "电话号码");
		printf("%-20s\t%-4d\t%-5s\t%-20s\t%-12s\n", pc->data[pos].name,
			pc->data[pos].age,
			pc->data[pos].sex,
			pc->data[pos].addr,
			pc->data[pos].tele);
}

我们使用刚才封装的查找函数即可,找到之后将他打印出来

8.修改联系人信息

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

修改也是先查找,再修改,使用我们之前的代码即可拼接而成,修改信息就是再录入一遍该联系人

9.对联系人进行排序

对通讯录排序可以通过对年龄排序,也可以通过名字的字典序来进行排序,我这里选择名字排序,大家可以根据需要进行添加多种排序方法

int cmp_name(const void* e1, const void* e2) {
	return strcmp(((PeoInfo*)e1)->name, ((PeoInfo*)e2)->name);
}
//通讯录排序
void SortContact(Contact* pc) {
	assert(pc);
	qsort(pc, pc->sz, sizeof(pc->data[0]),cmp_name);
	printf("已将通讯录按名字进行排序!\n");
}

我们使用qsort即可完成,不知道如何使用该函数的可以参考我的往前文章,在回调函数里我详细介绍了该函数

(3条消息) 万字讲解!进阶指针!_KLZUQ的博客-CSDN博客

 到这里,我们的简单通讯录就已经完成,后续我们可以文件操作系统来对其进行扩展,最后我会附上全部代码

10.完整代码

#pragma once
//Contact.h
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<assert.h>
#define MAX 100//最大联系人数量
#define NAME_MAX 20//最大名字字符数
#define SEX_MAX 5//最大性别字符数
#define ADDR_MAX 30//最大住址字符数
#define TELE_MAX 12//最大电话字符数

typedef struct PeoInfo {
	char name[NAME_MAX];//名字
	int age;//年龄
	char sex[SEX_MAX];//性别
	char addr[ADDR_MAX];//住址
	char tele[TELE_MAX];//电话
}PeoInfo;

typedef struct Contact {
	PeoInfo data[MAX];//存放人的信息
	int sz;//当前存放信息数量
}Contact;
//初始化通讯录
void InitContact(Contact* pc);

//新建联系人
void AddContact(Contact* pc);

//显示通讯录中所有联系人信息
void ShowContact(const Contact* pc);

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

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

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

//通讯录排序
void SortContact(Contact* pc);
#include"Contact.h"
//Contact.c

//初始化通讯录
void InitContact(Contact* pc){
	assert(pc);
	pc->sz = 0;
	memset(pc->data, 0,sizeof(pc->data));
}

//新建联系人
void AddContact(Contact* pc) {
	assert(pc);
	if (pc->sz == MAX) {
		printf("通讯录已满,无法添加!\n");
		return;
	}
	//添加一个联系人
	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].addr);
	printf("请输入电话:>");
	scanf("%s", pc->data[pc->sz].tele);
	pc->sz++;
}

//显示通讯录中所有联系人信息
void ShowContact(const Contact* pc) {
	assert(pc);
	int i = 0;
	printf("%-20s\t%-4s\t%-5s\t%-20s\t%-12s\n","姓名","年龄","性别","住址","电话号码");
	for (i = 0; i < pc->sz; i++) {
		printf("%-20s\t%-4d\t%-5s\t%-20s\t%-12s\n",pc->data[i].name,
			pc->data[i].age,
			pc->data[i].sex,
			pc->data[i].addr,
			pc->data[i].tele);
	}
}
//根据名字查找
FindByName(const 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) {
	assert(pc);
	char name[NAME_MAX] = { 0 };
	if (pc->sz == 0) {
		printf("通讯录为空!无法删除!\n");
		return;
	}
	//查找需要删除的人
	printf("请输入需要删除联系人的姓名:>");
	scanf("%s", name);
	int ret = FindByName(pc, name);
	if (ret == -1) {
		printf("该联系人不存在!\n");
		return;
	}
	//删除
	int i = 0;
	for (i = ret; i < pc->sz - 1; i++) {
		pc->data[i] = pc->data[i + 1];
	}
	pc->sz--;
	printf("删除联系人成功!\n");
}

//查找联系人
void SearchContact(const Contact* pc) {
	assert(pc);
	char name[NAME_MAX] = { 0 };
	printf("请输入要查找的联系人的姓名:>");
	scanf("%s", name);
	int pos = FindByName(pc, name);
	if (pos == -1) {
		printf("该联系人不存在!\n");
		return;
	}
	printf("%-20s\t%-4s\t%-5s\t%-20s\t%-12s\n", "姓名", "年龄", "性别", "住址", "电话号码");
		printf("%-20s\t%-4d\t%-5s\t%-20s\t%-12s\n", pc->data[pos].name,
			pc->data[pos].age,
			pc->data[pos].sex,
			pc->data[pos].addr,
			pc->data[pos].tele);
}

//修改联系人信息
void ModifyContact(Contact* pc) {
	assert(pc);
	char name[NAME_MAX] = { 0 };
	printf("请输入要修改的联系人的姓名:>");
	scanf("%s", name);
	int pos = FindByName(pc, name);
	if (pos == -1) {
		printf("该联系人不存在!\n");
		return;
	}
	printf("请输入姓名:>");
	scanf("%s", pc->data[pos].name);
	printf("请输入年龄:>");
	scanf("%d", &(pc->data[pos].age));
	printf("请输入性别:>");
	scanf("%s", pc->data[pos].sex);
	printf("请输入住址:>");
	scanf("%s", pc->data[pos].addr);
	printf("请输入电话:>");
	scanf("%s", pc->data[pos].tele);
	printf("修改成功!\n");
}
int cmp_name(const void* e1, const void* e2) {
	return strcmp(((PeoInfo*)e1)->name, ((PeoInfo*)e2)->name);
}
//通讯录排序
void SortContact(Contact* pc) {
	assert(pc);
	qsort(pc, pc->sz, sizeof(pc->data[0]),cmp_name);
	printf("已将通讯录按名字进行排序!\n");
}
#include"Contact.h"
//test.c
void menu() {
	printf("*****************************\n");
	printf("*****1. 新建联系人     ******\n");
	printf("*****2. 删除联系人     ******\n");
	printf("*****3. 查找联系人     ******\n");
	printf("*****4. 修改联系人信息 ******\n");
	printf("*****5. 联系人列表     ******\n");
	printf("*****6. 联系人列表排序 ******\n");
	printf("*****0. 退出通讯录     ******\n");
	printf("*****************************\n");
}
int main() {
	int input=0;
	//创建通讯录
	Contact con;
	//初始化通讯录
	InitContact(&con);
	do {
		menu();
		printf("请选择:>");
		scanf("%d", &input);
		switch (input) {
		case 1:
			AddContact(&con);
			break;
		case 2:
			DelContact(&con);
			break;
		case 3:
			SearchContact(&con);
			break;
		case 4:
			ModifyContact(&con);
			break;
		case 5:
			ShowContact(&con);
			break;
		case 6:
			SortContact(&con);
			break;
		case 0:
			printf("退出通讯录!\n");
			break;
		default:
			printf("选择错误!请重新选择!\n");
			break;
		}
	} while (input);
}

希望大家可以有所收获

如有错误,还请指正

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值