Arduino not concatenating string in loop

I am trying to get the WWN of an ESP8266 to use as a unique code. Whenever I try to concat it into a string using a loop, the last entry always trashes the contents. (Yes, I can write 6 lines to do it one-by-one, but thats a rubbish coding standard that I want to avoid)

According the Arduino rules, the string length is not exceeded, and the variable scope should be correct. I have reversed the order in case element 0 had some special characters but no change. So why does Arduino keep stuffing the data at the end?

pass1 - forward

  String strFull="";
  String strWork;
  // Loop around appending to strFull
  for (int x = 6; x > 0; x--) {
    int intX = x - 1;
    strWork=String(myMac[intX], HEX);
    strFull.concat(strWork);
     // Serial.printf("MYMAC:%i %s\n", x, String(myMac[x], HEX));
    Serial.printf("MYMAC:%i :%s:\n", intX, strWork);
    Serial.printf("MYMAC_prog: %s\n", strFull);
  }
  Serial.printf("concat strFull: %s\n", strFull);

14:13:14.159 -> MYMAC_prog: c5
14:13:14.191 -> MYMAC:4 :86:
14:13:14.191 -> MYMAC_prog: c586
14:13:14.226 -> MYMAC:3 :7:
14:13:14.226 -> MYMAC_prog: c5867
14:13:14.257 -> MYMAC:2 :ae:
14:13:14.257 -> MYMAC_prog: c5867ae
14:13:14.290 -> MYMAC:1 :11:
14:13:14.290 -> MYMAC_prog: c5867ae11
14:13:14.326 -> MYMAC:0 :4c:
14:13:14.326 -> MYMAC_prog: ��?
14:13:14.357 -> concat strFull: ��?

pass 2 - backwards

// Loop around appending to strFull
  String strFull="";
  String strWork;
  for (byte intX = 0; intX < 6; intX++) {
    strWork=String(myMac[intX], HEX);
    strFull.concat(strWork);
     // Serial.printf("MYMAC:%i %s\n", x, String(myMac[x], HEX));
    Serial.printf("MYMAC:%i :%s:\n", intX, strWork);
    Serial.printf("MYMAC_prog: %s\n", strFull);
  }
Serial.printf("concat strFull: %s\n", strFull);

14:21:59.883 -> MYMAC_prog: 4c
14:21:59.920 -> MYMAC:1 :11:
14:21:59.920 -> MYMAC_prog: 4c11
14:21:59.956 -> MYMAC:2 :ae:
14:21:59.956 -> MYMAC_prog: 4c11ae
14:22:00.023 -> MYMAC:3 :7:
14:22:00.023 -> MYMAC_prog: 4c11ae7
14:22:00.023 -> MYMAC:4 :86:
14:22:00.023 -> MYMAC_prog: 4c11ae786
14:22:00.051 -> MYMAC:5 :c5:
14:22:00.051 -> MYMAC_prog: ��?
14:22:00.085 -> concat strFull: ��?

Regards, Ian

[sterretje edit]
fixed code tags

Without knowing what the type of myMac is, I don't think that anybody can solve your puzzle; is it an uint32_t, a c-string, an array of bytes, a String, ...?

Please post a complete example that demonstrates the issue.

Note:
I have fixed your code tags; it should have been [code] and [/code], not <code> and </code> :wink:

the %s format is to print cString not String instances. You can get the underlying cString with .c_str()

    Serial.printf("MYMAC:%i :%s:\n", intX, strWork.c_str());
    Serial.printf("MYMAC_prog: %s\n", strFull.c_str());
1 Like
// https://forum.arduino.cc/t/esp-uid-or-not-uid/997787/3
// https://www.arduino.cc/reference/en/libraries/wifi/wifi.macaddress/
// https://forum.arduino.cc/t/how-do-i-convert-decimal-to-hexadecimal/499242/7


#include <ESP8266WiFi.h>
#include <ArduinoUniqueID.h>

