需求背景:
在项目的mqtt相关业务中需要解析topic字符串,如下格式示例 “homeassistant/switch/112233AABBCC-01/set”,需要解析获取到字段"112233AABBCC"所代表的目标设备MAC地址、字段"01"所代表的操作位、字段"set"所代表的操作命令;
实施方法:
uint8_t macTarget[MWIFI_ADDR_LEN] = {0}; //MWIFI_ADDR_LEN = 6
uint8_t opBitNum = 0;
char eventTopic_temp[128] = {0};
char opreatTopic[16] = {0};
memcpy(eventTopic_temp, event->topic, sizeof(char) * event->topic_len); //设定event->topic的字符串为"homeassistant/switch/112233AABBCC-01/set"
sscanf(eventTopic_temp, "%*[^/]/%*[^/]/%02X%02X%02X%02X%02X%02X-%d/%s",
(int *)&macTarget[0],
(int *)&macTarget[1],
(int *)&macTarget[2],
(int *)&macTarget[3],
(int *)&macTarget[4],
(int *)&macTarget[5],
(int *)&opBitNum,
opreatTopic);
%*[^/] : 取到指定字符为止的字符串(%[^/] )并过滤掉不要(%*[^/] );
实施时遇到问题:
运行功能后macTarget、opBitNum、opreatTopic都可以正常获取,但是运行完这段代码后,其他变量内存收到了扰乱:
uint8_t macTarget[MWIFI_ADDR_LEN] = {0}; //MWIFI_ADDR_LEN = 6
uint8_t opBitNum = 0;
char eventTopic_temp[128] = {0};
char opreatTopic[16] = {0};
uint8_t haDevSelfMac[MWIFI_ADDR_LEN] = {0};
esp_wifi_get_mac(ESP_IF_WIFI_STA, haDevSelfMac);
printf("self-mac:%02X%02X%02X%02X%02X%02X"); //此处获取打印值为:"self-mac:345C6D8729D8"
memcpy(eventTopic_temp, event->topic, sizeof(char) * event->topic_len); //设定event->topic的字符串为"homeassistant/switch/112233AABBCC-01/set"
sscanf(eventTopic_temp, "%*[^/]/%*[^/]/%02X%02X%02X%02X%02X%02X-%d/%s",
(int *)&macTarget[0],
(int *)&macTarget[1],
(int *)&macTarget[2],
(int *)&macTarget[3],
(int *)&macTarget[4],
(int *)&macTarget[5],
(int *)&opBitNum,
opreatTopic);
printf("self-mac:%02X%02X%02X%02X%02X%02X"); //此处获取打印值为:"self-mac:0000008729D8" -前三个字节内存被清零
分析解决问题:
字符串"%02X"表明必须将输入字符串作为一个int类型来保存到目标地址处,应该是使用指针强转(int *)破坏了相关内存布局;
故重新编写功能为:
uint8_t loop = 0;
int macTarget_16b[MWIFI_ADDR_LEN] = {0};
uint8_t macTarget_8b[MWIFI_ADDR_LEN] = {0};
int opBitNum_16b = 0;
char eventTopic_temp[128] = {0};
char opreatTopic[16] = {0};
memcpy(eventTopic_temp, event->topic, sizeof(char) * event->topic_len);
sscanf(eventTopic_temp, "%*[^/]/%*[^/]/%02X%02X%02X%02X%02X%02X-%d/%s", //避免内存布局被sscanf打乱,强制使用int型缓冲中转
&macTarget_16b[0],
&macTarget_16b[1],
&macTarget_16b[2],
&macTarget_16b[3],
&macTarget_16b[4],
&macTarget_16b[5],
&opBitNum_16b,
opreatTopic);
for(loop = 0; loop < MWIFI_ADDR_LEN; loop ++){
macTarget_8b[loop] = macTarget_16b[loop];
}
问题解决,变量内存恢复正常。