当前位置: 首页 > news >正文

结构体熟练掌握--实现通讯录

在这里插入图片描述

  • 魔王的介绍:😶‍🌫️一名双非本科大一小白。
  • 魔王的目标:🤯努力赶上周围卷王的脚步。
  • 魔王的主页:🔥🔥🔥大魔王.🔥🔥🔥
    在这里插入图片描述
    ❤️‍🔥大魔王与你分享:无人问津也好,技不如人也罢,你都要是安静下来去做自己该做的事,而不是让内心烦躁、焦虑,毁掉你本就不多的热情和定力。

文章目录

  • 一、前言
  • 二、介绍
  • 三、分布实现通讯录
    • 1.在test.c文件中创建基本格式
    • 2.创建结构体类型
    • 3.初始化通讯录
    • 4.实现AddContact函数
    • 5.实现ShowContact函数
    • 6.实现FindContact函数
    • 7.实现DelContact函数
    • 8.实现SearchContact函数
    • 9.实现ModifyContact函数
    • 10.实现SortContact函数
  • 四、总代码
    • contact.h
    • contact.c
    • test.c
  • 五、总结

一、前言

学习完结构体,我们一定会好奇它的应用场景,想要熟练掌握一个知识点,就必须让其在现实生活中熟练结合,本篇将通过结构体的灵活运用去实现简单通讯录,可以实现增加删除搜索修改展示排序六大功能。


二、介绍

test.c:测试文件
contact.h:头文件(只进行声明)
contact.c:源文件,进行函数的定义

我们会在contact.h头文件中进行声明,在contact.c源文件中进行定义,然后在test.c源文件中进行测试(也就是直接运用这些函数)。

除了头文件外,另外两个文件都要包含头文件,因为是头文件进行的声明,可以理解为另外两个文件都要用的东西我们会在头文件进行声明,之后只需要在另外两个文件中包含头文件便都可以使用了。


三、分布实现通讯录

1.在test.c文件中创建基本格式

#include "contact.h"

void menu()
{
	printf("**** 1.add    2.del    ****\n");
	printf("**** 3.search 4.modify ****\n");
	printf("**** 5.show   6.sort   ****\n");
	printf("**** 0.exit            ****\n");
}

int main()
{
	
	int input = 0;
	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("退出");
			break;
		default:
			printf("输入错误,请重新输入");
		}
	} while (input);
	return 0;
}

我们这时候就可以运行了,虽然什么都没有,不过程序是正确的。

2.创建结构体类型

我们会创建两个结构体类型,一个是存放数据的结构体类型,里面放的是一个用户的基本信息,另一个是我们直接应用的结构体,里面会有两个成员,第一个成员为上个结构体数组,因为我们的通讯录肯定不是只有一个人的信息,第二个成员为结构体数组中的成员个数。

#define NameMax 10
#define SexMax 5
#define AddrMax 10
#define TeleMax 11

//定义一个可以存放一个人数据的结构体类型
typedef struct PeoInfo
{
	char name[NameMax];
	int age;
	char sex[SexMax];
	char addr[AddrMax];
	char tele[TeleMax];
}PeoInfo;

//定义一个我们可以存放多人数据并进行判断和修改的结构体类型
typedef struct Contact
{
	PeoInfo date[100];
	int sz;
}Contact;
  • 解释:
  1. 我们进行define定义常量是为了以后方便修改,当我们发现某个不合适时,只需要在头文件中修改一下就可以了,也就是方便代码的维护。
  2. 两个结构体都进行重命名是为了在之后应用这个结构体时不再去写struct,比较方便。
  3. 因为不止一个文件要用到结构体,所以创建结构体在头文件进行。

3.初始化通讯录

void InitContact(Contact* pc)
{
	assert(pc);
	pc->sz = 0;
	memset(pc->date, 0, sizeof(pc->date));
}
  • 解释:
  1. 我们首先在测试文件的主函数内部用定义过的结构体创建
  2. 我们在测试时需要创建一个通讯录,创建的时候我们可以直接初始化为0,也可以像这样在创建完成后让通讯录中的值改为我们需要的(还是0,这种方法更好一些,因为可以改为别的值,而不是只能是0)。
  3. 我们这里用到了memset函数,对应的头文件是<string.h>,这个函数的作用就是让从给定地址开始前多少字节的内容都赋上一个特定的数值。

4.实现AddContact函数

