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

ESP32 Arduino中如何将stringstream提取的字符串存入结构体并正常打印?

问题根源与解决方案

核心问题

你遇到的不可读内容问题,本质是野指针导致的非法内存访问:

  • lectura是Extrae_Data函数内的局部std::string变量,c_str()返回的指针指向它内部的临时字符缓冲区。
  • 每次getline会覆盖lectura的内容,函数执行完毕后,lectura被销毁,其内部缓冲区也会被释放。此时结构体里的const char*成员变成野指针,指向已释放的内存,打印自然出现乱码或不可读内容。

另外你的contador计数逻辑和switch case的匹配存在错误,会导致数据存错结构体成员,这也需要同步修正。


解决方案1:改用std::string作为结构体成员(推荐,无需手动管理内存)

把结构体里的const char*替换为std::string,赋值时会自动复制字符串内容,不再依赖局部变量的生命周期:

  1. 修改结构体定义:
struct FechaProg {
  std::string dia;
  std::string mes;
  std::string ano;
  std::string hora;
  std::string minuto;
  std::string segundo;
};
  1. 修正函数内的赋值与计数逻辑:
uint8_t Extrae_Data(std::string trama, FechaProg* destino ,char sep) {
  uint8_t contador = 0;
  std::string lectura;
  std::stringstream cadena_leida(trama);
  
  Serial.print("La trama es: ");
  Serial.println(trama.c_str());
  
  while(getline(cadena_leida, lectura, sep))
  {
    if(sep == '-')
    {
      // 按第一个token=mes、第二个=dia、第三个=ano匹配
      switch(contador)
      {
        case 0: destino->mes = lectura; break;
        case 1: destino->dia = lectura; break;
        case 2: destino->ano = lectura; break;
      }
    }
    else if(sep == ':')
    {
      // 按第一个token=hora、第二个=minuto、第三个=segundo匹配
      switch(contador)
      {
        case 0: destino->hora = lectura; break;
        case 1: destino->minuto = lectura; break;
        case 2: destino->segundo = lectura; break;
      }
    }
    // 先处理当前token,再递增计数
    contador++;
    
    // 调试打印修正
    if(sep == '-' && contador == 3)
    {
      Serial.print("Datos fecha: ");
      Serial.println(destino->mes);
      Serial.println(destino->dia);
      Serial.println(destino->ano);
    }
    if(sep == ':' && contador == 3)
    {
      Serial.print("Datos hora: ");
      Serial.println(destino->hora);
      Serial.println(destino->minuto);
      Serial.println(destino->segundo);
    }
  }
  return contador;
}
  1. 打印时直接输出std::string即可:
Serial.println(tiempo.mes);

解决方案2:保留const char*,使用动态内存复制

如果必须保留const char*类型,需要用strdup复制字符串内容到堆内存,避免局部变量销毁导致指针失效:

  1. 修改函数内的赋值语句,比如:
destino->mes = strdup(lectura.c_str());
  1. 注意事项:
    • strdup会在堆上分配内存,后续不再使用结构体时,必须手动释放每个成员的内存,避免内存泄漏:
      free((void*)tiempo.dia);
      free((void*)tiempo.mes);
      free((void*)tiempo.ano);
      // 其他成员同理
      
    • 同样需要修正contador与switch case的匹配逻辑,确保数据存到正确位置。

内容的提问来源于stack exchange,提问作者vram

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.26 11:44:56