Go Down

Topic: String += not working (Read 453 times) previous topic - next topic

Napalm

Hi,

could someone please test this code on his arduino. It hangs on mine (Arduino Mega2560 R2).

Code: [Select]

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

void loop() {

  const String args[3] = {
    "foo", "boo", "baa"    };
  String result = "";
  Serial.println(result);
  result += args[0];
  Serial.println(result);
  result += args[1];
  Serial.println(result);
  result += args[2];
  Serial.println(result);
  Serial.println();
}


That codes hangs after a few seconds. BUT if you replace the
result +=
with
result = result +

everything works fine.
I wonder, as http://arduino.cc/en/Tutorial/StringAppendOperator shows that using += ist OK

regards
Mirko


Napalm

I tried a few more string-things and had strange results. Can someone confirm that code below, or is that a problem of my arduino?
(Uncomment only one of the lines in the source)

Code: [Select]

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

void loop()
{
  String str = ""; 
  for (int i=0; i<30; i++)
  {
    str = String(str +String(i,DEC));  // works fine
//    str = str +String(i,DEC);  // works fine
//    str = String(str) +String(i,DEC);  // crashes
//    str = String(str+ "-" +String(i,DEC)); // crashes
//    str = String(String(str) +String(i,DEC));  // crashes
//    str = str + "-" +String(i,DEC);  // crashes
    Serial.println(str);
  }
}

SurferTim

Code: [Select]
char outBuf[64];

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

void loop()
{
 for (int i=0; i<30; i++)
 {
     sprintf(outBuf,"This always works: %d",i);
     Serial.println(outBuf);
 }
}

Napalm

Ok, nice workearound, but does not explain why the above crashes or freezes the arduino.

SurferTim

One is addition (byte, integer, long). The other is concatenation (string).

It would appear the "+=" does not work with concatenation, only addition.

James C4S

If you look at WString.cpp in the Arduino core files, you will see that concatenation using += is implemented as concatenation.   

It works by allocating a buffer large enough to contain the old + new string, then cating it.  This appears to lead to memory fragmentation on ATmegas limited memory and stack environment.

Your workaround works or just treating all Strings as character arrays instead.  This results in much lower over head.  It does require you, as the programmer, to determine ahead of time what size the arrays should be.  Which, in such a limited memory environment, is actually a good idea.
Capacitor Expert By Day, Enginerd by night.  ||  Personal Blog: www.baldengineer.com  || Electronics Tutorials for Beginners:  www.addohms.com

Napalm

After changing my code not to use the String class anymore but use char arrays, i ran into another problem

Code: [Select]

void loop()
{
  char tx[100];
  long TestA = 1;
  word TestB = 1;
 
  sprintf (tx, "%d %d %d %d", TestA, 2, 3, 4);
  Serial.println(tx);

  sprintf (tx, "%d %d %d %d", TestB, 2, 3, 4);
  Serial.println(tx);
}


I would have expected the to outputs to be the same, but they are not.
It outputs the following two lines:

1 0 2 3
1 2 3 4

Can anybody explain this to me?
Isn't it possible to use a long or unsigned long with sprintf?

regards
Mirko




James C4S

#7
Dec 07, 2011, 03:33 pm Last Edit: Dec 07, 2011, 03:35 pm by James C4S Reason: 1
Capacitor Expert By Day, Enginerd by night.  ||  Personal Blog: www.baldengineer.com  || Electronics Tutorials for Beginners:  www.addohms.com

Napalm

OK, thanx for that info.
I did not know that as i never needed %ld before ;-)

regards
Mirko

James C4S

In that case, you should know that

%u is unsigned int
%lu is unsigned long
Capacitor Expert By Day, Enginerd by night.  ||  Personal Blog: www.baldengineer.com  || Electronics Tutorials for Beginners:  www.addohms.com

Go Up