void AddContact(Contact* pc)
{
	assert(pc);
	if (pc->sz == 100)
	{
		printf("人数已满\n");
		return;
	}
	printf("请输入要添加联系人姓名:> ");
	scanf("%s", pc->date[pc->sz].name);
	printf("请输入要添加联系人年龄:> ");
	scanf("%d", &(pc->date[pc->sz].age));
	printf("请输入要添加联系人性别:> ");
	scanf("%s", pc->date[pc->sz].sex );
	printf("请输入要添加联系人地址:> ");
	scanf("%s", pc->date[pc->sz].addr);
	printf("请输入要添加联系人电话:> ");
	scanf("%s", pc->date[pc->sz].tele);
	pc->sz++;
	printf("添加成功\n");
}
  • 解释:
  1. 首先判断是否满了(也就是我们规定的100人),如果没满,那么就执行后面的添加,如果满了,就退出函数。
  2. 为什么只有第二个加取地址呢,因为其他的都是结构体信息(PeoInfo)里不同类型的首元素地址(因为是数组,所以数组名表示首元素地址),而age的类型为int,表示的不是地址,所以需要取地址符。
  3. 每次添加一个人,结构体成员sz需要加1。

5.实现ShowContact函数

void ShowContact(const Contact* pc)
{
	assert(pc);
	printf("%-10s\t%-3s\t%-5s\t%-10s\t%-11s\n", "姓名", "年龄", "性别", "地址", "电话");
	int i = 0;
	for (i = 0; i < pc->sz; i++)
	{
		printf("%-10s\t%-3d\t%-5s\t%-10s\t%-11s\n", pc->date[i].name,
			pc->date[i].age,
			pc->date[i].sex,
			pc->date[i].addr,
			pc->date[i].tele);
	}
}
  • 解释:
  1. \t为水平制表符,也就是会空出来一段距离。
  2. 展示函数会从结构体数组的零下标开始逐个打印出全部人的信息。

6.实现FindContact函数

int FindContact(Contact* pc, char* arr)
{
	int i = 0;
	for (i = 0; i < pc->sz; i++)
	{

		int ret = strcmp(arr, pc->date[i].name);
		if (ret == 0)
			return i;//找到的话返回结构体的下标
	}
	return -1;
}

这个函数并不是六种功能的哪一个,我们之所以要专门分装出这么一个函数,是因为多个功能都需要用到这个函数,所以为了方便其他函数使用,我们把这个部分写成一个函数分离出来。

7.实现DelContact函数

void DelContact(Contact* pc)
{
	assert(pc);
	if (pc->sz==0)
	{
		printf("通讯录中没有信息\n");
		return;
	}
	printf("输入要删除人的姓名:>");
	char arr[10] = "0";
	scanf("%s", arr);
	int ret = FindContact(pc,arr);
	if (ret== -1)
	{
		printf("该姓名不存在\n");
		return;
	}
	int i = 0;
	for (i = ret; i < pc->sz - 1; i++)
	{
		pc->date[i] = pc->date[i + 1];
	}
	pc->sz--;
	printf("删除成功\n");
} 
  • 解释:
  1. 首先判断是否有成员,如果没有成员,就直接退出函数。
  2. 如果确实存在该成员,该成员的结构体下标会通过FindContact函数返回给ret,然后ret里存放的值就是该结构体数组中对应的下标。
  3. 如果确实存在该成员,我们删除的思路就是从被删除这个结构体下标开始,每个后面的覆盖前面的,最后个数sz再减1。

8.实现SearchContact函数

void SearchContact(const Contact* pc)
{
	assert(pc);
	if (pc->sz == 0)
	{
		printf("通讯录中没有信息\n");
		return;
	}
	printf("输入要查找人的姓名:>");
	char arr[10] = "0";
	scanf("%s", arr);
	int ret = FindContact(pc, arr);
	if (ret == -1)
	{
		printf("该姓名不存在\n");
		return;
	}
	printf("%-10s\t%-3d\t%-5s\t%-10s\t%-11s\n", pc->date[ret].name,
		pc->date[ret].age,
		pc->date[ret].sex,
		pc->date[ret].addr,
		pc->date[ret].tele);
}

首先判断是否含有信息,如果没有退出函数。
然后如果有这个人的信息,那个其对应的结构体下标已经通过FindContact函数返回给了ret,我们把该姓名的信息打印出来。

9.实现ModifyContact函数

如果不存在就退出,如果存在,我们将这个人的信息打印出来。

void ModifyContact(Contact* pc)
{
	assert(pc);
	if (pc->sz==0)
	{
		printf("通讯录中没有信息\n");
		return;
	}
	char arr[10] = "0";
	printf("请输入要修改人的名字:> ");
	scanf("%s", arr);
	int ret = FindContact(pc,arr);
	if (ret == -1)
	{
		printf("该联系人不存在\n");
		return;
	}
	printf("请输入要修改成的姓名:> ");
	scanf("%s", pc->date[ret].name);
	printf("请输入要修改成的年龄:> ");
	scanf("%d", &(pc->date[ret].age));
	printf("请输入要修改成的性别:> ");
	scanf("%s", pc->date[ret].sex);
	printf("请输入要修改成的地址:> ");
	scanf("%s", pc->date[ret].addr);
	printf("请输入要修改成的电话:> ");
	scanf("%s", pc->date[ret].tele);
	printf("修改成功\n");
	return;
}

