C语言简单数据解析
在嵌入式开发中通过串口等传输数据通常使用JSON解析,虽然JSON十分强大,但JSON耗费资源太多,数据的打包和解析都比较麻烦。有时我们只是传输一些简单的数据,没必要引入JSON。
下面我将介绍一种简单的数据解析方法,通过编写函数,将字符串解析取得目标数据。
解析字符型数据
函数原型
/**
* @brief 从一段字符串中解析期望的字符串
* @param pBuff: 要解析的字符串地址
* @param pLeft: 目标字符串左边的字符串
* @param pRight: 目标字符串右边的字符串
* @param pRes: 接收字符数据的地址
* @retval 0:成功 -1:失败
*/
int DataParsingChar(const char *pBuff, const char *pLeft, const char *pRight,char *pRes)
{
char *pBegin = NULL;
char *pEnd = NULL;
pBegin = strstr(pBuff, pLeft);
pEnd = strstr(pBegin + strlen(pLeft), pRight);
if (pEnd == NULL || pBegin == NULL || pBegin > pEnd) {
return -1;
} else {
pBegin += strlen(pLeft);
memcpy(pRes, pBegin, pEnd - pBegin);
return 0;
}
}
此函数思想是使用strstr
函数找出目标字符串的首尾位置,使用memcpy
函数将目标字符串拷贝给接收数据的指针。
测试代码
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int DataParsingChar(const char *pBuff, const char *pLeft, const char *pRight,char *pRes)
{
char *pBegin = NULL;
char *pEnd = NULL;
pBegin = strstr(pBuff, pLeft);
pEnd = strstr(pBegin + strlen(pLeft), pRight);
if (pEnd == NULL || pBegin == NULL || pBegin > pEnd) {
return -1;
} else {
pBegin += strlen(pLeft);
memcpy(pRes, pBegin, pEnd - pBegin);
return 0;
}
}
int main(int argc, char **argv)
{
/* 原始数据 */
char *name = "LiHua";
int age = 20;
int number = 10086;
char buff[100] = {0};
char re_name[10] = {0};
char re_age[10] = {0};
char re_number[10] = {0};
/* 数据打包 */
sprintf(buff,"name:%s, age:%d, number:%d.",name, age, number);
/* 数据解析 */
DataParsingChar(buff, "name:", ",", re_name);
DataParsingChar(buff, "age:", ",", re_age);
DataParsingChar(buff, "number:", ".", re_number);
printf("buff : %s\n", buff);
printf("re_name : %s\n", re_name);
printf("re_age : %s\n", re_age);
printf("re_number : %s\n", re_number);
return 0;
}
执行结果
buff : name:LiHua, age:20, number:10086.
re_name : LiHua
re_age : 20
re_number : 10086
在测试代码中,使用sprintf
将数据打包,通过传入标识符来获取目标数据。
在有些情况,我们希望在字符串中获取整型数据,例如坐标数据等,可以直接拿来运算使用,对上面的解析函数稍加更改,就可以解析整型数据。
解析整型数据
函数原型
/**
* @brief 从一段字符串中提取出整型数据
* @param pBuff: 要解析的字符串地址
* @param pLeft: 目标数据左边的字符串
* @param pRight: 目标数据右边的字符串
* @param pRes: 接收整型数据的地址
* @retval 0:成功 -1:失败
*/
int DataParsingInt(const char *pBuff, const char *pLeft, const char *pRight, int *pRes)
{
char *pBegin = NULL;
char *pEnd = NULL;
char *pTemp = NULL;
pBegin = strstr(pBuff, pLeft);
pEnd = strstr(pBegin + strlen(pLeft), pRight);
if (pEnd == NULL || pBegin == NULL || pBegin > pEnd) {
return -1;
} else {
pBegin += strlen(pLeft);
pTemp = (char *)malloc(pEnd - pBegin);
memcpy(pTemp, pBegin, pEnd - pBegin);
*pRes = atoi(pTemp);
free(pTemp);
return 0;
}
}
在上面的代码中,增加了atoi
函数。此函数经常用于Linux应用开发中,将终端输入的数字型的字符串转换为整型变量(int
类型)。在不清楚数字长度的情况下使用malloc
分配内存,若传输简短数据可替换成数组,增加代码运行效率。
测试代码
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int DataParsingInt(const char *pBuff, const char *pLeft, const char *pRight, int *pRes)
{
char *pBegin = NULL;
char *pEnd = NULL;
char *pTemp = NULL;
pBegin = strstr(pBuff, pLeft);
pEnd = strstr(pBegin + strlen(pLeft), pRight);
if (pEnd == NULL || pBegin == NULL || pBegin > pEnd) {
return -1;
} else {
pBegin += strlen(pLeft);
pTemp = (char *)malloc(pEnd - pBegin);
memcpy(pTemp, pBegin, pEnd - pBegin);
*pRes = atoi(pTemp);
free(pTemp);
return 0;
}
}
int main(int argc, char **argv)
{
/* 原始数据 */
int left = 123;
int right = 456;
char buff[100] = {0};
int re_left = 0;
int re_right = 0;
/* 数据打包 */
sprintf(buff, "[%d,%d]", left, right);
/* 数据解析 */
DataParsingInt(buff, "[", ",", &re_left);
DataParsingInt(buff, ",", "]", &re_right);
printf("buff : %s\n", buff);
printf("re_left : %d\n", re_left);
printf("re_right : %d\n", re_right);
printf("re_right - re_left = %d\n", re_right - re_left);
return 0;
}
执行结果
buff : [123,456]
re_left : 123
re_right : 456
re_right - re_left = 333
在测试代码中,打包了一个坐标字符串,通过函数解析获得整型得目标数据,可以直接进行运算。