HJ212协议C#代码解析实现

HJ212协议C#代码解析实现

HJ212协议是环保中一个非常重要的标准协议(字符串协议),之前写了两篇C++ HJ212协议解析的相关博文:

  • 环保 HJ212协议解析
  • 基于Qt5.14.2的HJ212 TCP服务端接收解析入库程序
    最近在学习C#,所以打算基于C#重新实现一遍,算是熟悉一下C#的基本语法。

HJ212协议简介

由于是做环保相关的,有时需要对212协议进行拆包和解包。HJ212协议是一种字符串协议,数据传输通讯包主要由包头、数据段长度、数据段、CRC校验、包尾组成,其中“数据段”内容包括请求编码、系统编码、命令编码、密码、设备唯一标识、总包数、包号、指令参数。请求编码为请求的时间戳,系统编码ST统一规定为22,命令编码CN为该数据包的时间类型,访问密码、设备唯一标识在对接时由平台提供,指令参数为数据内容。通讯协议的数据结构如图4所示。
通讯协议的数据结构
图4 通讯协议的数据结构

6.1.1通讯包结构组成

名称类型长度描述
包头字符2固定为##
数据段长度十进制整数4数据段的ASCII字符数。例如数据段的字符数为128,则写为“0128”
数据段字符0<=n<=9999变长的数据
CRC校验十六进制4数据段的校验结果,例如C901,如果CRC错,即执行超时
包尾字符2回车换行(\r\n)

《污染物在线监控(监测)系统数据传输标准》简称《HJ212-2017》标准PDF文档可以从中华人民共和国生态环境部的官网下载,具体地址为:HJ212-2017》标准PDF文档
如下图所示:
HJ212-2017标准下载
目前HJ212标准协议已经发布了两个版本,一个是HJ/T 212-2005,另一个是 HJ 212-2017,最新的HJ 212-2017下载地址为:污染物在线监控(监测)系统数据传输标准(HJ 212-2017代替HJ/T 212-2005)

## 基于C#的HJ212解析类

首先创建一个基于C# .Net的库项目,名称为:HJ212ParseLibrary,相关类实现代码如下:

(1)、通用工具类 CommonUtils

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;namespace HJ212ParseLibrary
{/// <summary>/// 通用工具类/// </summary>public class CommonUtils{/// <summary>/// 切分数据/// </summary>/// <param name="cp"></param>/// <returns></returns>public static List<Dictionary<string, string>>  SplitKV(string cp){List<Dictionary<string, string>> resultList = new List<Dictionary<string, string>>();var arr1 = cp.Split(';');foreach (var i in arr1){Dictionary<string, string> item = new Dictionary<string, string>();var arr2 = i.Split(',');foreach(var j in arr2){var arrKv = j.Split('=');if (arrKv.Length == 2){item.Add(arrKv[0], arrKv[1]);   }}resultList.Add(item);}return resultList;}/// <summary>/// 组合数据/// </summary>/// <param name=""></param>/// <returns></returns>public static string JoinKV(List<Dictionary<string, string>> myList){List<string> item = new List<string>();foreach (var i in myList){List<string> arrKv = new List<string>();foreach (var j in i){arrKv.Add(j.Key + "=" + j.Value);}item.Add(Join(arrKv, ','));}return Join(item, ';');}/// <summary>/// 数据组合字符串/// </summary>/// <param name="arrKv">字符串列表</param>/// <param name="sep">分隔符</param>/// <returns></returns>/// <exception cref="NotImplementedException"></exception>private static string Join(List<string> arrKv, char sep = ' '){string result = "";bool isFirst = true;foreach (var item in arrKv){if (isFirst){result = item;isFirst = false;continue;}result += sep + item;}return result;}/// <summary>/// 将字符串数组按照sep分隔符分割之后,生成新的字符串/// </summary>/// <param name="arrKv">字符串数组</param>/// <param name="sep">分隔符</param>/// <returns></returns>private static string Join(string[] arrKv, char sep = ' '){string result = "";bool isFirst = true;foreach (var item in arrKv){if (isFirst){result = item;isFirst = false;continue;}result += sep + item;}return result;}/// <summary>/// 计算计算字节数组的CRC-16校验码/// </summary>/// <param name="byteArr">字节数组</param>/// <returns>CRC-16校验码</returns>public static uint GetCrc16(byte[] byteArr){uint crc_reg, check;int i, j;crc_reg = 0xFFFF;for (i = 0; i < byteArr.Length; i++){crc_reg = (crc_reg >> 8) ^ byteArr[i];for (j = 0; j < 8; j++){check = crc_reg & 0x0001;crc_reg >>= 1;if (check == 0x0001){crc_reg ^= 0xA001;}}}return crc_reg;}/// <summary>/// 将对应位置置1,n从1开始/// </summary>/// <param name="x"></param>/// <param name="n"></param>public static void SetBit(int x, int n){x |= 1 << (n - 1);}/// <summary>/// 将对应位置置0,n从1开始/// </summary>/// <param name="x"></param>/// <param name="n"></param>public static void CtrlBit(int x, int n){x &= ~(1 << (n - 1));}public static int GetBit(int x, int n){return x & (1 << (n - 1));}}
}