这个的原理就是把找到的那个人对应的结构体下标返回给ret,然后让该下标的结构体成员重新赋一次值。

10.实现SortContact函数

int cmp(const void* e1, const void* e2)
{
	assert(e1 && e2);
	//return strcmp(((PeoInfo*)e1)->name, ((PeoInfo*)e2)->name);
	return ((PeoInfo*)e1)->age - ((PeoInfo*)e2)->age;
}

void SortContact(Contact* pc)
{
	assert(pc);
	qsort(pc->date, pc->sz, sizeof(pc->date[0]), cmp);
	
}
  • 注意:
    qsort第二个参数不是传数组能放多少元素,而是放了多少元素,因为如果没使用的位置也算进去,它会将它们这些没放的元素也参加排序。

四、总代码

contact.h

#define _CRT_SECURE_NO_WARNINGS 1

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

#define NameMax 10
#define SexMax 5
#define AddrMax 10
#define TeleMax 11

//定义一个可以存放一个人数据的结构体类型
typedef struct PeoInfo
{
	char name[NameMax];
	int age;
	char sex[SexMax];
	char addr[AddrMax];
	char tele[TeleMax];
}PeoInfo;

//定义一个我们可以存放多人数据并进行判断和修改的结构体类型
typedef struct Contact
{
	PeoInfo date[100];
	int sz;
}Contact;

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

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

//展示添加上的联系人
void ShowContact(const Contact* pc);

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

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

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

//按名字大小排序
void SortContact(Contact* pc);

contact.c

#define _CRT_SECURE_NO_WARNINGS 1

#include "contact.h"


void InitContact(Contact* pc)
{
	assert(pc);
	pc->sz = 0;
	memset(pc->date, 0, sizeof(pc->date));
}

void AddContact(Contact* pc)
{
	assert(pc);
	if (pc->sz == 100)
	{
		printf("人数已满\n");
		return;
	}
	printf("请输入要添加联系人姓名:> ");
	scanf("%s", pc->date[pc->sz].name);
	printf("请输入要添加联系人年龄:> ");
	scanf("%d", &(pc->date[pc->sz].age));
	printf("请输入要添加联系人性别:> ");
	scanf("%s", pc->date[pc->sz].sex );
	printf("请输入要添加联系人地址:> ");
	scanf("%s", pc->date[pc->sz].addr);
	printf("请输入要添加联系人电话:> ");
	scanf("%s", pc->date[pc->sz].tele);
	pc->sz++;
	printf("添加成功\n");
}

void ShowContact(const Contact* pc)
{
	assert(pc);
	printf("%-10s\t%-3s\t%-5s\t%-10s\t%-11s\n", "姓名", "年龄", "性别", "地址", "电话");
	int i = 0;
	for (i = 0; i < pc->sz; i++)
	{
		printf("%-10s\t%-3d\t%-5s\t%-10s\t%-11s\n", pc->date[i].name,
			pc->date[i].age,
			pc->date[i].sex,
			pc->date[i].addr,
			pc->date[i].tele);
	}
}
int FindContact(Contact* pc, char* arr)
{
	int i = 0;
	for (i = 0; i < pc->sz; i++)
	{

		int ret = strcmp(arr, pc->date[i].name);
		if (ret == 0)
			return i;//找到的话返回结构体的下标
	}
	return -1;

}

void DelContact(Contact* pc)
{
	assert(pc);
	if (pc->sz==0)
	{
		printf("通讯录中没有信息\n");
		return;
	}
	printf("输入要删除人的姓名:>");
	char arr[10] = "0";
	scanf("%s", arr);
	int ret = FindContact(pc,arr);
	if (ret== -1)
	{
		printf("该姓名不存在\n");
		return;
	}
	int i = 0;
	for (i = ret; i < pc->sz - 1; i++)
	{
		pc->date[i] = pc->date[i + 1];
	}
	pc->sz--;
	printf("删除成功\n");
}

void SearchContact(const Contact* pc)
{
	assert(pc);
	if (pc->sz == 0)
	{
		printf("通讯录中没有信息\n");
		return;
	}
	printf("输入要查找人的姓名:>");
	char arr[10] = "0";
	scanf("%s", arr);
	int ret = FindContact(pc, arr);
	if (ret == -1)
	{
		printf("该姓名不存在\n");
		return;
	}
	printf("%-10s\t%-3d\t%-5s\t%-10s\t%-11s\n", pc->date[ret].name,
		pc->date[ret].age,
		pc->date[ret].sex,
		pc->date[ret].addr,
		pc->date[ret].tele);
}