void setup() {
  Serial.begin(9600);
  Serial.println();
 
  byte myMac[6];
  WiFi.macAddress(myMac);

  Serial.printf("myMac: %s\n", myMac);

  // try to concatenate into string
  String strFull="";
  String strWork;
  // Loop around appending to strFull
  for (int intX = 0; intX < 6; intX++) {
    strWork=String(myMac[intX], HEX);
    strFull.concat(strWork);
     // Serial.printf("MYMAC:%i %s\n", x, String(myMac[x], HEX));
    Serial.printf("MYMAC:%i :%s:\n", intX, strWork);
    Serial.printf("MYMAC_prog: %s\n", strFull);
  }
Serial.printf("concat loop strFull: %s\n", strFull);

String strManualFull="";
int bSeq=5;
strManualFull.concat(String(myMac[bSeq], HEX));
bSeq=4;
strManualFull.concat(String(myMac[bSeq], HEX));
bSeq=3;
strManualFull.concat(String(myMac[bSeq], HEX));
bSeq=2;
strManualFull.concat(String(myMac[bSeq], HEX));
bSeq=1;
strManualFull.concat(String(myMac[bSeq], HEX));
bSeq=0;
strManualFull.concat(String(myMac[bSeq], HEX));

Serial.printf("concat standalone strManualFull: %s\n", strManualFull);

String strNoVarFull;
strNoVarFull.concat(String(myMac[5], HEX));
strNoVarFull.concat(String(myMac[4], HEX));
strNoVarFull.concat(String(myMac[3], HEX));
strNoVarFull.concat(String(myMac[2], HEX));
strNoVarFull.concat(String(myMac[1], HEX));
strNoVarFull.concat(String(myMac[0], HEX));
Serial.printf("concat No Varaible strNoVarFull: %s\n", strNoVarFull);

String strStopShortFull;
strStopShortFull.concat(String(myMac[5], HEX));
strStopShortFull.concat(String(myMac[4], HEX));
strStopShortFull.concat(String(myMac[3], HEX));
strStopShortFull.concat(String(myMac[2], HEX));
strStopShortFull.concat(String(myMac[1], HEX));
// No zeroth value
Serial.printf("concat Stop short strStopShortFull: %s\n", strStopShortFull);

}
void loop() {
}
15:25:08.056 -> MYMAC:0 :4c:
15:25:08.090 -> MYMAC_prog: 4c
15:25:08.091 -> MYMAC:1 :11:
15:25:08.091 -> MYMAC_prog: 4c11
15:25:08.124 -> MYMAC:2 :ae:
15:25:08.124 -> MYMAC_prog: 4c11ae
15:25:08.157 -> MYMAC:3 :7:
15:25:08.157 -> MYMAC_prog: 4c11ae7
15:25:08.191 -> MYMAC:4 :86:
15:25:08.191 -> MYMAC_prog: 4c11ae786
15:25:08.226 -> MYMAC:5 :c5:
15:25:08.259 -> MYMAC_prog: <��?
15:25:08.259 -> concat loop strFull: <��?
15:25:08.291 -> concat standalone strManualFull: T��?
15:25:08.325 -> concat No Varaible strNoVarFull: l��?
15:25:08.359 -> concat Stop short strStopShortFull: c5867ae11

I have reproduced the problem here, with the full code and output shown. I am using the inbuilt wifiaddress function within Arduino which returns a 6 byte array. Arduino uses the "0" array first element standard, fine with that.

Note "concat standalone" shows progressively the string being built, until the last element.

Note "concat No Variable" also shows the issue, so the problem is not how the array is accessed.

Note "concat stop short" only address 5 elements of the array, and does not corrupt the output.

