通讯录(C 语言)

目录

一、通讯录设计思路

1. 伪代码设计思路

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

提供方法:

  1. 添加联系人信息
  2. 删除指定联系人信息
  3. 查找指定联系人信息
  4. 修改指定联系人信息
  5. 显示所有联系人信息
  6. 清空所有联系人
  7. 以名字排序所有联系人

2. 代码设计思路

通过对上述伪代码的分析,我们使用结构体 info_person 来表示个人信息。

c 复制代码
// 个人信息结构声明
typedef struct info_person
{
	char name[20];  // 姓名
	char sex[5];  // 性别
	size_t age;  // 年龄
	char phone[12];  // 电话
	char address[40];  // 住址
}info_person;

接着再使用一个结构体 ContacksList 来表示通讯录,该通讯录包含一个结构体 info_person 数组,大小为 100,用来存储 100 个人的信息。此外还应该包含一个 size_t 类型的成员 size 用来表示当前存储个人信息的数量,这也方便了上述伪代码中要求的方法设计。

c 复制代码
// 常量声明
#define SIZE_INFO 100

// 通讯录结构声明
typedef struct ContacksList
{
	info_person infos[SIZE_INFO];
	size_t size;
}ContacksList;

下面就是使用有意义的函数名来表示上述方法。

c 复制代码
// 方法

// 1. 添加联系人信息
void AddContack(ContacksList* cl);

// 2. 删除指定联系人信息
void DeleteContack(ContacksList* cl, char* name);

// 3. 查找指定联系人信息
void FindContack(const ContacksList* cl, char* name);

// 4. 修改指定联系人信息
void ModifyContack(ContacksList* cl, char* name);

// 5. 显示所有联系人信息
void PrintContack(const ContacksList* cl);

// 6. 清空所有联系人
void ClearContack(ContacksList* cl);

// 7. 以名字排序所有联系人
void SortByName(ContacksList* cl);

以上就是头文件 ContacksList.h 包含的基本内容,剩下的就是方法的实现和代码的测试。

二、代码实现

整体代码分成三个文件:头文件 ContacksList.h,方法定义文件 ContacksList.c,测试文件 test.c。由于头文件在前面已经给出,下面就只给出剩下两个文件。

方法定义文件 ContacksList.c

c 复制代码
// 头文件
#include "ContacksList.h"
#include <assert.h>
#include <string.h>

// 方法

// 1. 添加联系人信息
void AddContack(ContacksList* cl)
{
	assert(cl);
	// 通讯录已满
	if (CAPACITY == cl->size)
	{
		printf("通讯录已满,添加失败!\n");
		return;
	}
	// 添加
	// 
	// 输入联系人的相关信息
	info_person tmp;
	printf("请输入联系人的信息->");
	printf("姓名: ");
	scanf("%s", tmp.name);
	printf("性别: ");
	scanf("%s", tmp.sex);
	printf("年龄: ");
	scanf("%zd", &tmp.age);
	printf("电话: ");
	scanf("%s", tmp.phone);
	printf("地址: ");
	scanf("%s", tmp.address);
	// 拷贝
	cl->infos[cl->size] = tmp;
	// 人数 +1
	++cl->size;
	printf("添加成功!\n");
}

// 2. 删除指定联系人信息
void DeleteContack(ContacksList* cl)
{
	assert(cl);
	// 删除
	//
	// 查找指定联系人
	char name[20];
	printf("请输入删除人的姓名: ");
	scanf("%s", name);
	int i = FindContack(cl, name);
	// 找到了
	if (-1 != i)
	{
		// 把该位置往后的联系人往前移
		while (i < cl->size - 1)
		{
			// 前移
			cl->infos[i] = cl->infos[i + 1];
			// 下一个
			++i;
		}
		// 联系人 -1
		--cl->size;
		printf("删除成功!\n");
	}
	else
	{
		printf("删除失败!\n");
	}
}

// 3. 查找指定联系人信息
int FindContack(const ContacksList* cl, char* name)
{
	assert(cl);
	// 通讯录为空
	if (0 == cl->size)
		return -1;

	// 输入查找人的姓名
	char tmp[20] = { 0 };
	if (NULL == name)
	{
		name = tmp;
		printf("请输入查找人的姓名: ");
		scanf("%s", name);
	}

	// 查找
	int i;
	for (i = 0; i < cl->size; ++i)
	{
		// 找到
		if (strcmp(cl->infos[i].name, name) == 0)
		{
			return i;
		}
	}
	// 没找到
	return -1;
}

// 4. 修改指定联系人信息
void ModifyContack(ContacksList* cl)
{
	assert(cl);
	// 查找指定联系人
	char name[20];
	printf("请输入修改人的姓名: ");
	scanf("%s", name);
	int i = FindContack(cl, name);
	// 找到了
	if (-1 != i)
	{
		// 输入联系人修改后的相关信息
		info_person tmp;
		printf("请输入联系人的信息->");
		printf("姓名: ");
		scanf("%s", tmp.name);
		printf("性别: ");
		scanf("%s", tmp.sex);
		printf("年龄: ");
		scanf("%zd", &tmp.age);
		printf("电话: ");
		scanf("%s", tmp.phone);
		printf("地址: ");
		scanf("%s", tmp.address);
		// 修改
		cl->infos[i] = tmp;
		printf("修改成功!\n");
	}
	else
	{
		printf("修改失败!\n");
	}
}