void ModifyContact(Contact* pc)
{
	assert(pc);
	if (pc->sz==0)
	{
		printf("通讯录中没有信息\n");
		return;
	}
	char arr[10] = "0";
	printf("请输入要修改人的名字:> ");
	scanf("%s", arr);
	int ret = FindContact(pc,arr);
	if (ret == -1)
	{
		printf("该联系人不存在\n");
		return;
	}
	printf("请输入要修改成的姓名:> ");
	scanf("%s", pc->date[ret].name);
	printf("请输入要修改成的年龄:> ");
	scanf("%d", &(pc->date[ret].age));
	printf("请输入要修改成的性别:> ");
	scanf("%s", pc->date[ret].sex);
	printf("请输入要修改成的地址:> ");
	scanf("%s", pc->date[ret].addr);
	printf("请输入要修改成的电话:> ");
	scanf("%s", pc->date[ret].tele);
	printf("修改成功\n");
	return;
}

int cmp(const void* e1, const void* e2)
{
	assert(e1 && e2);
	//return strcmp(((PeoInfo*)e1)->name, ((PeoInfo*)e2)->name);
	return ((PeoInfo*)e1)->age - ((PeoInfo*)e2)->age;
}

void SortContact(Contact* pc)
{
	assert(pc);
	qsort(pc->date, pc->sz, sizeof(pc->date[0]), cmp);
	//qsort第二个参数不是传数组能放多少元素,而是放了多少元素,因为如果没使用的位置也算进去,它会将它们这些没放的元素也参加排序
}

test.c

#define _CRT_SECURE_NO_WARNINGS 1

#include "contact.h"

void menu()
{
	printf("**** 1.add    2.del    ****\n");
	printf("**** 3.search 4.modify ****\n");
	printf("**** 5.show   6.sort   ****\n");
	printf("**** 0.exit            ****\n");
}

int main()
{
	//创建通讯录
	Contact con;
	//初始化通讯录
	InitContact(&con);
	int input = 0;
	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("退出");
			break;
		default:
			printf("输入错误,请重新输入");
		}
	} while (input);
	return 0;
}

五、总结

在这里插入图片描述

💘原创不易,还希望各位佬佬支持一下 \textcolor{colourful}{💘原创不易,还希望各位佬佬支持一下} 💘原创不易,还希望各位佬佬支持一下

💓点赞,你的认可是我创作的动力! \textcolor{red}{💓点赞,你的认可是我创作的动力!} 💓点赞,你的认可是我创作的动力!

💕收藏,你的青睐是我努力的方向! \textcolor{orange}{💕收藏,你的青睐是我努力的方向!} 💕收藏,你的青睐是我努力的方向!

💞评论,你的意见是我进步的财富! \textcolor{aqua}{💞评论,你的意见是我进步的财富!} 💞评论,你的意见是我进步的财富!

✨请点击下面进入主页关注大魔王
如果感觉对你有用的话,就点我进入主页关注我吧!

相关文章:

  • IDEA配置部署tomcat详细步骤(maven web 和Javaweb)
  • 软件测试面试准备——(一)Selenium(1)基础问题及自动化测试
  • 【Unity3D】Shader常量、变量、结构体、函数
  • Android 逆向工具大整理,碉堡了
  • 【java】springboot和springcloud区别
  • Linux(Linux各目录结构详解)
  • 二进制 k8s 集群下线 master 组件流程分析和实践
  • pandas——字符串处理【建议收藏】
  • 机器学习基础总结
  • 前端高频面试题—JavaScript篇(二)
  • MongoDB--》MongoDB数据库以及可视化工具的安装与使用—保姆级教程
  • IC封装常见形式
  • 制作自己的ChatGPT
  • 数据结构与算法这么难,为什么我们还要学习?
  • 1.2(完结)C语言进阶易忘点速记
  • 大数据之Hadoop
  • spark数据清洗练习
  • ChatGPT 这个风口,普通人怎么抓住:比如APP集成ChatGPT,公众号集成ChatGPT...
  • 谷粒商城-品牌管理-JSR303数据校验
  • Lesson 6.5 机器学习调参基础理论与网格搜索
  • 能上天入海的“鲲龙”毕业了,AG600取得型号合格证
  • 张宝亮履新临沂市委书记表态:不断提升在全省全国经济版图中的发展位势
  • “云南舞蹈大家跳”暨牟定“三月会”下周举行,城际公交免票
  • 两日内连续施压,特朗普再次喊话美联储降息
  • 安徽省合肥市人大常委会原副主任杜平太接受审查调查
  • 三一重工去年净利增逾三成至59.75亿,拟分红超30亿元