(2)、HJ212协议 CP数据部分 HJ212DataCP

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;namespace HJ212ParseLibrary
{/// <summary>/// HJ212协议 CP数据部分/// </summary>public class HJ212DataCP{public HJ212DataCP(){}public HJ212DataCP(string s){List<Dictionary<string, string>> arr = CommonUtils.SplitKV(s);foreach (var i in arr){int kvlen = i.Count;string key = "";foreach (var j in i){// 对指定监测因子的项,统一使用因子代表if (j.Key == "PolId"){key = j.Value;this.KVDict[key] = new Dictionary<string, string>();continue;}string name, field;// 查询是否包含标准协议中的设备状态var f1 = j.Key.IndexOf("SB");var f2 = j.Key.IndexOf("-");if (f2 != -1 && f1 != 0){// a20004-Rtd   name-fieldname = j.Key.Substring(0, f2);field = j.Key.Substring(f2 + 1);// i11001-Info   fieldif (field == "Info"){field = name;}else{key = name;}}else{if (j.Key == "DataTime"){this.DataTime = j.Value;}name = j.Key;key = name;field = "value";}if (this.KVDict.ContainsKey(key)){// 如果存在key,则追加this.KVDict[key].Add(field, j.Value);} else{// 如果不存在该key,则创建一个字典对象,并添加到KVDict中Dictionary<string, string> dict = new Dictionary<string, string>();dict.Add(field, j.Value);this.KVDict.Add(key, dict);}}}}public void Clear(){this.KVDict.Clear();}public Dictionary<string, Dictionary<string, string>> KVDict = new Dictionary<string, Dictionary<string, string>>();   // 监测因子数据字典string DataTime;}
}

