You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何将形如"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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.17 12:50:15