Character Array Extraction Returning 0

Hello all!

Thank you for taking the time to process my question. I have been fooling around off and on with Arduino for a couple of years now and am familiar with the basics. The board that I have and that I'm using to prototype this project is an Arduino Due. The project is a battery management system with an Internet connection, so the Arduino will be processing HTTP requests and extracting information from them. For instance, at one point, the Arduino will need to extract a complete IP address, subnet mask, default gateway, and HTTP port number from the HTTP request. Here is the code that I've come up with so far to do that, with an example HTTP request array:

char extractedIPOctet1[4];
int iPOctet1;

int iPOctet2StartingIndex;
char extractedIPOctet2[4];
int iPOctet2;

int iPOctet3StartingIndex;
char extractedIPOctet3[4];
int iPOctet3;

int iPOctet4StartingIndex;
char extractedIPOctet4[4];
int iPOctet4;

int subnetOctet1StartingIndex;
char extractedSubnetOctet1[4];
int subnetOctet1;

int subnetOctet2StartingIndex;
char extractedSubnetOctet2[4];
int subnetOctet2;

int subnetOctet3StartingIndex;
char extractedSubnetOctet3[4];
int subnetOctet3;

int subnetOctet4StartingIndex;
char extractedSubnetOctet4[4];
int subnetOctet4;

int gatewayOctet1StartingIndex;
char extractedGatewayOctet1[4];
int gatewayOctet1;

int gatewayOctet2StartingIndex;
char extractedGatewayOctet2[4];
int gatewayOctet2;

int gatewayOctet3StartingIndex;
char extractedGatewayOctet3[4];
int gatewayOctet3;

int gatewayOctet4StartingIndex;
char extractedGatewayOctet4[4];
int gatewayOctet4;

int hTTPPortStartingIndex;
char extractedHTTPPort[6];
int hTTPPort;

void setup() {
  
  Serial.begin(9600);
  
}

