如何将形如"0x21,0x32,'I',0x0f,0x00"的字符串转为uint8_t数组?
问题:将混合格式的逗号分隔字符串转换为uint8_t数组
我用Arduino从API读取数据,拿到的root_0_Title是形如"0x21, 0x32, 'I', 'F', 0x00"的字符串,需要把它转换成对应的uint8_t数组(比如uint8_t data[5]={33, 50, 73, 70, 0})。之前尝试用strtol只能解析第一个元素,无法处理整个数组,求可行的实现方法。
当前读取API的代码如下:
#include <WiFi.h> #include <HTTPClient.h> #include <ArduinoJson.h> const char* ssid = "****"; const char* pass = "****"; void setup() { Serial.begin(115200); WiFi.begin(ssid, pass); while (WiFi.status() != WL_CONNECTED) { delay(500); } } int dataReceived = 0, dataSent = 0; void loop() { const char* root_0_id ; const char* root_0_Title ; if (WiFi.status() == WL_CONNECTED && dataReceived == 0) { HTTPClient client; client.begin("https://6336d6c365d1e8ef267481aa.mockapi.io/user?id=1"); int httpCode = client.GET(); if (httpCode > 0) { String payload = client.getString(); if (payload != "[]") { DynamicJsonDocument doc(49152); DeserializationError error = deserializeJson(doc, payload); if (error) { return; } root_0_id = doc[0]["id"]; root_0_Title = doc[0]["Bitmap"]; client.end(); dataReceived = 1; delay(2000); } } else { Serial.println("Error on HTTP request"); } } if (dataReceived == 1 && dataSent == 0) { // 目前是按字符串发送,需要改成发送转换后的uint8_t数组 Serial.write(root_0_Title, 40997); dataSent = 1; } }
解决方案:实现字符串解析函数
可以写一个专门的解析函数,逐个分割字符串中的元素,分别处理十六进制格式(0x开头)和字符格式(单引号包裹)的内容,最终填充到uint8_t数组中。
解析函数实现
#include <cstring> #include <ctype.h> // 解析函数:输入逗号分隔的字符串,输出uint8_t数组,返回解析到的元素个数 int parseBitmapString(const char* input, uint8_t* output, size_t maxOutputSize) { char* buffer = strdup(input); // 复制输入字符串,避免修改原只读数据 if (!buffer) return 0; // 内存分配失败直接返回 int count = 0; char* token = strtok(buffer, ","); // 按逗号分割字符串 while (token != nullptr && count < maxOutputSize) { // 跳过元素前后的空格 while (isspace((unsigned char)*token)) token++; char* end = token + strlen(token) - 1; while (end > token && isspace((unsigned char)*end)) end--; *(end + 1) = '\0'; // 截断末尾空格 uint8_t value = 0; if (strncmp(token, "0x", 2) == 0) { // 处理0x开头的十六进制值 value = (uint8_t)strtol(token + 2, nullptr, 16); } else if (*token == '\'' && *(end) == '\'') { // 处理单引号包裹的字符 if (end - token >= 1) { value = (uint8_t)token[1]; } } else { // 可选:处理十进制数字格式 value = (uint8_t)atoi(token); } output[count++] = value; token = strtok(nullptr, ","); // 获取下一个元素 } free(buffer); return count; }
在原代码中使用该函数
修改loop中处理root_0_Title的部分,替换原有的发送逻辑:
void loop() { const char* root_0_id ; const char* root_0_Title ; uint8_t bitmapData[8199]; // 对应实际需要存储的8199个元素 int bitmapLength = 0; if (WiFi.status() == WL_CONNECTED && dataReceived == 0) { // 原有的API请求代码保持不变 root_0_id = doc[0]["id"]; root_0_Title = doc[0]["Bitmap"]; // 解析字符串到uint8_t数组 bitmapLength = parseBitmapString(root_0_Title, bitmapData, sizeof(bitmapData)); client.end(); dataReceived = 1; delay(2000); } if (dataReceived == 1 && dataSent == 0) { // 发送解析后的二进制数组,长度为实际解析到的元素个数 Serial.write(bitmapData, bitmapLength); dataSent = 1; } }
关键说明
- 用
strtok按逗号分割字符串,逐个处理每个元素,避免一次性解析的局限性 - 先去除每个元素的前后空格,避免格式干扰导致解析错误
- 针对性处理三种输入格式:十六进制值、单引号包裹字符、十进制数字
- 用
strdup复制输入字符串,避免修改API返回的只读字符串 - 解析时限制数组最大长度,防止内存溢出
内容的提问来源于stack exchange,提问作者Just doin Gods work
相关产品推荐
相关产品推荐

