静态通讯录

在这里插入图片描述
今天我们分享一下静态通讯录详细解释和代码,之前分享过的只是通讯录的代码,但是我们没有进行讲解和解释,今天我们一边分享它的代码一边解释原因,让大家可以手撕通讯录。现在开始我们的学习吧。

首先我们应该要有三个文件,一个是来放我们的代码就是拿来测试的,我们叫他为test.c,一个就是我们来声明,比如一些函数或者结构体的声明,我们就应该放到这个里面,还有就是定义,我们函数是个怎么样的,怎么实现的我们也需要一个源文件来实现。

在这里插入图片描述
创建好这三个之后我们需要在我们的test.c里面写上我们的菜单,首先我们通讯录是不是一定要具备增删查改的功能,其实还有可以查找,或者排序的功能,那我们先简单的实现一下菜单。

在这里插入图片描述
我们简单的菜单就这样制成了,接下来我们需要做的就就是用switch函数来实现我们选啥就进入哪一个的操作,比如我们要进入add增加用户,那哦我们输入1就行了

Test.c

#include"Contact.h"
void menu()
{printf("**********************\n");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: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);return 0;
}

这样看其实我们的代码的可读性并不是很高,所以我们需要进行修改,大家可以看看我的上一篇文章,写的就是有一个枚举的例子,这里我们如果用的是枚举的话,看起来代码的可读性就高很多了,那我们改一下代码

#include"Contact.h"enum Option
{EXIT,ADD,DEL,SEARCH,MODIFY,SHOW,SORT
};
void menu()
{printf("**********************\n");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 ADD:break;case DEL:break;case SEARCH:break;case MODIFY:break;case SHOW:break;case SORT:break;case EXIT:printf("退出通讯录\n");break;default:printf("输入错误,请重新选择\n");break;}} while (input);return 0;
}

我们这样看的话是不是可读性就稍微高一点了。
完成上面的代码,我们来思考一下我们的通讯录需要存什么东西,我们是不是拿来存人的,所以我们需要这个人的名字,年龄,性别,电话号码,还有这个人的地址,那我们现在需要做的就是定义一个结构体,结构体我们需要的是把他放入到Contact.h中

在这里插入图片描述

typedef struct PeoInf
{char name[20];int age;char sex[5];char tel[12];char addr[20];
}PeoInf;

有了这个结构体我们还需要一个东西来统计它的个数,比如通讯录里面有几个人,这应该是一个局部变量,所以这里我们要做的就是在写一个结构体来实现

typedef struct PeoInf
{char name[20];int age;char sex[5];char tel[12];char addr[20];
}PeoInf;struct Contact
{PeoInf data[100];int sz;
};

上面的代码固然是好,但是我们还是存在一定的缺陷,缺陷是什么呢,我们结构体的数组好像是定死的,本来静态的通讯录就缺少一点动态,我们还把它定死,那比如我们像存101个人,这样不就是改改很麻烦,所以我们可以这样写

#define N 100
#define NMAE_MAX 20
#define SEX_MAX 5
#define TEL_MAX 12
#define ADDR_MAX 20typedef struct PeoInf
{char name[NMAE_MAX];int age;char sex[SEX_MAX];char tel[TEL_MAX];char addr[ADDR_MAX];
}PeoInf;typedef struct Contact
{PeoInf data[N];int sz;
}Contact;

这样就好很对,那我们现在来初始化一下我们的Conact吧

在这里插入图片描述
我们看到这里也是成功的将我们的数据初始化,那来看看我们的代码吧

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

代码也是很简短,但是我们这里必须得传我们的指针过来,否则就不行了,我们要做的是改变结构体中内容,所以就得传他们的地址过来才行,那我们继续来实现下一个吧,下一个我们实现一下ADD吧

void AddContact(Contact* ps)
{assert(ps);assert(ps->sz <= N);//断言如果通讯录满了就不能加了printf("请输入名字\n");scanf("%s", ps->data[ps->sz].name);printf("请输入年龄\n");scanf("%d", &ps->data[ps->sz].age);printf("请输入性别\n");scanf("%s", ps->data[ps->sz].sex);printf("请输入电话\n");scanf("%s", ps->data[ps->sz].tel);printf("请输入地址\n");scanf("%s", ps->data[ps->sz].addr);ps->sz++;printf("增加成功\n");
}

