Loading... ## 前言 在协议对接开发中,发现数据帧的校验计算、逐项加、逐项减之类的运算很多,人工拼接数据帧时计算很繁琐,于是就有了此文。 ### 需求 1. 校验计算 2. 字节数统计 3. 逐项加 4. 逐项减 ### 实现 #### 1.核心算法 > (1)将字符串形式的十六进制文本转为字节数组。 > > (2)将字节数组转为十六进制的字符串。 #### 2.开发工具 考虑到很久没使用MFC开发过软件了,不清楚VS2019对MFC编程支持程度到底如何了。 因此,就使用MFC开发这个小工具了。 > 集成开发环境:Microsoft Visual Studio Community 2019 > > 界面开发工具:MFC > > 字节编码方式:多字节 > > MFC的使用:在静态库中使用MFC,以避免各种动态库缺失的问题。 #### 3.代码(代码和界面都巨丑,就考虑快速实现功能) ```MFC //将十六进制文本转为字节数组 void StrToHex(byte* pbDest, char* pszSrc, int nLen) { char h1, h2; byte s1, s2; for (int i = 0; i < nLen; i++) { h1 = pszSrc[2 * i]; h2 = pszSrc[2 * i + 1]; s1 = toupper(h1) - 0x30; if (s1 > 9) s1 -= 7; s2 = toupper(h2) - 0x30; if (s2 > 9) s2 -= 7; pbDest[i] = s1 * 16 + s2; } } ``` ```MFC //将字节数组转为十六进制文本 void HexToStr(char* pszDest, byte* pbSrc, int nLen) { char ddl, ddh; for (int i = 0; i < nLen; i++) { ddh = 48 + pbSrc[i] / 16; ddl = 48 + pbSrc[i] % 16; if (ddh > 57) ddh = ddh + 7; if (ddl > 57) ddl = ddl + 7; pszDest[i * 3] = ddh; pszDest[i * 3 + 1] = ddl; pszDest[i * 3 + 2] = 0x20; } } ``` ```MFC //计算累加和并显示字节数 void CToolDlg::OnBnClickedButton1() { CString text; GetDlgItemText(IDC_EDIT1, text); if (text.IsEmpty()) { MessageBox("请输入十六进制文本字符串后再试!", "提示"); return; } text.Replace(" ", ""); //去除 ‘ ’,‘,’,‘0x’等字符 text.Replace("0x", ""); text.Replace(",", ""); CString str; str.Format("[%d]字节", text.GetLength() / 2); SetDlgItemText(IDC_EDIT6, str); char* tmp = new char[text.GetLength()]; memset(tmp, 0, text.GetLength()); StrToHex((byte*)tmp,text.GetBuffer(), text.GetLength()/2); byte sum = 0; int index = 0; while (index < text.GetLength() / 2) { sum += (byte)tmp[index]; //循环累加 index++; } CString result; result.Format("%02X", sum); SetDlgItemText(IDC_EDIT3, result); delete[] tmp; } ``` ```MFC //逐字节加 -> 结果仍为十六进制字符串 void CToolDlg::OnBnClickedButton2() { CString text; GetDlgItemText(IDC_EDIT1, text); if (text.IsEmpty()) { MessageBox("请输入十六进制数字后再试!", "提示"); return; } text.Replace(" ", ""); text.Replace("0x", ""); text.Replace(",", ""); CString str; str.Format("[%d]字节", text.GetLength() / 2); SetDlgItemText(IDC_EDIT6, str); byte* tmp = new byte[text.GetLength()]; memset(tmp, 0, text.GetLength()); StrToHex(tmp, text.GetBuffer(), text.GetLength() / 2); CString data; GetDlgItemText(IDC_EDIT4, data); if (data.IsEmpty()) { MessageBox("请输入需要逐字节加的十六进制字节后再试!", "提示"); return; } data.Replace(" ", ""); data.Replace("0x", ""); data.Replace(",", ""); byte b = 0; StrToHex(&b, data.GetBuffer(), 1); if (b == 0) { MessageBox("请输入需要逐字节加的非0十六进制字节后再试!", "提示"); return; } for (int i = 0; i < text.GetLength() / 2; i++) { tmp[i] += b; } char* result = new char[2 * text.GetLength()+1]; memset(result, 0, 2 * text.GetLength() + 1); HexToStr(result,tmp, text.GetLength() / 2); SetDlgItemText(IDC_EDIT2, CString(result, text.GetLength() * 3)); delete[] result; } ``` ```MFC //逐字节减 -> 结果仍为十六进制字符串 void CToolDlg::OnBnClickedButton3() { CString text; GetDlgItemText(IDC_EDIT1, text); if (text.IsEmpty()) { MessageBox("请输入十六进制数字后再试!", "提示"); return; } text.Replace(" ", ""); text.Replace("0x", ""); text.Replace(",", ""); CString str; str.Format("[%d]字节", text.GetLength() / 2); SetDlgItemText(IDC_EDIT6, str); byte* tmp = new byte[text.GetLength()]; memset(tmp, 0, text.GetLength()); StrToHex(tmp, text.GetBuffer(), text.GetLength() / 2); CString data; GetDlgItemText(IDC_EDIT4, data); if (data.IsEmpty()) { MessageBox("请输入需要逐字节加的十六进制字节后再试!", "提示"); return; } data.Replace(" ", ""); data.Replace("0x", ""); data.Replace(",", ""); byte b = 0; StrToHex(&b, data.GetBuffer(), 1); if (b == 0) { MessageBox("请输入需要逐字节加的非0十六进制字节后再试!", "提示"); return; } for (int i = 0; i < text.GetLength() / 2; i++) { tmp[i] -= b; } char* result = new char[2 * text.GetLength() + 1]; memset(result, 0, 2 * text.GetLength() + 1); HexToStr(result, tmp, text.GetLength() / 2); SetDlgItemText(IDC_EDIT2, CString(result, text.GetLength() * 3)); delete[] result; } ``` ### 后记 说句实话:MFC的CString、lpstr、lpcstr(多字节集的,unicode模式又是另外一套)真是恶心人。 源码详见gitee:[校验和计算工具](https://gitee.com/dhwm/ProtlTool) 最后修改:2022 年 04 月 23 日 11 : 46 PM © 允许规范转载