void loop() {
  
  char httpRequest[] = "iPAddressOctet1=192&iPAddressOctet2=168&iPAddressOctet3=0&iPAddressOctet4=220&"
  "subnetMaskOctet1=255&subnetMaskOctet2=255&subnetMaskOctet3=255&subnetMaskOctet4=0&defaultGatewayOctet1=192&"
  "defaultGatewayOctet2=168&defaultGatewayOctet3=0&defaultGatewayOctet4=1&hTTPPort=80";

// see if the Next button on the network setup page was clicked
  if (httpRequest[0] == 'i') {
    int networkIndex = 0;
    
    for (byte x = 16; x >= 16; x++) {
      if (httpRequest[x] == '&') {
        iPOctet2StartingIndex = x + 17;
        break;
      }
      extractedIPOctet1[networkIndex] = httpRequest[x];
      networkIndex++;
    }
    iPOctet1 = atoi(extractedIPOctet1); 
    Serial.println("Extracted IP address octet 1:");
    Serial.println(iPOctet1);
    
    delay(1000);
    
    networkIndex = 0;
    for (byte x = iPOctet2StartingIndex; x >= iPOctet2StartingIndex; x++) {
      if (httpRequest[x] == '&') {
        iPOctet3StartingIndex = x + 17;
        break;
      }
      extractedIPOctet2[networkIndex] = httpRequest[x];
      networkIndex++;
    }
    iPOctet2 = atoi(extractedIPOctet2); 
    Serial.println("Extracted IP address octet 2:");
    Serial.println(iPOctet2);
    
    delay(1000);
    
    networkIndex = 0;
    for (byte x = iPOctet3StartingIndex; x >= iPOctet3StartingIndex; x++) {
      if (httpRequest[x] == '&') {
        iPOctet4StartingIndex = x + 17;
        break;
      }
      extractedIPOctet3[networkIndex] = httpRequest[x];
      networkIndex++;
    }
    iPOctet3 = atoi(extractedIPOctet3); 
    Serial.println("Extracted IP address octet 3:");
    Serial.println(iPOctet3);
    
    delay(1000);
    
    networkIndex = 0;
    for (byte x = iPOctet4StartingIndex; x >= iPOctet4StartingIndex; x++) {
      if (httpRequest[x] == '&') {
        subnetOctet1StartingIndex = x + 18;
        break;
      }
      extractedIPOctet4[networkIndex] = httpRequest[x];
      networkIndex++;
    }
    iPOctet4 = atoi(extractedIPOctet4); 
    Serial.println("Extracted IP address octet 4:");
    Serial.println(iPOctet4);
    
    delay(1000);
    
    networkIndex = 0;
    for (byte x = subnetOctet1StartingIndex; x >= subnetOctet1StartingIndex; x++) {
      if (httpRequest[x] == '&') {
        subnetOctet2StartingIndex = x + 18;
        break;
      }
      extractedSubnetOctet1[networkIndex] = httpRequest[x];
      networkIndex++;
    }
    subnetOctet1 = atoi(extractedSubnetOctet1); 
    Serial.println("Extracted subnet mask octet 1:");
    Serial.println(subnetOctet1);
    
    delay(1000);
    
    networkIndex = 0;
    for (byte x = subnetOctet2StartingIndex; x >= subnetOctet2StartingIndex; x++) {
      if (httpRequest[x] == '&') {
        subnetOctet3StartingIndex = x + 18;
        break;
      }
      if (httpRequest[x] == '&') break;
      extractedSubnetOctet2[networkIndex] = httpRequest[x];
      networkIndex++;
    }
    subnetOctet2 = atoi(extractedSubnetOctet2); 
    Serial.println("Extracted subnet mask octet 2:");
    Serial.println(subnetOctet2);
    
    delay(1000);
    
    networkIndex = 0;
    for (byte x = subnetOctet3StartingIndex; x >= subnetOctet3StartingIndex; x++) {
      if (httpRequest[x] == '&') {
        subnetOctet4StartingIndex = x + 18;
        break;
      }
      extractedSubnetOctet3[networkIndex] = httpRequest[x];
      networkIndex++;
    }
    subnetOctet3 = atoi(extractedSubnetOctet3); 
    Serial.println("Extracted subnet mask octet 3:");
    Serial.println(subnetOctet3);
    
    delay(1000);
    
    networkIndex = 0;
    for (byte x = subnetOctet4StartingIndex; x >= subnetOctet4StartingIndex; x++) {
      if (httpRequest[x] == '&') {
        gatewayOctet1StartingIndex = x + 22;
        break;
      }
      extractedSubnetOctet4[networkIndex] = httpRequest[x];
      networkIndex++;
    }
    subnetOctet4 = atoi(extractedSubnetOctet4); 
    Serial.println("Extracted subnet mask octet 4:");
    Serial.println(subnetOctet4);
    
    delay(1000);
    
    networkIndex = 0;
    for (byte x = gatewayOctet1StartingIndex; x >= gatewayOctet1StartingIndex; x++) {
      if (httpRequest[x] == '&') {
        gatewayOctet2StartingIndex = x + 22;
        break;
      }
      extractedGatewayOctet1[networkIndex] = httpRequest[x];
      networkIndex++;
    }
    gatewayOctet1 = atoi(extractedGatewayOctet1); 
    Serial.println("Extracted default gateway octet 1:");
    Serial.println(gatewayOctet1);
    
    delay(1000);
    
    networkIndex = 0;
    for (byte x = gatewayOctet2StartingIndex; x >= gatewayOctet2StartingIndex; x++) {
      if (httpRequest[x] == '&') {
        gatewayOctet3StartingIndex = x + 22;
        break;
      }
      extractedGatewayOctet2[networkIndex] = httpRequest[x];
      networkIndex++;
    }
    gatewayOctet2 = atoi(extractedGatewayOctet2); 
    Serial.println("Extracted default gateway octet 2:");
    Serial.println(gatewayOctet2);
    
    delay(1000);
    
    networkIndex = 0;
    for (byte x = gatewayOctet3StartingIndex; x >= gatewayOctet3StartingIndex; x++) {
      if (httpRequest[x] == '&') {
        gatewayOctet4StartingIndex = x + 22;
        break;
      }
      extractedGatewayOctet3[networkIndex] = httpRequest[x];
      
      networkIndex++;
    }
    gatewayOctet3 = atoi(extractedGatewayOctet3); 
    Serial.println("Extracted default gateway octet 3:");
    Serial.println(gatewayOctet3);
    
    delay(1000);
    
    networkIndex = 0;
    for (byte x = gatewayOctet4StartingIndex; x >= gatewayOctet4StartingIndex; x++) {
      if (httpRequest[x] == '&') {
        hTTPPortStartingIndex = x + 10;
        break;
      }
      extractedGatewayOctet4[networkIndex] = httpRequest[x];
      networkIndex++;
    }
    gatewayOctet4 = atoi(extractedGatewayOctet4); 
    Serial.println("Extracted default gateway octet 4:");
    Serial.println(gatewayOctet4);
    
    delay(1000);
    
    networkIndex = 0;
    for (byte x = hTTPPortStartingIndex; x >= hTTPPortStartingIndex; x++) {
      if (httpRequest[x] == NULL) break;
      extractedHTTPPort[networkIndex] = httpRequest[x];
      networkIndex++;
    }
    hTTPPort = atoi(extractedHTTPPort);
    Serial.println("Extracted HTTP port number:");
    Serial.println(hTTPPort);
    
    delay(1000);
  }
}