上面就是我们进行增加通讯录的代码,写完这个我们在加一个printf数据的代码也就是显示(show)

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

为了让我们的打印显示起来好看一点,我们这里加了对齐,看起来就比较整齐,小编的代码是右对齐,大家也可以进行左对齐的形式,上面的两个代码其实也没有什么要需要注意的,考察的就是对结构体的了解和怎么使用。我们下面来看我们后面的接口函数吧

下一个接口函数就是我们的删除,删除可不是随机删除人,比如我们先要找到这个人的名字,然后进行删除,在删除之前是不是还要看一下通讯录里面还有没有人,如果没有人的话,我们就不能进行删除了,所以这里我们进行强制断言一下

int FindByName(Contact* ps, char name[])
{assert(ps);int i = 0;for (i = 0; i < ps->sz; i++){if (strcmp(ps->data[i].name, name) == 0)return i;}return -1;
}
void DelContact(Contact* ps)
{assert(ps);assert(ps->sz > 0);char name[NMAE_MAX];printf("请输入要删除的人的名字>");scanf("%s", name);int ret = FindByName(ps, name);if (ret == -1){printf("通讯录没有这个人\n");return ;}int i = 0;for (i = ret; i < ps->sz - 1; i++){ps->data[i] = ps->data[i + 1];}ps->sz--;
}

上面的FIndByName是我们自己写的一个函数,只能在这个文件中使用,所以我们也可以用static修饰一下,就变成这样了

static int FindByName(Contact* ps, char name[])
{assert(ps);int i = 0;for (i = 0; i < ps->sz; i++){if (strcmp(ps->data[i].name, name) == 0)return i;}return -1;
}
void DelContact(Contact* ps)
{assert(ps);assert(ps->sz > 0);char name[NMAE_MAX];printf("请输入要删除的人的名字>");scanf("%s", name);int ret = FindByName(ps, name);if (ret == -1){printf("通讯录没有这个人\n");return ;}int i = 0;for (i = ret; i < ps->sz - 1; i++){ps->data[i] = ps->data[i + 1];}ps->sz--;
}

这里调试个人感觉特别麻烦,因为我们每次调试一个接口函数的时候,都要重新输入,这是为什么呢,因为我们的数据是存储在内存中的,程序运行结束的时候,我们的数据是无法进行保存的,只要存储在数据库或者文件中,数据才能进行保存,那现在我们来看一下下个接口函数的实现吧

下面一个接口函数就是查找了,查找很简单,我们就不过多解释,直接来看代码吧

void SearchContact(Contact* ps)
{assert(ps);char name[NMAE_MAX];printf("要查找人的名字>");scanf("%s", name);int ret = FindByName(ps, name);if (ret == -1){printf("找不到这个人");return;}printf("%-20s%-5d%-5s%-12s%-12s\n",ps->data[ret].name, ps->data[ret].age, ps->data[ret].sex, ps->data[ret].tel, ps->data[ret].addr);}

下面我们增删查改还有一个改的环节,改的话我们首先是不是要找到这个人,然后对它进行修改就行了。

void ModifyContact(Contact* ps)
{assert(ps);char name[NMAE_MAX];printf("要查找人的名字>");scanf("%s", name);int ret = FindByName(ps, name);if (ret == -1){printf("找不到这个人");return;}printf("请输入名字\n");scanf("%s", ps->data[ret].name);printf("请输入年龄\n");scanf("%d", &ps->data[ret].age);printf("请输入性别\n");scanf("%s", ps->data[ret].sex);printf("请输入电话\n");scanf("%s", ps->data[ret].tel);printf("请输入地址\n");scanf("%s", ps->data[ret].addr);printf("修改成功\n");}

最后还剩下一个排序,这里我们就假设是按年龄来进行排序的吧,排序大家还记不记得我们有一个库函数,之前我们用冒泡函数来模拟实现,并且我们也掌握它的用法,那这里我们就直接用库函数qsort来实现吧

int CmpByAge(const void* p1, const void* p2)
{return *(int*)p1 - *(int*)p2;
}
void SortContact(Contact* ps)
{assert(ps);qsort(ps->data, N, sizeof(ps->data[0]), CmpByAge);
}

这样就可以了

那来看一下我们的完整代码吧

Contact.h