(3)、HJ212协议 数据区 HJ212Data

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;namespace HJ212ParseLibrary
{/// <summary>/// HJ212协议 数据区/// 请求编码QN + 系统编码ST + 命令编码CN + 密码PW + 设备唯一标识MN + 标志位Flag + 总包数PNUM + 包号PNO + 指令参数CP/// 其中,指令CP字符数范围为:[0,9899],CP=&&数据区&&/// </summary>public class HJ212Data{public string QN;		// 请求编码 20字符	QN=YYYYMMDDHHmmssZZZpublic string ST;		// 系统编码 5字符		ST=21public string CN;		// 命令编码 7字符		CN=2011public string PW;		// 访问密码 9字符		PW=123456public string MN;		// 设备标识 27字符	MN=[0-9A-F]public string Flag;	    // 标志位   8整数		Flag=7	bit:000001(协议版本)0(是否有包号)0(是否需应答)public string PNUM;	    // 总包数   9字符		PNUM=0000	[不分包则没有本字段]public string PNO;		// 包号     8字符	PNO=0000	[不分包则没有本字段]public string CP;		// 指令参数	<=9899字符	CP=&&数据区&&public HJ212DataCP CPs;private bool bValid = false;// 设置Flag,bit从1开始public void SetFlag(int bit, bool enable){int flag = 4;flag = Int32.Parse(Flag);if (enable){CommonUtils.SetBit(flag, bit);} else{CommonUtils.CtrlBit(flag, bit);}this.Flag = flag.ToString();}// 获取Flag,bit从1开始public int GetFlag(int bit){int flag = 4;if (Int32.TryParse(Flag, out flag)){return CommonUtils.GetBit(flag, bit);}return CommonUtils.GetBit(flag, bit);}// 有效性public bool IsValid(){return bValid;}// 长度public int Size(){return QN.Length + ST.Length + CN.Length + PW.Length + MN.Length +Flag.Length + PNUM.Length + PNO.Length + CP.Length;}// 构造函数public HJ212Data(){}public HJ212Data(string s){CopyStr(s);}public void CopyStr(string s){// 查找数据段int d1 = s.IndexOf("CP=&&");        // 数据段开始位置int d2 = s.IndexOf("&&", d1 + 5);   // 数据段结束位置String tmpStr = "";if (d1 != -1 && d2 != -1){CP = s.Substring(d1 + 5, d2 - d1 - 5);CPs = new HJ212DataCP(CP);tmpStr = s.Substring(0, d1) + s.Substring(d2 + 2);}else{tmpStr = s;}Dictionary<string, string> strDict = new Dictionary<string, string>();var arr1 = tmpStr.Split(';');foreach (var i in arr1){var arr2 = i.Split('=');if (arr2.Length == 2){strDict.Add(arr2[0], arr2[1]);}}if (strDict.ContainsKey("QN")){QN = strDict["QN"];}if (strDict.ContainsKey("ST")){ST = strDict["ST"];}if (strDict.ContainsKey("CN")){CN = strDict["CN"];}if (strDict.ContainsKey("PW")){PW = strDict["PW"];}if (strDict.ContainsKey("MN")){MN = strDict["MN"];}if (strDict.ContainsKey("Flag")){Flag = strDict["Flag"];}if (strDict.ContainsKey("PNUM")){PNUM = strDict["PNUM"];}if (strDict.ContainsKey("PNO")){PNO = strDict["PNO"];}bValid = true;}// 获取数据项public List<Dictionary<string, string>> Cp2Object(){return CommonUtils.SplitKV(CP);}// 字符串输出public override string ToString(){string str = "";if (!string.IsNullOrEmpty(QN)){str += ("QN=" + QN + ";");}if (!string.IsNullOrEmpty(ST)){str += ("ST=" + ST + ";");}if (!string.IsNullOrEmpty(CN)){str += ("CN=" + CN + ";");}if (!string.IsNullOrEmpty(PW)){str += ("PW=" + PW + ";");}if (!string.IsNullOrEmpty(MN)){str += ("MN=" + MN + ";");}if (!string.IsNullOrEmpty(Flag)){str += ("Flag=" + Flag + ";");}if (!string.IsNullOrEmpty(PNUM)){str += ("PNUM=" + PNUM + ";");}if (!string.IsNullOrEmpty(PNO)){str += ("PNO=" + PNO + ";");}str += ("CP=&&" + CP + "&&");return str;}}
}

(4)、HJ212协议实体类 HJ212

