作者|釜薪君
公众号|嵌入式杂牌军
前言
上篇中与小伙伴们分享一下数据通信过程中数据的转义,今天来它的后篇——数据的解析。
一、关于转义与解析的说明
1.为什么要进行转义与解析
数据通信中需要对有特定功能的数据在发送时进行转义,在接收时进行解析。
比如通信协议中将0x8a作为帧起始符号,将0x8c作为帧结束符号,为了避免混淆,当数据中也出现0x8a或0x8c时就要对这些字符进行转义,这样可以避免将数据误作为起始或结束帧。
转义可以类比C代码的转义字符。
2.什么是数据的转义
在数据发送时,将敏感功能编码相同的数据转换为协议可识别的数据的过程。
3.什么是数据的解析
在数据接收时,将转义数据恢复成原发送数据的过程。
二、实例代码
1.实例代码
转义规则如下:
0x8a -> 0x8c0a
0x8b -> 0x8c0b
0x8c -> 0x8c0c
数据中碰到十六进制的8a就将8a替换为8c0a,其他两个类似,不满足转义条件的数据保持不变。
解析规则如下:
8c0a -> 8a
8c0b -> 8b
8c0c -> 8c
转义之后是字符串,字符串的替换处理起来比较方便所以,解析后是字符串,而并非是整型数据,想获得整型数据需要对数据进行转换,注意数据位数问题哈,这里就不转了。
说明都在代码注释中了。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
#define MAXSIZE 500 // 临时缓冲数组大小
/* 转义函数声明 */
void RecoveryData(char *str);
char *EscapeData(uint32_t dat);
int main(int argc, char *argv[])
{
uint32_t inputdata = 0x128a8b8c; // 要转义的数据
char *p = malloc(100);
printf("\n转义规则(整型数据): \n \
\n 0x8a -> 0x8c0a \
\n 0x8b -> 0x8c0b \
\n 0x8c -> 0x8c0c \
\n 数据不满足条件不变 \
\n");
printf("\n转义前的数据:0x%x\n",inputdata); // 打印转义前的数据
strcpy(p,EscapeData(inputdata)); // int转字符串后进行数据转义
printf("转义后的数据:0x%s\n",p); // 打印转义后的数据
printf("\n解析规则(字符串): \n \
\n 8c0a -> 8a \
\n 8c0b -> 8b \
\n 8c0c -> 8c \
\n 数据不满足条件不变 \
\n");
printf("\n解析前的数据:0x%s\n",p); // 打印解析前的数据(即转义后的数据)
RecoveryData(p); // 进行数据的解析
printf("解析后的数据:0x%s\n",p); // 打印解析后的数据
/* 上面打印的数据是字符串,需要的话可以将解析后的数据转回整型数据,注意数据的大小!*/
free(p);
return 0;
}
/* 数据转义,输入为整型,输出是字符串 */
char *EscapeData(uint32_t dat)
{
uint8_t i;
uint32_t tmp[4] = {0,0,0,0},array[10] = {0,0,0,0,0,0,0,0,0,0};
char s0[10],s1[10],s2[10],s3[10];
char *ret = malloc(100);
/* 按字节分割32位数据 */
tmp[0] = dat & 0xFF; // 最低位
tmp[1] = (dat >> 8) & 0xFF; // 次低位
tmp[2] = (dat >> 16) & 0xFF; // 次高位
tmp[3] = (dat >> 24) & 0xFF; // 最高位
for(i = 0; i < 4; i++)
{
if((tmp[i] == 0x8a) && (tmp[i] != 0x8b) && (tmp[i] != 0x8c))
{
array[i] = (0x8c << 8) | (0x8a^0x80); // 按转义条件进行转义 0x8a -> 0x8c 0x0a -> 0x8c0a
}
else if((tmp[i] == 0x8b) && (tmp[i] != 0x8a) && (tmp[i] != 0x8c))
{
array[i] = (0x8c << 8) | (0x8b^0x80); // 按转义条件进行转义 0x8b -> 0x8c 0x0b -> 0x8c0b
}
else if((tmp[i] == 0x8c) && (tmp[i] != 0x8a) && (tmp[i] != 0x8b))
{
array[i] = (0x8c << 8) | (0x8c^0x80); // 按转义条件进行转义 0x8c -> 0x8c 0x0c -> 0x8c0c
}
else
{
array[i] = tmp[i]; // 不满足转义条件的数据不变
}
}
/* 按字节进行整数转字符串 */
sprintf(s0,"%02x",array[0]);
sprintf(s1,"%02x",array[1]);
sprintf(s2,"%02x",array[2]);
sprintf(s3,"%02x",array[3]);
ret = strcat(s3,strcat(s2,strcat(s1,s0))); // 字符串拼接
free(ret);
return ret;
}
/* 数据解析,输入是字符串,所以用得是处理字符串的方式 */
void RecoveryData(char *str)
{
char str1[] = "8c0a"; // 查找的字符,要被替换的字符
char str2[] = "8a"; // 要替换的字符
char str3[] = "8c0b";
char str4[] = "8b";
char str5[] = "8c0c";
char str6[] = "8c";
uint8_t i, j, k, SeachFlag = 1;
uint8_t count = 0, gap = 0;
char temp[MAXSIZE];
// 8c0a -> 8a
for(i = 0; i < strlen(str); i += gap)
{
if(str[i] == str1[0])
{
SeachFlag = 0;
for(j = i, k = 0; k < strlen(str1); j++, k++)
{
if(str[j] != str1[k])
{
SeachFlag = 1;
gap = k;
break;
}
}
if(0 == SeachFlag) // 已找到待替换字符串并替换
{
for(j = i + strlen(str1), k = 0; j < strlen(str); j++, k++)
{
temp[k] = str[j]; // 保存原字符串中剩余的字符
}
temp[k] = '\0'; // 将字符数组变成字符串
for(j = i, k = 0; k < strlen(str2); j++, k++)
{
str[j] = str2[k]; // 字符串替换
count++;
}
for(k = 0; k < strlen(temp); j++, k++)
{
str[j] = temp[k]; // 剩余字符串回接
}
str[j] = '\0'; // 将字符数组变成字符串
gap = strlen(str);
}
}
else
{
gap = 1;
}
}
// 8c0b -> 8b
for(i = 0; i < strlen(str); i += gap)
{
if(str[i] == str3[0])
{
SeachFlag = 0;
for(j = i, k = 0; k < strlen(str3); j++, k++)
{
if(str[j] != str3[k])
{
SeachFlag = 1;
gap = k;
break;
}
}
if(0 == SeachFlag) // 已找到待替换字符串并替换
{
for(j = i + strlen(str3), k = 0; j < strlen(str); j++, k++)
{
temp[k] = str[j]; // 保存原字符串中剩余的字符
}
temp[k] = '\0'; // 将字符数组变成字符串
for(j = i, k = 0; k < strlen(str4); j++, k++) // 字符串替换
{
str[j] = str4[k];
count++;
}
for(k = 0; k < strlen(temp); j++, k++)
{
str[j] = temp[k]; // 剩余字符串回接
}
str[j] = '\0'; // 将字符数组变成字符串
gap = strlen(str3);
}
}
else
{
gap = 1;
}
}
// 8c0c -> 8c
for(i = 0; i < strlen(str); i += gap)
{
if(str[i] == str5[0])
{
SeachFlag = 0;
for(j = i, k = 0; k < strlen(str5); j++, k++)
{
if(str[j] != str5[k])
{
SeachFlag = 1;
gap = k;
break;
}
}
if(0 == SeachFlag) // 已找到待替换字符串并替换
{
for(j = i + strlen(str5), k = 0; j < strlen(str); j++, k++)
{
temp[k] = str[j]; // 保存原字符串中剩余的字符
}
temp[k] = '\0'; // 将字符数组变成字符串
for(j = i, k = 0; k < strlen(str6); j++, k++) // 字符串替换
{
str[j] = str6[k];
count++;
}
for(k = 0; k < strlen(temp); j++, k++) // 剩余字符串回接
{
str[j] = temp[k];
}
str[j] = '\0'; // 将字符数组变成字符串
gap = strlen(str5);
}
}
else
{
gap = 1;
}
}
}
2.运行结果
今天就到这吧,希望对小伙伴有所帮助哈!
欢迎关注公众号~