#pragma once#include<stdio.h>
#include<assert.h>
#include<stdlib.h>
#include<string.h>#define N 100
#define NMAE_MAX 20
#define SEX_MAX 5
#define TEL_MAX 12
#define ADDR_MAX 20typedef struct PeoInf
{char name[NMAE_MAX];int age;char sex[SEX_MAX];char tel[TEL_MAX];char addr[ADDR_MAX];
}PeoInf;typedef struct Contact
{PeoInf data[N];int sz;
}Contact;//初始化
void InitContact(Contact* pc);void AddContact(Contact* ps);void ShowContact(Contact* ps);void DelContact(Contact* ps);void SearchContact(Contact* ps);void ModifyContact(Contact* ps);void SortContact(Contact* ps);

Contact.c

#define _CRT_SECURE_NO_WARNINGS 1#include"Contact.h"void InitContact(Contact* pc)
{assert(pc);memset(pc->data, 0, sizeof(pc->data));pc->sz = 0; }void AddContact(Contact* ps)
{assert(ps);assert(ps->sz <= N);//断言如果通讯录满了就不能加了printf("请输入名字\n");scanf("%s", ps->data[ps->sz].name);printf("请输入年龄\n");scanf("%d", &ps->data[ps->sz].age);printf("请输入性别\n");scanf("%s", ps->data[ps->sz].sex);printf("请输入电话\n");scanf("%s", ps->data[ps->sz].tel);printf("请输入地址\n");scanf("%s", ps->data[ps->sz].addr);ps->sz++;printf("增加成功\n");
}void ShowContact(Contact* ps)
{assert(ps);int i = 0;printf("%-20s%-5s%-5s%-12s%-12s\n", "姓名", "年龄", "性别", "电话", "地址");for (i = 0; i < ps->sz; i++){printf("%-20s%-5d%-5s%-12s%-12s\n",ps->data[i].name, ps->data[i].age, ps->data[i].sex, ps->data[i].tel, ps->data[i].addr);}
}
int FindByName(Contact* ps, char name[])
{assert(ps);int i = 0;for (i = 0; i < ps->sz; i++){if (strcmp(ps->data[i].name, name) == 0)return i;}return -1;
}
void DelContact(Contact* ps)
{assert(ps);assert(ps->sz > 0);char name[NMAE_MAX];printf("请输入要删除的人的名字>");scanf("%s", name);int ret = FindByName(ps, name);if (ret == -1){printf("通讯录没有这个人\n");return;}int i = 0;for (i = ret; i < ps->sz - 1; i++){ps->data[i] = ps->data[i + 1];}ps->sz--;
}void SearchContact(Contact* ps)
{assert(ps);char name[NMAE_MAX];printf("要查找人的名字>");scanf("%s", name);int ret = FindByName(ps, name);if (ret == -1){printf("找不到这个人");return;}printf("%-20s%-5d%-5s%-12s%-12s\n",ps->data[ret].name, ps->data[ret].age, ps->data[ret].sex, ps->data[ret].tel, ps->data[ret].addr);}void ModifyContact(Contact* ps)
{assert(ps);char name[NMAE_MAX];printf("要查找人的名字>");scanf("%s", name);int ret = FindByName(ps, name);if (ret == -1){printf("找不到这个人");return;}printf("请输入名字\n");scanf("%s", ps->data[ret].name);printf("请输入年龄\n");scanf("%d", &ps->data[ret].age);printf("请输入性别\n");scanf("%s", ps->data[ret].sex);printf("请输入电话\n");scanf("%s", ps->data[ret].tel);printf("请输入地址\n");scanf("%s", ps->data[ret].addr);printf("修改成功\n");}int CmpByAge(const void* p1, const void* p2)
{return *(int*)p1 - *(int*)p2;
}
void SortContact(Contact* ps)
{assert(ps);qsort(ps->data, N, sizeof(ps->data[0]), CmpByAge);
}

接下来就是我们的测试代码

test.c

#define _CRT_SECURE_NO_WARNINGS 1#include"Contact.h"enum Option
{EXIT,ADD,DEL,SEARCH,MODIFY,SHOW,SORT
};
void menu()
{printf("********************************\n");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;Contact p;InitContact(&p);do{menu();printf("请输入你要进行的操作>");scanf("%d", &input);switch (input){case ADD:AddContact(&p);break;case DEL:DelContact(&p);break;case SEARCH:SearchContact(&p);break;case MODIFY:ModifyContact(&p);break;case SHOW:ShowContact(&p);break;case SORT:SortContact(&p);break;case EXIT:printf("退出通讯录\n");break;default:printf("输入错误,请重新选择\n");break;}} while (input);return 0;
}