using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Runtime.InteropServices.ComTypes;
using System.Text;
using System.Threading.Tasks;namespace HJ212ParseLibrary
{/// <summary>/// HJ212协议 整包=包头+数据段长度+数据段+CRC校验+包尾组成/// ##0637ST=22;CN=2011;PW=123456;MN=LB4200001;CP=&&DataTime=20210107143500;a05002-Rtd=0,a05002-Flag=N;a21005-Rtd=0.825,a21005-Flag=N;a34006-Rtd=874,a34006-Flag=N;a24088-Rtd=0,a24088-Flag=N;a21003-Rtd=5.656,a21003-Flag=N;a21004-Rtd=9.253,a21004-Flag=N;a21002-Rtd=17.894,a21002-Flag=N;a05024-Rtd=5.803,a05024-Flag=N;a34007-Rtd=2679,a34007-Flag=N;a34002-Rtd=123.97,a34002-Flag=N;a34004-Rtd=24.82,a34004-Flag=N;a01006-Rtd=1032.3,a01006-Flag=N;a01002-Rtd=20.9,a01002-Flag=N;a21026-Rtd=0.795,a21026-Flag=N;a01007-Rtd=3.3,a01007-Flag=N;a34049-Rtd=3553,a34049-Flag=N;a01001-Rtd=-0.6,a01001-Flag=N;a99999-Rtd=0,a99999-Flag=N;a01008-Rtd=349,a01008-Flag=N&&3300/// </summary>public class HJ212{public string header = "##";        // 包头 2字符public string dataLen = "0000";     // 数据段长度    4整数,如长度128,写为"0128"HJ212Data data;                     // 数据段  0<=n<=9999public string crc = "0000";         // CRC校验码  4hexpublic string tailer = "\r\n";      // 包尾 2字符public string full;                 // 全数据,整包/// 输出public override string ToString(){string dataStr = data.ToString();uint crc16 = CommonUtils.GetCrc16(Encoding.UTF8.GetBytes(dataStr));return string.Format("{0}{1:D4}{2}{3:X4}{4}", header, dataStr.Length, dataStr, crc16, tailer);  // D4标示4位10进制数字,X4表示4位16进制数}// 有效性public bool IsValid(){return bValid;}// 有效性public bool IsDataValid(){return this.data.CN == "2011" || this.data.CN == "2051" || this.data.CN == "2061"|| this.data.CN == "2031" || this.data.CN == "2041" || this.data.CN == "3020";}// 长度public int Size(){return header.Length + dataLen.Length + data.Size() + crc.Length + tailer.Length;}// 清空数据区public void ClearCp(){this.data.CP = "";this.data.CPs.Clear();}// 设置是否需要应答public void SetNeedReply(bool need){data.SetFlag(1, need);}// 设置是否有包号public void SetNeedSubPack(bool need){data.SetFlag(2, need);if (!need){data.PNUM = "";data.PNO = "";}}// 是否需应答public int IsNeedReply(){return data.GetFlag(1);}// 是否有包号public int IsNeedSubPack(){return data.GetFlag(2);}// 数据区。字段与其值用‘=’连接;// 在数据区中,同一项目的不同分类值间用‘,’来分隔,不同项目之间 用‘;’来分隔。public void Combine(){this.dataLen = string.Format("{0:D4", this.data.Size());string dataStr = this.data.ToString();uint jisuanCrc = CommonUtils.GetCrc16(Encoding.UTF8.GetBytes(dataStr));this.crc = string.Format("{0:D4", jisuanCrc);this.bValid = true;}public HJ212(string str){this.full = str;int totalSize = str.Length;dataLen = str.Substring(header.Length, dataLen.Length);int dLen = Int32.Parse(dataLen);if ((10 + dLen) > totalSize) {return;}string dataStr = str.Substring(header.Length + dataLen.Length, dLen);data = new HJ212Data(dataStr);crc = str.Substring(header.Length + dataLen.Length + dLen, crc.Length);//uint jisuanCrc16 = CommonUtils.GetCrc16(dataStr.ToCharArray());uint jisuanCrc16 = CommonUtils.GetCrc16(Encoding.UTF8.GetBytes(dataStr));int srcCrc16 = Int32.Parse(crc, System.Globalization.NumberStyles.HexNumber);if (srcCrc16 != jisuanCrc16) {return;}bValid = true;}public HJ212(HJ212 r){this.header = r.header;this.dataLen = r.dataLen;//this.data = new HJ212Data(r.data.ToString());this.data = r.data;this.crc = r.crc;this.tailer = r.tailer;this.full = r.full;this.bValid = r.bValid;}public HJ212(string st, string cn, string mn, string pw, string cp, bool needReply){this.data.QN = DateTime.Now.ToString("yyyyMMDDHHMMss000");this.data.ST = st;this.data.CN = cn;this.data.PW = pw;this.data.CP = cp;this.SetNeedReply(needReply);this.Combine();}// 获取响应报文public HJ212 GetDataResponse(string cn){HJ212 outHJ212 = new HJ212(this);outHJ212.data.ST = "91";outHJ212.data.CN = cn;outHJ212.ClearCp();outHJ212.Combine();return outHJ212;}/// <summary>/// 解析字符串,获取HJ212协议数据列表/// </summary>/// <param name="buffer">输入字符串</param>/// <returns>返回解析后的HJ212协议列表</returns>public static List<HJ212> Parse(string buffer){List<HJ212> hj212List = new List<HJ212>();int bufferSize = buffer.Length;string strTemp = "";for (int i = 0; i < bufferSize; i++){if ( i < bufferSize - 1 && buffer[i] == '#' && buffer[i + 1] == '#'){if (strTemp.Length > 0){hj212List.Add(new HJ212(strTemp));strTemp = "";}}strTemp += buffer[i];// 遍历到HJ212协议末尾,末尾以\r\n结束if (i > 0 && buffer[i - 1] == '\r' && buffer[i] == '\n'){if (strTemp.Length > 0){hj212List.Add(new HJ212(strTemp));strTemp = "";}}}if (strTemp.Length > 0){hj212List.Add(new HJ212(strTemp));strTemp = "";}return hj212List;}private bool bValid = false;}
}