The serial print commands and delays are in there for debugging. When viewed in the serial monitor, this code is able to extract the IP address octets, subnet mask octets, and default gateway octets. However, when it gets to the HTTP port, the code extracts a 0 when it should be 80 (see the HTTP request). Would anyone happen to know why this may be? Perhaps something having to do with it being at the end of the char array? It's probably obvious to you all, but I'm at a loss. Maybe I'm doing this completely wrong!

Let me know if you need any other information. Thank you for your time!

this is how I wuold have done this:

void printaddr(char * ret) {
  char addr2num[4] = "";
  char *ret3 = strstr(ret, "&");

  if (ret3 != NULL) {
    memcpy(addr2num, ret + 1, ret3 - ret);
    addr2num[ret3 - ret] = '\0';
    Serial.println(atoi(addr2num));
  }
}

void findstr(char *src, char *substr1, char *substr2) {
  char tempstr[25] = "";
  char *ret1, *ret2;

  strncat(tempstr, substr1, strlen(substr1));
  strncat(tempstr, substr2, strlen(substr2));

  ret1 = strstr(src, tempstr);

  if (ret1 != NULL) {
    Serial.print(tempstr);
    Serial.print(": ");
    
    ret2 = strstr(ret1, "=");
    if (ret2 != NULL) {
      printaddr(ret2);
    }
  }
}


void setup () {
  Serial.begin(115200);

  delay(1000);

  char httpRequest[] = "iPAddressOctet1=192&iPAddressOctet2=168&iPAddressOctet3=0&iPAddressOctet4=220&"
                       "subnetMaskOctet1=255&subnetMaskOctet2=255&subnetMaskOctet3=255&subnetMaskOctet4=0&defaultGatewayOctet1=192&"
                       "defaultGatewayOctet2=168&defaultGatewayOctet3=0&defaultGatewayOctet4=1&hTTPPort=80";

  char iPAddressOctet[] = "iPAddressOctet";
  char subnetMaskOctet[] = "subnetMaskOctet";
  char defaultGatewayOctet[] = "defaultGatewayOctet";
  char hTTPPort[] = "hTTPPort";
  char str2num[4] = "";
  static char *ret, *ret_ip;

  //Serial.println(httpRequest);
  ret_ip = strstr(httpRequest, iPAddressOctet);

  while (ret_ip != NULL) {
    //httpRequest;
    ret = strstr(ret_ip, "=");
    if (ret != NULL) {
      memcpy(str2num, ret_ip + strlen(iPAddressOctet), ret - (ret_ip + strlen(iPAddressOctet)));
      str2num[ret - (ret_ip + strlen(iPAddressOctet))] = '\0';
      Serial.print(iPAddressOctet);
      Serial.print(str2num);
      Serial.print(": ");
      
      printaddr(ret);

      findstr(httpRequest, subnetMaskOctet, str2num);

      findstr(httpRequest, defaultGatewayOctet, str2num);

    }
    
    ret_ip = strstr(ret, iPAddressOctet);
    Serial.println("");
  }

  ret = strstr(httpRequest, hTTPPort);

  if (ret != NULL) {
    Serial.print(hTTPPort);
    Serial.print(": ");
    
    ret = strstr(ret, "=");
    if (ret != NULL) {
      Serial.println(atoi(ret + 1));
    }
  }

}

void loop() {

}

Output:

iPAddressOctet1: 192
subnetMaskOctet1: 255
defaultGatewayOctet1: 192
iPAddressOctet2: 168
subnetMaskOctet2: 255
defaultGatewayOctet2: 168
iPAddressOctet3: 0
subnetMaskOctet3: 255
defaultGatewayOctet3: 0
iPAddressOctet4: 220
subnetMaskOctet4: 0
defaultGatewayOctet4: 1
hTTPPort: 80