这就是我们今天的分享,我们第一次是只分享了代码,这次我们就把整个过程以讲解的方式讲解出来,谢谢大家,我们下次再见

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/89524.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

MYSQL8解压版 windows 主从部署步骤及配置(包含配置文件,教程文件,免积分下载)

MYSQL8解压版 windows 主从部署步骤及配置 一.安装MSYQL 这里只讲大概,详细步骤、my.ini文件、安装包等会在页尾文件中(正常情况按首个mysql安装,只是名字有区别) 1.主库my.ini配置 [mysqld] #典型的值是5-6GB(8GB内存)&#xff0c;8-11GB(16GB内存), 20-25GB(32GB内存)&…

Ctfshow web入门 XSS篇 web316-web333 详细题解 全

CTFshow XSS web316 是反射型 XSS 法一&#xff1a; 利用现成平台 法二&#xff1a; 自己搭服务器 先在服务器上面放一个接受Cookie的文件。 文件内容&#xff1a; <?php$cookie $_GET[cookie];$time date(Y-m-d h:i:s, time());$log fopen("cookie.txt"…

路由器配置静态和默认路由实现VLAN之间的通信

目录 华为路由器静态路由和默认路由的写法 静态路由和默认路由的区别 案例 华为路由器静态路由和默认路由的写法 配置静态路由&#xff1a; [Huawei] ip route-static <目标网络> <子网掩码> <下一跳地址> 实例&#xff1a;将目标网络192.168.10.0/24的流…

一站式吃鸡利器,提升游戏战斗力,助您稳坐鸡王宝座!

各位吃鸡玩家们&#xff0c;听说过绝地求生作图工具吗&#xff1f;想知道如何提高游戏战斗力、分享顶级作战干货、查询装备皮肤库存&#xff1f;还在为游戏账号安全而担心吗&#xff1f;别急&#xff0c;今天就为您介绍一款一站式吃鸡利器&#xff0c;满足您的所有需求&#xf…

如何快速搭建一个react项目?如何使用react脚手架快速搭建项目?

如何使用react脚手架快速搭建项目&#xff1f; 一、前提 电脑已经安装了node和npm环境。 react文档中要求Node > 8.10 和 npm > 5.6&#xff0c;查看版本&#xff1a;node -v&#xff1b;npm -v&#xff1b; 二、步骤 1、在合适的文件夹中打开命令行窗口cmd 2、全局安…

SkyWalking搭配springboot应用(三)

title: “SkyWalking搭配springboot应用(三)” createTime: 2021-07-13T16:27:5708:00 updateTime: 2021-07-13T16:27:5708:00 slug: “SkyWalking搭配springboot应用(三)” draft: false author: “ggball” tags: [“skywalking”] categories: [“java”] description: “sk…

[论文笔记]Prefix Tuning

引言 今天带来微调LLM的第二篇论文笔记Prefix-Tuning。 作者提出了用于自然语言生成任务的prefix-tuning(前缀微调)的方法,固定语言模型的参数而优化一些连续的任务相关的向量,称为prefix。受到了语言模型提示词的启发,允许后续的token序列注意到这些prefix,当成虚拟toke…

美篇作文网教学资源源码-自带作文数据

非常漂亮的UI设计和页面排版&#xff01; 自适应手机pc端 页面内容均支持自定义 可以用来做网站矩阵&#xff0c;或者增强你其他网站板块&#xff0c;或者单独运营都可以。 可以通过广告方式变现&#xff0c;或者引流等等 友好的seo&#xff0c;更容易被浏览器收录 关注青狐…

Android导航抽屉

本文所有代码均位于https://github.com/MADMAX110/CatChat 之前使用过标签页布局可以让用户在应用中轻松地导航。 当只有为数不多地几个类别屏幕&#xff0c;而且它们都在应用层次结构地同一级上&#xff0c;标签页布局就很适用。 而抽屉导航可以实现更多选择&#xff0c;这是一…

MySQL基础-多表查询

目录 简单概述 1.多表之间的关系 1.1 一对多/多对一 1.2 多对多 1.3 一对一 2. 多表查询-内连接 2.1 隐式内连接 2.2 显式内连接 2.3 内连接小结 3.多表查询-外连接 3.1 左外连接 3.2 右外连接 4.多表查询-自连接 4.1 应用 5.多表查询-联合查询 6.子查询 6.1 标量子…