测试程序

新建一个基于C# .Net的控制台程序ConsoleHJ212App,然后输入如下测试代码:

using HJ212ParseLibrary;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;namespace ConsoleHJ212App
{public class Program{static void Main(string[] args){string buffer = "##0637ST=22;CN=2011;PW=123456;MN=LB4200001;CP=&&DataTime=20210107143500;a05002-Rtd=0,a05002-Flag=N;a21005-Rtd=0.825,a21005-Flag=N;a34006-Rtd=874,a34006-Flag=N;a24088-Rtd=0,a24088-Flag=N;a21003-Rtd=5.656,a21003-Flag=N;a21004-Rtd=9.253,a21004-Flag=N;a21002-Rtd=17.894,a21002-Flag=N;a05024-Rtd=5.803,a05024-Flag=N;a34007-Rtd=2679,a34007-Flag=N;a34002-Rtd=123.97,a34002-Flag=N;a34004-Rtd=24.82,a34004-Flag=N;a01006-Rtd=1032.3,a01006-Flag=N;a01002-Rtd=20.9,a01002-Flag=N;a21026-Rtd=0.795,a21026-Flag=N;a01007-Rtd=3.3,a01007-Flag=N;a34049-Rtd=3553,a34049-Flag=N;a01001-Rtd=-0.6,a01001-Flag=N;a99999-Rtd=0,a99999-Flag=N;a01008-Rtd=349,a01008-Flag=N&&3300\r\n##0404ST=22;CN=2011;PW=123456;MN=LB4200001;CP=&&DataTime=20210107152600;a05002-Rtd=1.755,a05002-Flag=N;a21005-Rtd=0.699,a21005-Flag=N;a34006-Rtd=845,a34006-Flag=N;a24088-Rtd=4.945,a24088-Flag=N;a21003-Rtd=3.877,a21003-Flag=N;a21002-Rtd=14.502,a21002-Flag=N;a05024-Rtd=10.389,a05024-Flag=N;a34007-Rtd=2859,a34007-Flag=N;a21026-Rtd=1.525,a21026-Flag=N;a34049-Rtd=3704,a34049-Flag=N;a99999-Rtd=6.7,a99999-Flag=N&&9C01\r\n";List<HJ212> hj212List = HJ212.Parse(buffer);foreach (HJ212 item in hj212List){Console.WriteLine(item.ToString());}}}
}

并引用HJ212ParseLibrary库项目,在VS2022中运行结果如下图所示:
调试运行结果1

