C语言之通讯录(动态 存储文件版)
目录
前言
一.基本思路
二.代码的实现
2.1通讯录菜单
2.2通讯录的定义及功能
2.3函数实现
2.3.1初始化通讯录
2.3.2文件信息传递到通讯录里
2.3.3扩容通讯录
2.3.4增加联系人
2.3.5删除联系人
2.3.6查询联系人
2.3.7修改联系人
2.3.8打印通讯录
2.3.9信息保留在文件中
2.3.10销毁空间退出程序
三.完整代码
3.1Text.c文件
3.2Contact.h文件
3.3Contact.c文件
总结
前言
文件存储版的通讯录 是在通讯录的基础上添加了文件操作等
在了解通讯录(文件存储版)之前,我们得好好学习一下 文件操作
只有掌握了操作文件,才能明白文件存储版的通讯录
一.基本思路
1.通讯录是由多人的信息组合,信息:姓名,年龄,性别,地址等。
2.通讯录的大小,存放的人数,此使用动态存储,更加方便存储和利用空间。
3.通讯录的基本功能:增加联系人、删除联系人、查找联系人,修改联系人
4.保存通讯录文档,方便下次使用。
注:通讯录分三种:静态、动态、文件三种。而此文章讲述的是动态存储的文件版通讯录。
静态:大小固定,存储的人数有明确限制,无法改变,使用数组实现。
动态:存储人数可以调节,可以随着人数的增加而增加,选择一个初始大小,之后可进行扩充操作, 可更好的利用空间。
文件:该通讯录是在以上两种通讯录之一上加上存储文件的操作,在程序执行结束后都无法保存,录入的信息在程序结束时就会消失。为了保存录入的信息,可以通过文件操作来实现。
二.代码的实现
2.1通讯录菜单
菜单能够实现和用户的交互。需要选择增、删、查、改的功能。
所以,通讯录需要一个菜单。
代码如下:
void menu()
{printf("*********************************\n");printf("*******1.添加 2.删除*******\n");printf("*******3.查找 4.修改*******\n");printf("*******5.显示 6.保存*******\n");printf("*******0.退出 *******\n");printf("*********************************\n");
}
//使用函数指针数组
void (*(p[7]))(Contact*) = { Exit,AddContact,DeleteContact,SearchContact,ModifyContact,PrintContact,SaveContact };int main()
{ //Contact cl; 这是下面代码结构体的//InitContact(&cl);int input;do {menu();printf("请输入->");scanf("%d", &input);if (input <= 6)p[input](&cl); elseprintf("输入错误\n");}while (input != 0);
}
为了方便,我们使用了函数指针数组,void (*(p[7]))(Contact*)
2.2通讯录的定义及功能
通讯录需要姓名、性别、年龄及电话,此时我们需要使用结构体来定义。还需要定义函数:增、删、查、改、打印学生信息、保存通讯录。
代码如下:
#include<stdio.h>
#include<malloc.h>
#include<stdlib.h>
#include<string.h>
typedef struct PeoInfo
{char name[10];//姓名int age; //年龄char sex[3]; //性别int phone[12];//电话
}PeoInfo;typedef struct Contact
{ int size; //当前存储的人数int capacity; //通讯录容量大小contact* data; //结构体指针,访问个人信息}Contact;
//初始化通讯录
void InitContact(Contact* pc);
//增加联系人
void AddContact(Contact* pc);
//删除联系人
void DeleteContact(Contact* pc);
//查找联系人
void SearchContact(Contact* pc);
//修改联系人
void ModifyContact(Contact* pc);
//显示通讯录
void PrintContact(Contact* pc);
//扩容通讯录
void CheckCapacity(Contact* pc);
//保存信息到文件
void SaveContact(Contact* pc);
//文件信息传递到通讯录
void LoadContact(Contact* pc);
//销毁空间,退出程序
void Exit(Contact* pc);
2.3函数实现
注:当通讯录退出的时候,把信息写到文件。
当通讯录初始化后,加载文件的信息到通讯录中。
2.3.1初始化通讯录
通讯录是动态的,所以需要扩容,给一定空间。
void InitContact(Contact* pc)
{// 此时通讯录是空的,应先为通讯录分配空间pc->data = (PeoInfo*)malloc(sizeof(PeoInfo) * 4);// 如果分配成功,将通讯录的size设为0,capacity设为初识大小pc->size = 0;pc->capacity = 4;//将文档的信息传递到动态内存里,函数实现在下方LoadContact(pc);
}
2.3.2文件信息传递到通讯录里
将文件的信息加载到通讯录里
void LoadContact(Contact* pc)
{// 以读的形式打开文件FILE* pf = fopen("contact.txt", "rb");if (pf == NULL){perror("fopen");return;}// 将文件中的内容加载到通讯录中// 这里用fread函数,当fread函数读取的联系人信息数为0时,说明读取结束PeoInfo tmp = { 0 }; // 定义一个联系人信息的结构体,便于读取int i = 0;while (fread(&tmp, sizeof(PeoInfo), 1, pf)){CheckCapacity(pc); // 在这个函数中查看数组是否需要扩容,若需要,则扩容pc->data[i] = tmp;pc->size++;i++;}// 关闭文件fclose(pf);pf = NULL;return;
}
2.3.3扩容通讯录
添加联系人之前,需要判断通讯录是否满员,满员则需要扩容
void CheckCapacity(Contact* pc)
{// 判断通讯录是否已满,若满,进行扩容if (pc->size == pc->capacity){PeoInfo* tmp = (PeoInfo*)realloc(pc, sizeof(PeoInfo) * 4);if (tmp == NULL){printf("realloc fail\n");return;}pc->data = tmp;// 若扩容成功,增大capacitypc->capacity *= 2;}}
2.3.4增加联系人
需要添加联系人的各项信息。
void AddContact(Contact* pc)
{int num = 0;printf("添加人数:");scanf("%d", &num);// 输入要添加的联系人的信息// 这里pc->data为结构体数组,pc->data[pc->size]为其中的元素,也就是某一个联系人的信息for (int i = 0; i < num; i++){//判断通讯录是否满人CheckCapacity(pc);printf("请输入名字\n");scanf("%s", pc->data[pc->size].name);printf("请输入性别\n");scanf("%s", pc->data[pc->size].sex);printf("请输入年龄\n");scanf("%d", &pc->data[pc->size].age);printf("请输入电话\n");scanf("%s", pc->data[pc->size].phone);pc->size++; // 将存入的联系人的数量加1}
}
2.3.5删除联系人
需要找到该联系人的下标值,然后进行删除。
void DeleteContact(Contact* pc)
{int ret = 0;//记录寻找的下标值printf("请输入要删除的联系人的名字\n");char name[20];scanf("%s", name);// 定义一个新函数find,用来查找是否有这个联系人// 如果有,返回联系人的下标,如果没有,返回-1for (int i = 0; i < pc->size; i++){if (strcmp(pc->data[i].name, name) == 0){ret = i; break;}}if (ret){printf("不存在");}else {for (int i = ret; i < pc->size - 1; i++){pc->data[i] = pc->data[i + 1];}pc->size--;}}
2.3.6查询联系人
找到下标值,从而得到联系人的信息
void SearchContact(Contact* pc)
{int ret = 0;printf("请输入要查找的联系人的名字\n");char name[20];scanf("%s", name);// 利用已经定义的find函数进行查找for (int i = 0; i < pc->size; i++){if (strcmp(pc->data[i].name, name) == 0){ret = i; break;}}if (ret){printf("没有找到该联系人\n");}else{// 如果找到,打印该联系人的信息,首先打印五个标题printf("%-10s\t%-10s\t%-5s\t%-15s\n", "姓名", "性别", "年龄", "电话");printf("%-10s\t%-10s\t%-5d\t%-15s%\n",pc->data[ret].name,pc->data[ret].sex,pc->data[ret].age,pc->data[ret].phone);}}
2.3.7修改联系人
找到下标值,从而进行各项数据的修改
void ModifyContact(Contact* pc)
{int ret = 0;printf("请输入要查找的联系人的名字\n");char name[20];scanf("%s", name);for (int i = 0; i < pc->size; i++){if (strcmp(pc->data[i].name, name) == 0){ret = i; break;}}if (ret){printf("没有找到该联系人\n");}else{printf("请输入名字\n");scanf("%s", pc->data[ret].name);printf("请输入性别\n");scanf("%s", pc->data[ret].sex);printf("请输入年龄\n");scanf("%d", &pc->data[ret].age);printf("请输入电话\n");scanf("%s", pc->data[ret].phone);}}
2.3.8打印通讯录
打印每个人的具体数据
// 在这个函数内打印所有联系人的信息
void PrintContact(Contact* pc)
{// 首先打印五个标题printf("%-10s\t%-10s\t%-5s\t%-15s\n", "姓名", "性别", "年龄", "电话");// 然后用for循环打印所有联系人的信息for (int i = 0; i < pc->size; i++){printf("%-10s\t%-10s\t%-5d\t%-15s\n",pc->data[i].name,pc->data[i].sex,pc->data[i].age,pc->data[i].phone );}
}
2.3.9信息保留在文件中
程序退出时,要将销毁空间,并且把数据存入文件里,方便下次调用
void SaveContact(Contact* pc)
{FILE* p = fopen("contact.txt", "wb");if (p == NULL){perror("SaveContact");}else {int i = 0;for (i; i < pc->size; i++){fwrite(pc->data + i, sizeof(PeoInfo), 1, p);}fclose(p);p = NULL;printf("保存成功");}}
2.3.10销毁空间退出程序
void Exit(Contact* pc)
{//销毁空间free(pc->data);pc->data = NULL;pc->size = 0;pc->capacity = 0;
}
三.完整代码
和上面的代码比起来,连贯了Contact.c的各个函数实现。
3.1Text.c文件
#include"Contact.h"
void menu()
{printf("*********************************\n");printf("*******1.添加 2.删除*******\n");printf("*******3.查找 4.修改*******\n");printf("*******5.显示 6.保存*******\n");printf("*******0.退出 *******\n");printf("*********************************\n");
}
//使用函数指针数组
void (*(p[7]))(Contact*) = { Exit,AddContact,DeleteContact,SearchContact,ModifyContact,PrintContact,SaveContact };int main()
{//定义结构体Contact cl;InitContact(&cl);int input;do {menu();printf("请输入->");scanf("%d", &input);if (input <= 6)p[input](&cl);elseprintf("输入错误\n");} while (input != 0);
}
3.2Contact.h文件
#include<stdio.h>
#include<malloc.h>
#include<stdlib.h>
#include<string.h>
typedef struct PeoInfo
{char name[10];//姓名int age; //年龄char sex[3]; //性别int phone[12];//电话
}PeoInfo;typedef struct Contact
{int size; //当前存储的人数int capacity; //通讯录容量大小PeoInfo* data; //结构体指针,访问个人信息}Contact;
//初始化通讯录
void InitContact(Contact* pc);
//增加联系人
void AddContact(Contact* pc);
//删除联系人
void DeleteContact(Contact* pc);
//查找联系人
void SearchContact(Contact* pc);
//修改联系人
void ModifyContact(Contact* pc);
//显示通讯录
void PrintContact(Contact* pc);
//扩容通讯录
void CheckCapacity(Contact* pc);
//销毁并且保存通讯录
void SaveContact(Contact* pc);
void LoadContact(Contact* pc);
void Exit(Contact* pc);
3.3Contact.c文件
#include"Contact.h"void InitContact(Contact* pc)
{// 此时通讯录是空的,应先为通讯录分配空间pc->data = (PeoInfo*)malloc(sizeof(PeoInfo) * 4);// 如果分配成功,将通讯录的size设为0,capacity设为初识大小pc->size = 0;pc->capacity = 4;//将文档的信息传递到动态内存里,函数实现在下方LoadContact(pc);
}
void LoadContact(Contact* pc)
{// 以读的形式打开文件FILE* pf = fopen("contact.txt", "rb");if (pf == NULL){perror("fopen");return;}// 将文件中的内容加载到通讯录中// 这里用fread函数,当fread函数读取的联系人信息数为0时,说明读取结束PeoInfo tmp = { 0 }; // 定义一个联系人信息的结构体,便于读取int i = 0;while (fread(&tmp, sizeof(PeoInfo), 1, pf)){CheckCapacity(pc); // 在这个函数中查看数组是否需要扩容,若需要,则扩容pc->data[i] = tmp;pc->size++;i++;}// 关闭文件fclose(pf);pf = NULL;return;
}
void CheckCapacity(Contact* pc)
{// 判断通讯录是否已满,若满,进行扩容if (pc->size == pc->capacity){PeoInfo* tmp = (PeoInfo*)realloc(pc, sizeof(PeoInfo) * 4);if (tmp == NULL){printf("realloc fail\n");return;}pc->data = tmp;// 若扩容成功,增大capacitypc->capacity *= 2;}}
void AddContact(Contact* pc)
{int num = 0;printf("添加人数:");scanf("%d", &num);// 输入要添加的联系人的信息// 这里pc->data为结构体数组,pc->data[pc->size]为其中的元素,也就是某一个联系人的信息for (int i = 0; i < num; i++){//判断通讯录是否满人CheckCapacity(pc);printf("请输入名字\n");scanf("%s", pc->data[pc->size].name);printf("请输入性别\n");scanf("%s", pc->data[pc->size].sex);printf("请输入年龄\n");scanf("%d", &pc->data[pc->size].age);printf("请输入电话\n");scanf("%s", pc->data[pc->size].phone);pc->size++; // 将存入的联系人的数量加1}
}
void DeleteContact(Contact* pc)
{int ret = 0;//记录寻找的下标值printf("请输入要删除的联系人的名字\n");char name[20];scanf("%s", name);// 定义一个新函数find,用来查找是否有这个联系人// 如果有,返回联系人的下标,如果没有,返回-1for (int i = 0; i < pc->size; i++){if (strcmp(pc->data[i].name, name) == 0){ret = i; break;}}if (ret){printf("不存在");}else {for (int i = ret; i < pc->size - 1; i++){pc->data[i] = pc->data[i + 1];}pc->size--;}}
void SearchContact(Contact* pc)
{int ret = 0;printf("请输入要查找的联系人的名字\n");char name[20];scanf("%s", name);// 利用已经定义的find函数进行查找for (int i = 0; i < pc->size; i++){if (strcmp(pc->data[i].name, name) == 0){ret = i; break;}}if (ret){printf("没有找到该联系人\n");}else{// 如果找到,打印该联系人的信息,首先打印五个标题printf("%-10s\t%-10s\t%-5s\t%-15s\n", "姓名", "性别", "年龄", "电话");printf("%-10s\t%-10s\t%-5d\t%-15s%\n",pc->data[ret].name,pc->data[ret].sex,pc->data[ret].age,pc->data[ret].phone);}}
void ModifyContact(Contact* pc)
{int ret = 0;printf("请输入要查找的联系人的名字\n");char name[20];scanf("%s", name);// 利用已经定义的find函数进行查找for (int i = 0; i < pc->size; i++){if (strcmp(pc->data[i].name, name) == 0){ret = i; break;}}if (ret){printf("没有找到该联系人\n");}else{printf("请输入名字\n");scanf("%s", pc->data[ret].name);printf("请输入性别\n");scanf("%s", pc->data[ret].sex);printf("请输入年龄\n");scanf("%d", &pc->data[ret].age);printf("请输入电话\n");scanf("%s", pc->data[ret].phone);}}
// 在这个函数内打印所有联系人的信息
void PrintContact(Contact* pc)
{// 首先打印五个标题printf("%-10s\t%-10s\t%-5s\t%-15s\n", "姓名", "性别", "年龄", "电话");// 然后用for循环打印所有联系人的信息for (int i = 0; i < pc->size; i++){printf("%-10s\t%-10s\t%-5d\t%-15s\n",pc->data[i].name,pc->data[i].sex,pc->data[i].age,pc->data[i].phone );}
}
void SaveContact(Contact* pc)
{FILE* p = fopen("contact.txt", "wb");if (p == NULL){perror("SaveContact");}else {int i = 0;for (i; i < pc->size; i++){fwrite(pc->data + i, sizeof(PeoInfo), 1, p);}fclose(p);p = NULL;printf("保存成功");}}
void Exit(Contact* pc)
{//销毁空间free(pc->data);pc->data = NULL;pc->size = 0;pc->capacity = 0;
}
总结
在写动态存储文件版的通讯录,我们得学会动态存储和文件操作。
只有不断的掌握知识,我们才能敲代码得心应手,在不断的学习里,逐渐进步。
-------------小菜TQ02
相关文章:
C语言之通讯录(动态 存储文件版)
目录 前言 一.基本思路 二.代码的实现 2.1通讯录菜单 2.2通讯录的定义及功能 2.3函数实现 2.3.1初始化通讯录 2.3.2文件信息传递到通讯录里 2.3.3扩容通讯录 2.3.4增加联系人 2.3.5删除联系人 2.3.6查询联系人 2.3.7修改联系人 2.3.8打印通讯录 2.3.9信息保留在文…...
Linux 工具
文章目录一、软件包管理:yum1. 软件的生态环境2. yum 的使用3. yum 源及分类4. 在 centos 7.6 下更新 yum 源到国内镜像5. yum 命令二、编辑器:vim1. 命令模式2. 底行模式3. 插入模式4. 替换模式和视图模式5. vim 配置三、编译器:gcc/g1. C语…...
Java知识复习(七)常见的设计模式(装饰、代理、观察、策略、建造)
前言 参考书籍:《秒懂设计模式》 1、装饰器模式(Decorator) 1、装饰器模式:对原始对象动态地进行“包装”,是对类实例“装饰”的结果;类似于继承的效果,但这个过程是动态的,是可设…...
Linux系统看门狗应用编程
目录看门狗应用编程介绍打开设备获取设备支持哪些功能:WDIOC_GETSUPPORT获取/设置超时时间:WDIOC_GETTIMEOUT、WDIOC_SETTIMEOUT开启/关闭看门狗:WDIOC_SETOPTIONS喂狗:WDIOC_KEEPALIVE看门狗应用编程实战在产品化的嵌入式系统中&…...
Spring MVC 源码- LocaleResolver 组件
LocaleResolver 组件LocaleResolver 组件,本地化(国际化)解析器,提供国际化支持回顾先来回顾一下在 DispatcherServlet 中处理请求的过程中哪里使用到 LocaleResolver 组件,可以回到《一个请求的旅行过程》中的 Dispat…...
Servlet
Servlet1 简介2 快速入门3 执行流程4 生命周期5 方法介绍6 体系结构7 urlPattern配置8 XML配置1 简介 Servlet是JavaWeb最为核心的内容,它是Java提供的一门动态web资源开发技术。 使用Servlet就可以实现,根据不同的登录用户在页面上动态显示不同内容。 …...
简单的周总结
做一个简单的周总结。 校 OJ 上打了近 7 场比赛,ZR 及其他平台各一两场左右。 头几场打的中规中矩,分数大致在 100-200 左右,与同学分数差别不太大,但也没有很突出。 后面几场比较爆炸,分数一直在 100 以下࿰…...
Elasticsearch7.8.0版本进阶——IK中文分词器
目录一、ES 的默认分词器测试示例二、IK 中文分词器2.1、IK 中文分词器下载地址2.2、ES 引入IK 中文分词器2.3、IK 中文分词器测试示例三、ES 扩展词汇测试示例一、ES 的默认分词器测试示例 通过 Postman 发送 GET 请求查询分词效果,在消息体里,指定要分…...
一个阿里P6的说不会接口自动化测试,他不会是自己评的吧...
序 近期和一个阿里的测试工程师交流了一波,他竟然说我不会接口自动化测试,我当场就不服了我说你P6自己评级的吧,今天就带大家好好盘一盘接口自动化,本着以和大家交流如何实现高效的接口测试为出发点,本文包含了我在接…...
规则引擎与风控系统04:风控系统实例(下)
上一节把风控实例的基础代码都撸了出来。接下来再来把核心服务代码和规则文件写出来。 因为有了实体类、Dao,所以接来下就可以写服务类了。之前说过这个实例就是要实现两个目的: 1、一分钟内连续访问三次以上,就会被直接封杀; 2、黑名单用户登录会记录可疑事件。 所以服务类…...
我为什么选择Linux mint 21.1 “Vera“ ? Mint安装优化调教指南(分辨率DPI)
前言:为什么是Mint 笔者算是Linux老用户了,作为一个后端开发,尝试了多种不同发行版。 一开始是Manjaro这种Arch系,但是其对于开发而言实在是太过不稳定;每次滚动更新都要解决很多冲突。不适合当生产力(本…...
雅思经验(十四)
剑10 test3 阅读p3这篇阅读比较难做下来,主要是这个题材我们不太熟悉,介绍了一种成为拉皮塔人,他们在太平洋上航行,很多岛屿上都有他们足迹,后来人们发掘、探索他们的历史的故事。1.derelict 与 abandoned 主要是前面的…...
刚来的薪资20k,是我的2倍,我是真的卷不过,真的太变态了
在这个行业爬摸滚打5年了,从最开始点点点的功能测试到现在到现在成为高级测试,工资也翻了几倍,简单的说几句吧 改变的开始 之所以改变的原因很简单,我快被新来的卷死了,新来的本科是某211的,干劲十足&…...
五、DeepWalk、Node2Vec论文精读与代码实战【CS224W】(Datawhale组队学习)
开源内容:https://github.com/TommyZihao/zihao_course/tree/main/CS224W 子豪兄B 站视频:https://space.bilibili.com/1900783/channel/collectiondetail?sid915098 斯坦福官方课程主页:https://web.stanford.edu/class/cs224w 文章目录D…...
学习 Python 之 Pygame 开发魂斗罗(四)
学习 Python 之 Pygame 开发魂斗罗(四)继续编写魂斗罗1. 创建子弹类2. 根据玩家方向和状态设置子弹发射的位置(1). 站立向右发射子弹(2). 站立向左发射子弹(3). 站立朝上发射子弹(4). 蹲下发射子弹(5). 向斜方发射子弹(6). 奔跑时发射子弹(7). 跳跃时发射…...
Linux 基础知识:指令与shell
目录一、操作系统二、指令三、shell一、操作系统 什么是操作系统? 单纯的操作系统应该是指操作系统内核。内核的作用就是管理计算机的软硬件资源,让计算机在合适的时候干合适的事情。 但是有一个问题,并不是人人都会直接通过内核来操作计算机…...
【数通网络交换基础梳理1】二层交换机、以太网帧、MAC地址数据帧转发原理详解
一、网络模型 万年不变,先从模型结构分析,现在大家熟知的网络模型有两种。第一种是,OSI七层模型,第二种是TCP/IP模型。在实际运用中,参考更多的是TCP/IP模型。 OSI七层模型 TCP/IP模型 不需要全部理解,…...
《分布式技术原理与算法解析》学习笔记Day22
哈希与一致性哈希 在分布式系统中,哈希和一致性哈希是数据索引或者数据分布的常见实现方式。 数据分布设计原则 在分布式数据存储系统中,做存储方案选型时,一般会考虑以下因素: 数据均匀数据稳定节点异构性隔离故障域性能稳定…...
[MySQL]MySQL数据类型
文章目录数据类型分类数值类型tinyint类型bit类型float类型decimal类型字符串类型char类型varchar类型char和varchar对比日期和时间类型enum和set类型数据类型分类 MySQL中,支持各种各样的类型,比如表示数值的整型浮点型,文本、二进制类型、…...
利用steam搬砖信息差赚钱,单账号200+,小白也能轻松上手!
现在很多人在做互联网而且也赚到钱了,但还是有很多人赚不到钱,这是为什么? 这里我不得不说一个词叫做赛道,也就是选择,选择大于努力,项目本身大于一切,90%的人都觉得直播带货赚钱,但…...
RestClient
什么是RestClient RestClient 是 Elasticsearch 官方提供的 Java 低级 REST 客户端,它允许HTTP与Elasticsearch 集群通信,而无需处理 JSON 序列化/反序列化等底层细节。它是 Elasticsearch Java API 客户端的基础。 RestClient 主要特点 轻量级ÿ…...
web vue 项目 Docker化部署
Web 项目 Docker 化部署详细教程 目录 Web 项目 Docker 化部署概述Dockerfile 详解 构建阶段生产阶段 构建和运行 Docker 镜像 1. Web 项目 Docker 化部署概述 Docker 化部署的主要步骤分为以下几个阶段: 构建阶段(Build Stage):…...
C++初阶-list的底层
目录 1.std::list实现的所有代码 2.list的简单介绍 2.1实现list的类 2.2_list_iterator的实现 2.2.1_list_iterator实现的原因和好处 2.2.2_list_iterator实现 2.3_list_node的实现 2.3.1. 避免递归的模板依赖 2.3.2. 内存布局一致性 2.3.3. 类型安全的替代方案 2.3.…...
React Native 导航系统实战(React Navigation)
导航系统实战(React Navigation) React Navigation 是 React Native 应用中最常用的导航库之一,它提供了多种导航模式,如堆栈导航(Stack Navigator)、标签导航(Tab Navigator)和抽屉…...
VB.net复制Ntag213卡写入UID
本示例使用的发卡器:https://item.taobao.com/item.htm?ftt&id615391857885 一、读取旧Ntag卡的UID和数据 Private Sub Button15_Click(sender As Object, e As EventArgs) Handles Button15.Click轻松读卡技术支持:网站:Dim i, j As IntegerDim cardidhex, …...
智慧工地云平台源码,基于微服务架构+Java+Spring Cloud +UniApp +MySql
智慧工地管理云平台系统,智慧工地全套源码,java版智慧工地源码,支持PC端、大屏端、移动端。 智慧工地聚焦建筑行业的市场需求,提供“平台网络终端”的整体解决方案,提供劳务管理、视频管理、智能监测、绿色施工、安全管…...
Redis相关知识总结(缓存雪崩,缓存穿透,缓存击穿,Redis实现分布式锁,如何保持数据库和缓存一致)
文章目录 1.什么是Redis?2.为什么要使用redis作为mysql的缓存?3.什么是缓存雪崩、缓存穿透、缓存击穿?3.1缓存雪崩3.1.1 大量缓存同时过期3.1.2 Redis宕机 3.2 缓存击穿3.3 缓存穿透3.4 总结 4. 数据库和缓存如何保持一致性5. Redis实现分布式…...
关于nvm与node.js
1 安装nvm 安装过程中手动修改 nvm的安装路径, 以及修改 通过nvm安装node后正在使用的node的存放目录【这句话可能难以理解,但接着往下看你就了然了】 2 修改nvm中settings.txt文件配置 nvm安装成功后,通常在该文件中会出现以下配置&…...
在 Nginx Stream 层“改写”MQTT ngx_stream_mqtt_filter_module
1、为什么要修改 CONNECT 报文? 多租户隔离:自动为接入设备追加租户前缀,后端按 ClientID 拆分队列。零代码鉴权:将入站用户名替换为 OAuth Access-Token,后端 Broker 统一校验。灰度发布:根据 IP/地理位写…...
C++ Visual Studio 2017厂商给的源码没有.sln文件 易兆微芯片下载工具加开机动画下载。
1.先用Visual Studio 2017打开Yichip YC31xx loader.vcxproj,再用Visual Studio 2022打开。再保侟就有.sln文件了。 易兆微芯片下载工具加开机动画下载 ExtraDownloadFile1Info.\logo.bin|0|0|10D2000|0 MFC应用兼容CMD 在BOOL CYichipYC31xxloaderDlg::OnIni…...
