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

news/2024/11/20 23:19:48/

在这里插入图片描述

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

文章目录

  • 一、前言
  • 二、介绍
  • 三、分布实现通讯录
    • 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}{💞评论,你的意见是我进步的财富!}💞评论,你的意见是我进步的财富!

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


http://www.ppmy.cn/news/24761.html

相关文章

linux基本功系列之hostname实战

文章目录前言一. hostname命令介绍二. 语法格式及常用选项三. 参考案例3.1 显示本机的主机名3.2 临时修改主机名3.3 显示短格式的主机名3.4 显示主机的ip地址四. 永久修改主机名4.1 centos6 修改主机名的方式4.2 centos7中修改主机名永久生效总结前言 大家好&#xff0c;又见面…

电子招投标系统源码之 —采购数字化转型快人一步,以大数据支撑供应链管理未来

采购数字化转型快人一步&#xff0c;以大数据支撑供应链管理未来 招标采购为主的一站式全流程数字化采供协同。平台满足询比价、招标、竞价、拍卖、协议直采、商城采购等多种采购定价方式&#xff0c;采购过程全程留痕可追溯。平台支持企业通过WEB、APP、小程序等终端完成采购需…

在线预览PDF文件、图片,并且预览地址不显示文件或图片的真实路径。

实现在线预览PDF文件、图片&#xff0c;并且预览地址不显示文件或图片的真实路径。1、vue使用blob流在线预览PDF、图片&#xff08;包括jpg、png等格式&#xff09;。1、按钮的方法&#xff1a;2、方法详细&#xff1a;&#xff08;此方法可以在发起请求时携带token&#xff0c…

计算机视觉框架OpenMMLab开源学习(三):图像分类实战

前言&#xff1a;本篇主要偏向图像分类实战部分&#xff0c;使用MMclassification工具进行代码应用&#xff0c;最后对水果分类进行实战演示&#xff0c;本次环境和代码配置部分省略&#xff0c;具体内容建议参考前一篇文章&#xff1a;计算机视觉框架OpenMMLab开源学习&#x…

MongoDB--》文档查询的详细具体操作

目录 统计查询 分页列表查询 排序查询 正则的复杂条件查询 比较查询 包含查询 条件连接查询 统计查询 统计查询使用count()方法&#xff0c;其语法格式如下&#xff1a; db.collection.count(query,options) ParameterTypeDescriptionquerydocument查询选择条件optio…

MySQL 共享锁 (lock in share mode),排他锁 (for update)

共享锁 (lock in share mode) 简介 允许不同事务之间加共享锁读取&#xff0c;但不允许其它事务修改或者加入排他锁 如果有修改必须等待一个事务提交完成&#xff0c;才可以执行&#xff0c;容易出现死锁 共享锁事务之间的读取 session1: start transaction; select * from…

nvm控制node版本

目录 安装 nvm 1、下载 nvm 2、安装 3、验证安装 安装 node 1、查看 node 版本号 2、安装 node 3、查看已安装 nvm 常用命令 安装 nvm 1、下载 nvm 官网安装包&#xff1a; github 选择 nvm-setup.exe 下载 2、安装 1、选择 nvm 安装目录&#xff08;可自定义&#xff09;…

MongoDB--》基本常用命令使用

目录 数据库操作命令 选择和创建数据库 数据库的删除 集合操作命令 集合的显示创建 集合的隐式创建 集合的删除 文档基本的CRUD&#xff08;增删改查&#xff09; 文档的插入 文档的基本查询 文档的更新 删除文档 数据库操作命令 数据库常用的操作命令如下&#x…