运行结果如下:
解析HJ212协议测试实例
可以看到,我们输入的数据和解析到的数据是一致的,有2个协议数据报文。

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

如若内容造成侵权/违法违规/事实不符,请联系瞎胡闹网进行投诉反馈,一经查实,立即删除!

相关文章

【原创】java+swing+mysql二手车交易管理系统

前言&#xff1a; 本文主要介绍了二手车交易管理设计与实现。首先&#xff0c;通过市场需求&#xff0c;我们确定了二手车的功能&#xff0c;通常的二手车交易系统都是B/S架构&#xff0c;然而我们今天要用javaswing去开发一个C/S架构的二手车交易管理系统&#xff0c;主要功能…

面试经典-33-反转链表 II

题目 给你单链表的头指针 head 和两个整数 left 和 right &#xff0c;其中 left < right 。请你反转从位置 left 到位置 right 的链表节点&#xff0c;返回 反转后的链表 。 示例 1&#xff1a; 输入&#xff1a;head [1,2,3,4,5], left 2, right 4 输出&#xff1a…

【运维】PVE 自带监控显示问题处理

目录 问题描述 问题处理 问题描述 CPU和服务器负载显示为1970-01-01&#xff0c;无法正确显示当前监控 问题处理 使用如下命令 rm /var/lib/rrdcached/db/* -rf刷新网页显示如下

论文浅尝 | GPT-RE:基于大语言模型针对关系抽取的上下文学习

笔记整理&#xff1a;张廉臣&#xff0c;东南大学硕士&#xff0c;研究方向为自然语言处理、信息抽取 链接&#xff1a;https://arxiv.org/pdf/2305.02105.pdf 1、动机 在很多自然语言处理任务中&#xff0c;上下文学习的性能已经媲美甚至超过了全资源微调的方法。但是&#xf…

day10-SpringBootWeb案例-1

一、准备工作 1 需求&环境搭建 步骤&#xff1a; 准备数据库表(dept、emp)创建 springboot 工程&#xff0c;引入对应的起步依赖&#xff08;web、mybatis、mysql 驱动、lombok&#xff09;配置文件 application.properties 中引入 mybatis 的配置信息&#xff0c;准备对应…

【JAVA】JAVA方法的学习和创造

&#x1f308;个人主页: Aileen_0v0 &#x1f525;热门专栏: 华为鸿蒙系统学习|计算机网络|数据结构与算法|MySQL| ​&#x1f4ab;个人格言:“没有罗马,那就自己创造罗马~” 前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不…

算法导论第十一章思考题参考答案(21)

Ploblem 11-1 a.从所有可能的索引中统一计算每个探针的索引。由于我们有 n≤m/2&#xff0c;我们知道在任何阶段至少有一半的指标是空的。因此&#xff0c;对于需要超过 k 个探针&#xff0c;我 们需要在每 k 个第一个探针中&#xff0c;我们探测到一个已经有一个入口的顶点&a…

柚见十三期(优化)