Also cast your mind back to the original code, where the array was accessed in reverse and still failed at the last element (#5) so this is not a issue with element 0 of the array. And also proves that the wifi function call for MAC is working.

The same problem happens outside a loop, so it's not variable scope.

So something is wrong with the Arduino IDE / functionality here.

Correcting the String to c-string for the printf() gives the correct output on a NodeMCU here.

Note that your code produces a compile error on Arduino IDE 1.8.18, the compiler options may have changed since then to allow for the mismatched type for printf().

@david_2018; I am using IDE 2.2.1.

@ALL: I have done some research and wanted to record the results for posterity.

I tried to shorten the loop to 5 values and add the sixth value outside the loop. Still corrupts.

// Try insequence convert
  Serial.println("Try local conversion myMac\n");
  String strLocalConv="";
  String strLocalWork="";
  byte myMacc[6];
  
  WiFi.macAddress(myMacc);
  char strLookup[] = "0123456789ABCDEF";
  for (int intCount = 0; intCount < 5; intCount++) {
    Serial.printf("MYMAC_prog_seq: %i\n", intCount);
    Serial.printf("MYMAC_prog_intcount: %i\n", myMacc[intCount]);
    int intFirstMac = myMacc[intCount]/16;
    int intSecondMac = myMacc[intCount]%16;
    Serial.printf("MYMAC_prog_firstMac: %i\n", intFirstMac);
    Serial.printf("MYMAC_prog_secondMac: %i\n", intSecondMac);

    strLocalWork.concat(strLookup[intFirstMac]);
    strLocalWork.concat(strLookup[intSecondMac]);
    
     // Serial.printf("MYMAC:%i %s\n", x, String(myMac[x], HEX));
    // Serial.printf("Prog MYMAC:%i :%s%s:\n", intCount, strLookup[myMac[intCount]/16], strLookup[myMac[intCount]%16]);
    Serial.printf("Prog MYMAC_prog: %s\n", strLocalWork);
  }
  int intFirstMacc = myMacc[5]/16;
  int intSecondMacc = myMacc[5]%16;
  strLocalWork.concat(strLookup[intFirstMacc]);
  strLocalWork.concat(strLookup[intSecondMacc]);
  Serial.printf("End of Prog: %s\n", strLocalWork);

19:48:36.664 -> 493253
19:48:36.664 -> 
19:48:36.664 -> Try unique ID2.
19:48:36.698 -> 
19:48:36.698 -> UniqueID: 00 00 00 00 00 07 86 C5 
19:48:36.731 -> Try local conversion myMac
19:48:36.764 -> 
19:48:36.764 -> MYMAC_prog_seq: 0
19:48:36.764 -> MYMAC_prog_intcount: 76
19:48:36.798 -> MYMAC_prog_firstMac: 4
19:48:36.831 -> MYMAC_prog_secondMac: 12
19:48:36.864 -> Prog MYMAC_prog: 4C
19:48:36.864 -> MYMAC_prog_seq: 1
19:48:36.897 -> MYMAC_prog_intcount: 17
19:48:36.897 -> MYMAC_prog_firstMac: 1
19:48:36.931 -> MYMAC_prog_secondMac: 1
19:48:36.965 -> Prog MYMAC_prog: 4C11
19:48:36.998 -> MYMAC_prog_seq: 2
19:48:36.998 -> MYMAC_prog_intcount: 174
19:48:37.031 -> MYMAC_prog_firstMac: 10
19:48:37.065 -> MYMAC_prog_secondMac: 14
19:48:37.065 -> Prog MYMAC_prog: 4C11AE
19:48:37.099 -> MYMAC_prog_seq: 3
19:48:37.131 -> MYMAC_prog_intcount: 7
19:48:37.164 -> MYMAC_prog_firstMac: 0
19:48:37.164 -> MYMAC_prog_secondMac: 7
19:48:37.198 -> Prog MYMAC_prog: 4C11AE07
19:48:37.231 -> MYMAC_prog_seq: 4
19:48:37.231 -> MYMAC_prog_intcount: 134
19:48:37.264 -> MYMAC_prog_firstMac: 8
19:48:37.298 -> MYMAC_prog_secondMac: 6
19:48:37.345 -> Prog MYMAC_prog: 4C11AE0786
19:48:37.345 -> End of Prog: ���?

I then tried to add just any old text at the end, avoiding any lookups (code missing but same result) So it's not the last entry in MyMacc.

So I fell back on the bad old days of populating strings element by element, and voila, that seems to work.

 // Try insequence convert
  Serial.println("Try local conversion myMac\n");
  char strLocalConv[20];
  String strLocalWork="";
  byte myMacc[6];
  
  WiFi.macAddress(myMacc);
  char strLookup[] = "0123456789ABCDEF";
  for (int intCount = 0; intCount < 6; intCount++) {
    Serial.printf("MYMAC_prog_seq: %i\n", intCount);
    Serial.printf("MYMAC_prog_intcount: %i\n", myMacc[intCount]);
    int intFirstMac = myMacc[intCount]/16;
    int intSecondMac = myMacc[intCount]%16;
    Serial.printf("MYMAC_prog_firstMac: %i\n", intFirstMac);
    Serial.printf("MYMAC_prog_secondMac: %i\n", intSecondMac);
    strLocalConv[intCount*2]=strLookup[intFirstMac];
    strLocalConv[(intCount*2)+1]=strLookup[intSecondMac];
    // strLocalWork.concat(strLookup[intFirstMac]);
    // strLocalWork.concat(strLookup[intSecondMac]);
    
     // Serial.printf("MYMAC:%i %s\n", x, String(myMac[x], HEX));
    // Serial.printf("Prog MYMAC:%i :%s%s:\n", intCount, strLookup[myMac[intCount]/16], strLookup[myMac[intCount]%16]);
    // Serial.printf("Prog MYMAC_prog: %s\n", strLocalWork);
    Serial.printf("Prog MYMAC_prog: %s\n", strLocalConv);
  }
  strLocalConv[12]=0;
  Serial.printf("Prog MYMAC_breakout: %s\n", strLocalConv);

20:12:18.412 -> Try local conversion myMac
20:12:18.445 -> 
20:12:18.445 -> MYMAC_prog_seq: 0
20:12:18.445 -> MYMAC_prog_intcount: 76
20:12:18.478 -> MYMAC_prog_firstMac: 4
20:12:18.512 -> MYMAC_prog_secondMac: 12
20:12:18.545 -> Prog MYMAC_prog: 4C
20:12:18.545 -> MYMAC_prog_seq: 1
20:12:18.578 -> MYMAC_prog_intcount: 17
20:12:18.578 -> MYMAC_prog_firstMac: 1
20:12:18.612 -> MYMAC_prog_secondMac: 1
20:12:18.645 -> Prog MYMAC_prog: 4C11
20:12:18.678 -> MYMAC_prog_seq: 2
20:12:18.678 -> MYMAC_prog_intcount: 174
20:12:18.712 -> MYMAC_prog_firstMac: 10
20:12:18.745 -> MYMAC_prog_secondMac: 14
20:12:18.778 -> Prog MYMAC_prog: 4C11AE
20:12:18.778 -> MYMAC_prog_seq: 3
20:12:18.812 -> MYMAC_prog_intcount: 7
20:12:18.845 -> MYMAC_prog_firstMac: 0
20:12:18.845 -> MYMAC_prog_secondMac: 7
20:12:18.878 -> Prog MYMAC_prog: 4C11AE07
20:12:18.912 -> MYMAC_prog_seq: 4
20:12:18.912 -> MYMAC_prog_intcount: 134
20:12:18.945 -> MYMAC_prog_firstMac: 8
20:12:18.978 -> MYMAC_prog_secondMac: 6
20:12:19.015 -> Prog MYMAC_prog: 4C11AE0786
20:12:19.048 -> MYMAC_prog_seq: 5
20:12:19.048 -> MYMAC_prog_intcount: 197
20:12:19.099 -> MYMAC_prog_firstMac: 12
20:12:19.125 -> MYMAC_prog_secondMac: 5
20:12:19.125 -> Prog MYMAC_prog: 4C11AE0786C5��������0123456789ABCDEF
20:12:19.167 -> Prog MYMAC_breakout: 4C11AE0786C5

**So it appears I need to write my own string handler to get the result I need rather than trust in native functions. ** :rage:

Where's is the the form for submitting faults requests, if you would be so kind?

More than likely github. Note that this bug (if it really is one) is not an Arduino bug but a bug in the ESP8266 core. So you need to find the correct github repository.

I don't think this is the case... you failed to post a minimal example that was showing what you were really trying to do.

what would this do on your Arduino

#include <ESP8266WiFi.h> // or #include <WiFi.h> on ESP32

void setup() {
  Serial.begin(115200);
  byte myMac[6];
  String macStr = "";
  WiFi.macAddress(myMac);
  for (byte i = 0; i < 6; i++) {
    macStr += String(myMac[i], HEX);
    if (i != 5) macStr += ':';
  }
  Serial.print("Mac Address String = ");
  Serial.println(macStr);
}

void loop() {}

Try with strLocalWork.c_str, %s is a c-string, not a String. (see reply #3)

@David_2018. I see the issue now, thanks for the direction. Problem resolved.

@J-M-L - println also seems to format the string for output correctly, in addition to the c_str() method.

If you use printf() you need to ensure the place holders’ types are correct. %s is for c-strings (null terminated char array) which is not the same thing as a String instance.

Glad you got it to work.

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