Arduino中的字符串提取问题

Posted

技术标签:

【中文标题】Arduino中的字符串提取问题【英文标题】:String extraction issue in Arduino 【发布时间】:2016-06-07 08:51:53 【问题描述】:

我有以下 Arduino 代码

#include "SIM900.h"
#include <SoftwareSerial.h>
#include "inetGSM.h"
#include<String.h>

InetGSM inet;


char msg[165];
char store[2];
char a;
char b;

char* disp;

boolean started=false;

void setup()

     //Serial connection.
     Serial.begin(9600);
     Serial.println("GSM Shield testing.");
     //Start configuration of shield with baudrate.
     //For http uses is raccomanded to use 4800 or slower.
     if (gsm.begin(2400)) 
          Serial.println("\nstatus=READY");
          started=true;
      else Serial.println("\nstatus=IDLE");

     if(started) 
     
          //GPRS attach, put in order APN, username and password.
          //If no needed auth let them blank.
          if (inet.attachGPRS("TATA.DOCOMO.INTERNET", "", ""))
               Serial.println("status=ATTACHED");
          else Serial.println("status=ERROR");
          delay(1000);



          //TCP Client GET, send a GET request to the server and
          //save the reply.
          inet.httpGET("www.boat.esy.es", 80, "/retrieve.php", msg, 165);
          //Print the results.


          Serial.println("\nData received:");
          disp = strstr(msg,"\r\n\r\n");
          disp = disp+4;
          a = disp[1];
          b = disp[2];
     


void loop()

  Serial.println("Begin");
  Serial.println(a);
  Serial.println("+");
  Serial.println(b);
  Serial.println("End");
  delay(500);


我程序中的 disp 变量接受值 1 和 1 作为字符串。我希望这个 1 & 1 存储在两个单独的变量中。所以我尝试了上面提到的方式,这就是我得到的

输出

Begin
1
+

End
Begin
1
+

End
Begin
1
+

End

如果我对数组的理解正确,char arr[100]char* arr 相同,只是前者在内存中保留了100 个字符位置,那么b = disp[2] 应该给后者111 对吗?

我不想使用 String 库,因为那会占用大量内存。因此,如果有任何我不知道的方法可以提取两个 1 并将它们分开存储,请告诉我。

感谢您的宝贵时间!

【问题讨论】:

“11 后 1 对”是什么意思? 你的预期输出是什么? 您确定http://www.boat.esy.es/retrieve.php 返回字符串"\r\n\r\n11"。 IMO 你从那里得到的字符串只是"11",因此disp = strstr(msg,"\r\n\r\n"); 是错误的。 @Rakete1111 当我的 Arduino 向 Web 服务器上的 PHP 脚本发出 GET 请求时,它会收到带有 Header 和 Body 的响应。我已经提取了正文的内容并将其存储在 disp 变量中。存储的内容是 11。现在我希望它们分成 1 和 1,并存储到两个单独的变量 a 和 b @MichaelWalz disp = strstr(msg,"\r\n\r\n") 实际上从 HTTP 响应中提取了我需要的内容。如果您查看我的代码,您会看到响应存储在msg 变量中,并且该响应包含HTTP 1.0 SERVER:APACHE.. 之类的内容(我猜通常是响应的标题部分)。所以为了从它的头部提取响应的主体,我使用了strstr(msg,"\r\n\r\n")。现在我希望将响应“11”拆分为“1”和“1”并存储在两个单独的变量中 【参考方案1】:

您的代码几乎是正确的。

问题出在这里:

disp = strstr(msg,"\r\n\r\n");
disp = disp+4;  // now disp points to the string "11" (correct)

// what follows is wrong
a = disp[1];    // this is the second char element if the disp string
b = disp[2];    // this is the zero terminator of the disp string

你需要这个,因为在 C 数组中索引从 0 开始:

a = disp[0];
b = disp[1];

小测试程序:

#include <stdio.h>
#include <string.h>

int main()

  char *disp;
  char msg[] = "Fake Header\r\n\r\n12";
  char a;
  char b;

  disp = strstr(msg,"\r\n\r\n");
  disp = disp+4;
  a = disp[0];
  b = disp[1]; 

  printf("a = %c\nb = %c\n", a, b);
  return 0;

输出:

a = 1
b = 2

【讨论】:

我不敢相信我犯了这么愚蠢的错误并完全忽略了这一点。非常感谢您指出。现在一切正常【参考方案2】:

这里的代码有很多问题... 首先,您的所有变量都未初始化,并且您在声明后访问它们,而最初没有在内存中赋予它们任何值。要解决此问题,请在继续之前将每个变量设置为:

char a = ''; // & so on...

接下来,char* disp; 是一个指针,而不是一个变量。你实际上并不知道 disp 的物理位置,它指向某个它的内存,也许是一些填充的内存,也许什么都没有。因此,将某些内容存储在 disp 中的最佳方法是将其转换为数组,并在需要时逐部分读取并以正确的格式终止变量。 例如

char disp[2] = ; // Declare disp...
disp[0] = '1';     // Write to disp...
disp[1] = '1';
disp[2] = '\0';

& 最后,你连接的网络服务器的地址也附加了 DynDNS,任何人都可以在没有密码的情况下访问它,任何人都可以开始攻击它,所以我会隐藏它。

【讨论】:

全局范围变量初始化为零:bss 部分。 disp赋值strstr(msg,"\r\n\r\n");的返回值,所以必须是 char *...

以上是关于Arduino中的字符串提取问题的主要内容,如果未能解决你的问题,请参考以下文章

arduino数据类型转换

如何让 Qt 中的程序不断向我的 Arduino 发送字符串?

arduino通信问题的学习与解决

ardiuno怎么将蓝牙串口中调试的数据提取出来

Arduino 统计中文字符串中的中文标点符号数量

Arduino int 到字符串的转换