leetcode 10. 正则表达式匹配

2023.9.20 感觉是目前做过dp题里最难的一题了... 本题首要的就是需要理解题意&#xff0c;翻了评论区我才发现之前一直理解的题意是错的。 我原来理解的 “ *匹配0次” 是指&#xff1a;*直接消失&#xff0c;不会影响到前面的字符。 但是*和前一个字符其实是连体的&#xff0…

现代 GPU 容易受到新 GPU.zip 侧通道攻击

来自四所美国大学的研究人员开发了一种新的 GPU 侧通道攻击&#xff0c;该攻击利用数据压缩在访问网页时泄露现代显卡中的敏感视觉数据。 研究人员通过 Chrome 浏览器执行跨源 SVG 过滤器像素窃取攻击&#xff0c;证明了这种“ GPU.zip ”攻击的有效性。 研究人员于 2023 年 …

mysql面试题2:说一说MySQL的架构设计?一条 MySQL 语句执行的步骤?

该文章专注于面试,面试只要回答关键点即可,不需要对框架有非常深入的回答,如果你想应付面试,是足够了,抓住关键点 面试官:说一说MySQL的架构设计? MySQL的架构设计主要包括以下几个组件: 连接器(Connector):负责与客户端建立连接,并进行身份验证和授权。 查询缓存…

黑马JVM总结(二十五)

&#xff08;1&#xff09;字节码指令-cinit 构造方法可以分为两类&#xff0c;一类是cinit 一类init cinit是整个类的构造方法 putstatic&#xff1a;进行static变量的赋值&#xff0c;是到常量池里找到名字一个叫做i的变量 &#xff08;2&#xff09;字节码指令-init in…

自适应阈值分割-OTSU

OTSU 在前面固定阈值中选取了一个阈值为127进行阈值分割&#xff0c;那如何知道选的这个阈值效果好不好呢&#xff1f;答案是&#xff1a;不断尝试&#xff0c;所以这种方法在很多文献中都被称为经验阈值。 Otsu阈值法就提供了一种自动高效的二值化方法。Otsu算法也称最大类间…

python+vue电子资源管理系统

能实现不出家门就可以通过网络进行系统管理&#xff0c;交易等&#xff0c;而且过程简单、快捷。同样的&#xff0c;在人们的工作生活中&#xff0c;也就需要互联网技术来方便人们的日常工作生活&#xff0c;实现工作办公的自动化处理&#xff0c;实现信息化&#xff0c;无纸化…

社区团购新零售搭伙拼团小程序源码(前后端)

社区团购新零售搭伙拼团小程序源码是一款非常实用的电商小程序&#xff0c;它包含了前后端文件&#xff0c; 可以快速地进行部署和使用。该小程序是基于微信小程序开发的&#xff0c;支持社区团购、新零售、搭伙拼团等多种功能。 该小程序具有良好的用户体验&#xff0c;包括…

数据湖在爱奇艺数据中台的应用

01 我们眼中的数据湖 作为爱奇艺的数据中台团队&#xff0c;我们的核心任务是管理和服务公司内的大量数据资产。在实施数据治理的过程中&#xff0c;我们不断吸收新的理念&#xff0c;引入尖端的工具&#xff0c;以精细化我们的数据体系管理。“数据湖”作为近年来数据领域广泛…

链表入门(单链表讲)

链表 1.链表1.1 链表概念及其结构1.2 链表的分类 2.单链表代码实现2.1 单链表的定义2.2 单链表的初始化2.3 单链表的新增结点2.4 单链表的打印2.4 单链表的插入2.4.1 头插2.4.2 尾插2.4.3 任意位置插入 2.5 单链表的删除2.5.1 头删2.5.2 尾删2.5.3 任意位置删除 2.6 单链表的查…

【PickerView案例10-国旗选择界面02 Objective-C预言】

一、好了,我们继续来实现这个国旗选择界面: 1.它的界面里面,是不是很简单,就一个UIPickerView,就完事儿了 然后,显示的每一行内容呢, 1)一个文字Label 2)一个图片 那大家应该有意识,它返回的应该是一个View,对吧, 代理方法里面,有一个返回View的,viewForRow…