前端优化 加载匹配功能与加载骨架特效 骨架屏 : vant-skeleton index.vue中 /** * 加载数据 */ const loadData async () > { let userListData; loading.value true; //心动模式 if (isMatchMode.value){ const num 10;//推荐人数 userListData await myA…

软件应用,台球管理系统怎么收费,球房计时计费系统的安装方法,计时灯控器连接

软件应用&#xff0c;台球管理系统怎么收费&#xff0c;球房计时计费系统的安装方法&#xff0c;计时灯控器连接 一、前言 以下软件操作教程以 佳易王桌球计时计费管理系统软件V17.9为例说明 件文件下载可以点击最下方官网卡片——软件下载——试用版软件下载 1、软件的安装…

【Spring Boot】创建你的第一个 Spring Boot 应用

创建你的第一个 Spring Boot 应用 1.环境配置2.步骤详解3.项目结构分析3.1 入口类 DemoApplication3.2 控制器 PathVariableController3.3 控制器 BasicController3.4 模型 User 4.运行 Spring Boot 目前已经成为了 Java 开发领域的框架范式。本篇博客&#xff0c;我将带领大家…

Vision Pro的初体验

每周跟踪AI热点新闻动向和震撼发展 想要探索生成式人工智能的前沿进展吗&#xff1f;订阅我们的简报&#xff0c;深入解析最新的技术突破、实际应用案例和未来的趋势。与全球数同行一同&#xff0c;从行业内部的深度分析和实用指南中受益。不要错过这个机会&#xff0c;成为AI领…

redis学习-redis介绍以及一些通用命令

目录 1.redis介绍 2.redis常用命令&#xff08;可以在官网的命令中查看redis的所有命令&#xff09; 2.1终端命令 2.2 redis通用命令 1.redis介绍 redis即远程字典服务&#xff0c;是当下最热门的NoSQL&#xff08;非关系型数据库&#xff09;技术之一&#xff0c;采用…

中文编程入门(Lua5.4.6中文版)第四章 Lua 循环

在游戏开发的奇幻世界中&#xff0c;循环机制就像一位执着的冒险者&#xff0c;在特定规则&#xff08;条件&#xff09;的指引下&#xff0c;会不断重复执行一系列精心设计的游戏动作。在 Lua 这款强大而灵活的游戏引擎中&#xff0c;我们有几种独特的“游戏回合”来实现这一规…

C++算法学习心得八.动态规划算法(4)

1.零钱兑换&#xff08;322题&#xff09; 题目描述&#xff1a; 给定不同面额的硬币 coins 和一个总金额 amount。编写一个函数来计算可以凑成总金额所需的最少的硬币个数。如果没有任何一种硬币组合能组成总金额&#xff0c;返回 -1。 你可以认为每种硬币的数量是无限的。…

ArkTs的资源Resource类型怎么转为string

使用ResourceManager同步转换 请参看&#xff1a;ResourceManager.getStringSync9 例子&#xff1a; try { let testStr: string this.context.resourceManager.getStringSync($r(app.string.test).id); } catch (error) { console.error(getStringSync failed, error code…

@RequestParam、@PathVariable、@RequestBody

1、中文翻译 RequestParam-请求参数、PathVariable-路径变量、RequestBody请求体 2、作用&#xff1a; Controller中获取前端传递的参数 3、从注解本身角度分析 3.1、PathVariable&#xff1a;路径变量 通过 PathVariable 可以将URL中占位符参数{xxx}绑定到处理器类的方法形…

基于单片机的智能小车泊车系统设计

摘 要:随着信息技术的进步,汽车逐渐朝着安全、智能方向发展,智能泊车系统的出现不仅能帮助人们更加快速、安全地完成泊车操作,而且适用于狭小空间的泊车操作,降低驾驶员泊车负担,减轻泊车交通事故发生率。文章基于单片机设计自动泊车系统,以单片机为核心来实现信息收集及…

Java程序OOM自动生成.hprof堆文件并使用jvisualvm分析

Java程序OOM自动生成.hprof堆文件并使用jvisualvm分析 1.示例代码2.编译两份源代码3.带jvm参数启动当内存溢出后&#xff0c;命令会出现4.启动jvisualvm5.导入堆文件 1.示例代码 同目录下准备两个.java源文件 StudentOne.java public class StudentOne {private String id;pri…

【Python】成功解决NameError: name ‘cv2‘ is not defined

【Python】成功解决NameError: name ‘cv2’ is not defined &#x1f308; 个人主页&#xff1a;高斯小哥 &#x1f525; 高质量专栏&#xff1a;Matplotlib之旅&#xff1a;零基础精通数据可视化、Python基础【高质量合集】、PyTorch零基础入门教程&#x1f448; 希望得到您…

Rabbit MQ详解

写在前面,由于Rabbit MQ涉及的内容较多&#xff0c;赶在春招我个人先按照我认为重要的内容进行一定总结&#xff0c;也算是个学习笔记吧。主要参考官方文档、其他优秀文章、大模型问答。自己边学习边总结。后面有时间我会慢慢把所有内容补全&#xff0c;分享出来也是希望可以给…