// 5. 显示所有联系人信息
void PrintContack(const ContacksList* cl)
{
	assert(cl);
	// 标题行
	printf("%-10s%-8s%-8s%-15s%-10s\n", "姓名", "性别", "年龄", "电话", "地址");
	// 输出
	int i;
	for (i = 0; i < cl->size; ++i)
	{
		printf("%-10s%-8s%-8zd%-15s%-10s\n", cl->infos[i].name, cl->infos[i].sex, cl->infos[i].age, cl->infos[i].phone, cl->infos[i].address);
	}
}

// 6. 清空所有联系人
void ClearContack(ContacksList* cl)
{
	assert(cl);
	// 清空
	cl->size = 0;
}

// 7. 以名字排序所有联系人
void SortByName(ContacksList* cl)
{
	assert(cl);
	// 冒泡排序
	int i;
	for (i = 0; i < cl->size - 1; ++i)
	{
		int j;
		for (j = 0; j < cl->size - 1 - i; ++j)
		{
			// 相邻比较
			if (strcmp(cl->infos[j].name, cl->infos[j + 1].name) > 0)
			{
				// 交换
				info_person tmp = cl->infos[j];
				cl->infos[j] = cl->infos[j + 1];
				cl->infos[j + 1] = tmp;
			}
		}
	}
	printf("按名字身升序排序成功!\n");
}

测试文件 test.c

c 复制代码
// 头文件
#include "ContacksList.h"

// 菜单
void menu()
{
	printf("****************************************************\n");
	printf("***********1. Add          2. Delete   *************\n");
	printf("***********3. Find         4. Modify   *************\n");
	printf("***********5. Print        6. Clear    *************\n");
	printf("***********7. Sort         0. Exit     *************\n");
	printf("****************************************************\n");
}

int main()
{
	// 创建通讯录
	ContacksList cl = { {0}, 0 };
	// 选择操作
	int select = 0;
	int i = 0;
	do
	{
		// 菜单
		menu();
		// 选择
		printf("请选择: ");
		scanf("%d", &select);
		switch (select)
		{
		case 1:
			AddContack(&cl);
			break;
		case 2:
			DeleteContack(&cl);
			break;
		case 3:
			i = FindContack(&cl, NULL);
			printf("%-10s%-8s%-8s%-15s%-10s\n", "姓名", "性别", "年龄", "电话", "地址");
			printf("%-10s%-8s%-8zd%-15s%-10s\n", cl.infos[i].name, cl.infos[i].sex, cl.infos[i].age, cl.infos[i].phone, cl.infos[i].address);
			break;
		case 4:
			ModifyContack(&cl);
			break;
		case 5:
			PrintContack(&cl);
			break;
		case 6:
			ClearContack(&cl);
			break;
		case 7:
			SortByName(&cl);
			break;
		case 0:
			printf("退出通讯录!\n");
			break;
		default:
			printf("选择错误,请重新选择!\n");
			break;
		}
	} while (select);

	return 0;
}

三、程序运行演示

四、整体分析

该通讯录是一个静态通讯录,容量是固定的,当数据超出容量时不够存储,当数据少于容量时造成空间的浪费。后面作者会把该通讯录升级为动态通讯录,当容量不够的时候会进行增容。

在方法实现中,删除指定联系人函数 DeleteContack() 和修改指定联系人函数 ModifyContack() 都需要先找到指定的联系人,所以可以稍微修改一下查找指定联系人函数 FindContack(),然后再前面两个函数中调用该函数,这样就减少了代码的冗余。删除操作需要判断通讯录是否为空,插入操作需要判断通讯录是否已满。

当然读者可以自行根据需要进行修改,这里只提供一个大概思路和基础功能的实现。

相关推荐
Ajiang28247353041 小时前
对于C++中stack和queue的认识以及priority_queue的模拟实现
开发语言·c++
幽兰的天空1 小时前
Python 中的模式匹配:深入了解 match 语句
开发语言·python
Theodore_10224 小时前
4 设计模式原则之接口隔离原则
java·开发语言·设计模式·java-ee·接口隔离原则·javaee
网易独家音乐人Mike Zhou5 小时前
【卡尔曼滤波】数据预测Prediction观测器的理论推导及应用 C语言、Python实现(Kalman Filter)
c语言·python·单片机·物联网·算法·嵌入式·iot
zy张起灵5 小时前
48v72v-100v转12v 10A大功率转换电源方案CSM3100SK
经验分享·嵌入式硬件·硬件工程
----云烟----6 小时前
QT中QString类的各种使用
开发语言·qt
lsx2024066 小时前
SQL SELECT 语句:基础与进阶应用
开发语言
开心工作室_kaic7 小时前
ssm161基于web的资源共享平台的共享与开发+jsp(论文+源码)_kaic
java·开发语言·前端
向宇it7 小时前
【unity小技巧】unity 什么是反射?反射的作用?反射的使用场景?反射的缺点?常用的反射操作?反射常见示例
开发语言·游戏·unity·c#·游戏引擎
武子康7 小时前
Java-06 深入浅出 MyBatis - 一对一模型 SqlMapConfig 与 Mapper 详细讲解测试
java·开发语言·数据仓库·sql·mybatis·springboot·springcloud