hope that helps....

Thank you, sherzaad. I copied and pasted your code into the compiler (I'm using Arduino's online editor) and this is the error I got:

/home/builder/opt/arduino-builder/arduino-builder -compile -core-api-version 10611 -hardware /home/builder/opt/arduino-builder/hardware -hardware /home/builder/.arduino15/packages -tools /home/builder/opt/arduino-builder/tools -tools /home/builder/.arduino15/packages -built-in-libraries /home/builder/opt/libraries/latest -logger humantags -fqbn arduino:sam:arduino_due_x_dbg -build-cache /tmp -build-path /tmp/814143065/build -verbose -prefs runtime.tools.arm-none-eabi-gcc.path=/home/builder/.arduino15/packages/arduino/tools/arm-none-eabi-gcc/4.8.3-2014q1 -prefs runtime.tools.bossac.path=/home/builder/.arduino15/packages/arduino/tools/bossac/1.6.1-arduino -prefs runtime.tools.avr-gcc.path=/home/builder/.arduino15/packages/arduino/tools/avr-gcc/7.3.0-atmel3.6.1-arduino5 -prefs runtime.tools.dfu-util.path=/home/builder/.arduino15/packages/arduino/tools/dfu-util/0.9.0-arduino2 -prefs runtime.tools.arm-linux-gcc.path=/home/builder/.arduino15/packages/arduino/tools/arm-linux-gcc/4.9.3 -prefs runtime.tools.CMSIS-Atmel.path=/home/builder/.arduino15/packages/arduino/tools/CMSIS-Atmel/1.2.0 -prefs runtime.tools.linuxuploader.path=/home/builder/.arduino15/packages/arduino/tools/linuxuploader/1.5.1 -prefs runtime.tools.ctags.path=/home/builder/.arduino15/packages/builtin/tools/ctags/5.8-arduino11 -prefs runtime.tools.serial-discovery.path=/home/builder/.arduino15/packages/builtin/tools/serial-discovery/1.1.0 -prefs runtime.tools.core2-32-poky-linux.path=/home/builder/.arduino15/packages/Intel/tools/core2-32-poky-linux/1.6.2+1.0 -prefs runtime.tools.sketchUploader.path=/home/builder/.arduino15/packages/Intel/tools/sketchUploader/1.6.2+1.0 -prefs runtime.tools.arduinoOTA.path=/home/builder/.arduino15/packages/arduino/tools/arduinoOTA/1.3.0 -prefs runtime.tools.xtensa-lx106-elf-gcc.path=/home/builder/.arduino15/packages/esp8266/tools/xtensa-lx106-elf-gcc/2.5.0-3-20ed2b9 -prefs runtime.tools.avrdude.path=/home/builder/.arduino15/packages/arduino/tools/avrdude/6.3.0-arduino8 -prefs runtime.tools.arc-elf32.path=/home/builder/.arduino15/packages/Intel/tools/arc-elf32/1.6.9+1.0.1 -prefs runtime.tools.flashpack.path=/home/builder/.arduino15/packages/Intel/tools/flashpack/2.0.0 -prefs runtime.tools.i586-poky-linux-uclibc.path=/home/builder/.arduino15/packages/Intel/tools/i586-poky-linux-uclibc/1.6.2+1.0 -prefs runtime.tools.mkspiffs.path=/home/builder/.arduino15/packages/esp8266/tools/mkspiffs/2.5.0-3-20ed2b9 -prefs runtime.tools.openocd.path=/home/builder/.arduino15/packages/Intel/tools/openocd/0.9.0+0.1 -prefs runtime.tools.CMSIS.path=/home/builder/.arduino15/packages/arduino/tools/CMSIS/4.5.0 -prefs runtime.tools.nrf5x-cl-tools.path=/home/builder/.arduino15/packages/arduino/tools/nrf5x-cl-tools/9.3.1 -prefs runtime.tools.x86-linux-gcc.path=/home/builder/.arduino15/packages/arduino/tools/x86-linux-gcc/7.2.0 -prefs runtime.tools.arduino101load.path=/home/builder/.arduino15/packages/Intel/tools/arduino101load/2.0.1 -prefs runtime.tools.esptool.path=/home/builder/.arduino15/packages/esp8266/tools/esptool/2.5.0-3-20ed2b9 -libraries /tmp/814143065/custom -libraries /tmp/814143065/pinned /tmp/814143065/String_Parser
Compiling sketch...
/tmp/814143065/String_Parser/String_Parser.ino: In function 'void setup()':
/tmp/814143065/String_Parser/String_Parser.ino:58:52: error: invalid conversion from 'const char*' to 'char*' [-fpermissive]
findstr(httpRequest, subnetMaskOctet, str2num);
^
/tmp/814143065/String_Parser/String_Parser.ino:12:6: error: initializing argument 2 of 'void findstr(char*, char*, char*)' [-fpermissive]
void findstr(char src, char substr1, char substr2) {
^
/tmp/814143065/String_Parser/String_Parser.ino:60:56: error: invalid conversion from 'const char
' to 'char
' [-fpermissive]
findstr(httpRequest, defaultGatewayOctet, str2num);
^
/tmp/814143065/String_Parser/String_Parser.ino:12:6: error: initializing argument 2 of 'void findstr(char
, char*, char*)' [-fpermissive]
void findstr(char *src, char *substr1, char *substr2) {
^
exit status 1

So I changed the const char arrays at line 39 to char arrays and that resolved the error. However, the output I was receiving looked like this:

iPAddressOctet1192
subnetMaskOctet1255
defaultGatewayOctet1192
hTTPPort80

How do I achieve the output that you achieved when running the sketch?

Thanks!

what board are you using?

The board is an Arduino Due:

https://store.arduino.cc/usa/due

Yeah... I tried this code as well on due and I think it was a fluke it worked the first time!

Wen I tried to re-upload the code I got the same issue.

got rid of the 'const' and made the pointers 'static' and that seemed to do the trick this time round (updated code in reply #1).

Hope that work for you as well this time! :wink:

Thanks sherzaad, no errors this time! I'll actually get to try the code on the Due a bit later. And spend some time figuring out how it works!

Here is another way to do it

It may need some error-checking :slight_smile:

Sherzaad, I uploaded your updated sketch into the Due and this is the output that it's giving me:

iPAddreshKvq(vq(VT0FV0Fd:

Guix, thank you for your suggestion! I did put copy your sketch into the compiler and receive errors unfortunately - I might try working them out if I'm able.

It looks like clearly there's a more efficient way to do this that's going to take me some time to figure out - it's a bit over my head at the moment. However, for the sake of learning and curiosity, would either of you have any idea why my original sketch was returning 0 for the HTTP port number?

at one point, the Arduino will need to extract a complete IP address, subnet mask, default gateway, and HTTP port number from the HTTP request. Here is the code that I've come up with so far to do that, with an example HTTP request array:

I don't have time at the moment but with the example array it looks like you could extract the data using the strtok() function

Ok, I think I've heard of strtok(). I'll look into it, thanks UKHeliBob.

I tell you why your code doesn't work for the httpPort. Mainly because your whole code is wrong, it's simply not the way to do it, you hardcoded almost everything and all your for loops are wrong !

Why httpPort doesn't work :

Your httpRequest string length is 267, so hTTPPortStartingIndex should be equal to 266 because the port is 80 which is 2 characters.

A byte can hold a value between 0 and 255, and if you try to put a value greater than 255 in a byte, it will overflow and wraps around. For example if you put 266 in a byte, the result will be 10 (266%256)

So if hTTPPortStartingIndex = 266, then in this loop:

for (byte x = hTTPPortStartingIndex; x >= hTTPPortStartingIndex; x++) {

x will start with a value of 10 (edit: in fact, the loop will not run at all, x will be 10, so it will never be greater than hTTPPortStartingIndex)

Why your for loops are wrong :

Take the first loop for example:

for (byte x = 16; x >= 16; x++) {

It means: set x to 16, then increase x while it's greater or equal 16. So, as said, a byte can be between 0 to 255, so this for loop would loop 256-16 = 240 times (but fortunately, you use break to stop it). I think it's not what you expected ! If you don't know how many time you have to loop, then use a while loop instead

Demonstration of the problems : vlNWRC - Online C++ Compiler & Debugging Tool - Ideone.com

Ah, that makes sense! I changed byte to int and now I'm getting 80 for the HTTP port - thanks Guix!

If I can't figure out how your sketches are able to extract the data with much less code, then I'll revise my much more basic sketch with while() loops.

Thanks again!

This topic was automatically closed 120 days after the last reply. New replies are no longer allowed.