Trying to print elements of a String array

Good afternoon, everyone. I am currently trying to print elements of an array of String objects and having some difficulty. I have searched the forums for a solution to this problem but have not found someone posting about the same problem I am facing. Also, I have seen some posts where the proposed solution is exactly what is not working in my case. Any help would be greatly appreciated.

I have reduced the problem down to four lines of code (with comments for explanation of the problem), for example purposes. All of the below example code takes place inside the setup() function.

	//For testing only
	String Things[2];			//Declare array of Things
	Things[0] = "First thing";	//Populate the first element with a string
	
	Serial.print("First element in the array is called: ");
	Serial.println(Things[0]);	//Print the first element in the array. This line prints blank

I have also attached a screenshot of my code, in case it is easier to see. Thank you all so much for taking a look. If I can answer any additional questions, please let me know and I will provide as much information as I can.

Best Regards,
Donovan

Issue_06-20-16.JPG

String is a class not a type.

When you write String XYZ = "abc"; you are creating an instance of the class Sting and calling a constructor to inutile the value to "abc"

When you do String things[2] you don't call any constructors. the type should in theory be String but note sure this works with arduino IDE

Try declaring

String things[2] = {String("1st string"), String("2nd string")};

And then print the element at index 0

Do you get better result?

I’m unable to reproduce your problem. This

void setup() {
  Serial.begin(115200);
  String Things[4];
  Things[0] = "First thing";
  Things[1] = "Second thing";
  Things[2] = "Third thing";
  Things[3] = "Fourth thing";

  for (byte idx = 0; idx < sizeof(Things) / sizeof(Things[0]); idx++) {
    Serial.print("Things[");
    Serial.print(idx);
    Serial.print("] = '");
    Serial.print(Things[idx]);
    Serial.println("'");
  }
}
void loop() {}

as well as this

void setup() {
  Serial.begin(115200);
  String Things[] = { "First thing", "Second thing", "Third thing", "Fourth thing"};
  for (byte idx = 0; idx < sizeof(Things) / sizeof(Things[0]); idx++) {
    Serial.print("Things[");
    Serial.print(idx);
    Serial.print("] = '");
    Serial.print(Things[idx]);
    Serial.println("'");
  }
}
void loop() {}

gives

Things[0] = 'First thing'
Things[1] = 'Second thing'
Things[2] = 'Third thing'
Things[3] = 'Fourth thing'

So where is the problem (besides using Strings at all) ?

It is in the code that you are not showing… :wink:

Whandall is giving you some great advice: Dump the String class. His code, which works perfectly, compiles to 3940 bytes. The code below, which duplicates his output, but without using the String class, compiles to 2496 bytes.

void setup() {
  Serial.begin(115200);
  char Things[4][13] = {
  "First thing",
  "Second thing",
  "Third thing",
  "Fourth thing"};

  for (byte idx = 0; idx < sizeof(Things) / sizeof(Things[0]); idx++) {
    Serial.print("Things[");
    Serial.print(idx);
    Serial.print("] = '");
    Serial.print(Things[idx]);
    Serial.println("'");
  }
}
void loop() {}

The String class uses more memory because it has to bring the trailing wheels along with it. Stick with char arrays for string.

Thanks everyone. Right now I'm away from my Arduino but I'll definitely try to implement some of your suggestions. I'm particularly intrigued by Whandall's solution working. I'm sure you are correct that it's something in my code that I'm not showing that's the problem, but it's mind boggling!

I purposely moved my four lines into the setup() function so that it would run first without potentially being affected by anything downstream, and I tried to use a fully contained block that shouldn't need any other code to work (besides Serial.begin() obviously).

I think when I start again tomorrow, I'll write a new program that is for the sole purpose of testing out your solutions. I would rather use the String instead of char arrays only because I have a relatively large program now and would have to completely re-do the data structure if I were to switch, but I will use the char array if it comes to it.

I'm a mechanical engineer so learning the finer points of programming wasn't something I needed for my degree, but it's definitely something that interests me! I'll post an update when I get my results tomorrow.

Best Regards,
Donovan

econjack:
Whandall is giving you some great advice: Dump the String class. His code, which works perfectly, compiles to 3940 bytes. The code below, which duplicates his output, but without using the String class, compiles to 2496 bytes.

interestingly on my uno it compiles to 2190 bytes.

I thought I would be smarter and actually you going one step further to save memory because econjack is statically allocating 13 bytes for each string to accommodate the largest string. that means some of this memory is lost

You get the same behavior is you declare your Things as a list of pointers to char

void setup() {
  Serial.begin(115200);
  char* Things[4] = {
  "First thing",
  "Second thing",
  "Third thing",
  "Fourth thing"};

  for (byte idx = 0; idx < sizeof(Things) / sizeof(Things[0]); idx++) {
    Serial.print("Things[");
    Serial.print(idx);
    Serial.print("] = '");
    Serial.print(Things[idx]);
    Serial.println("'");
  }
}
void loop() {}

But interestingly enough, now the code is only 2 198 bytes :slight_smile:

the 8 extra bytes is the sizeof(Things) (the 4 pointers to the strings) and the strings are using memory outside

if you add a statement

    Serial.println(sizeof(Things));

in the code, you’ll see that in econjack’s code, the Things size is 52 ==> 4x13 makes sense and if you look at the strings he uses, they have 11 and 12 characters, so use up 12 and 13 bytes… so by statically allocating the array to 13 bytes, econjack’s code only miss-use 2 bytes in memory

Now if you had really big differences in string sizes, then building an array of pointers rather than all strings of the same size would probably end up being a better bet.

I would not like the RAM usage of this version.

void setup() {
  Serial.begin(115200);
  char* Things[4] = {
  "First thing",
  "Second thing",
  "Third thing",
  "Fourth thing"};

  for (byte idx = 0; idx < sizeof(Things) / sizeof(Things[0]); idx++) {
    Serial.print("Things[");
    Serial.print(idx);
    Serial.print("] = '");
    Serial.print(Things[idx]);
    Serial.println("'");
  }
}
void loop() {}
2.218 Bytes (7%)
272 Bytes (13%) RAM

This uses less RAM and a little more code.

const char pmT1[] PROGMEM = "First thing";
const char pmT2[] PROGMEM = "Second thing";
const char pmT3[] PROGMEM = "Third thing";
const char pmT4[] PROGMEM = "Fourth thing";
const char * const pmTab[] PROGMEM = { pmT1, pmT2, pmT3, pmT4 };

void setup() {
  Serial.begin(115200);
  for (byte idx = 0; idx < sizeof(pmTab) / sizeof(pmTab[0]); idx++) {
    Serial.print(F("Things["));
    Serial.print(idx);
    Serial.print(F("] = '"));
    Serial.print((__FlashStringHelper*)pgm_read_word(pmTab+idx));
    Serial.println(F("'"));
  }
}
void loop() {}
2.232 Bytes (7%)
200 Bytes (9%) RAM

Indeed Whandall

we often overload the 2k of RAM of our small ATMega328P while we have 32 KBytes of flash often not fully used.

A general note to mention that Version 1.0 of the Arduino IDE introduced the F() syntax for storing strings in flash memory rather than RAM.

This is pretty useful to save precious RAM space when you have large amount of static text to send to a LCD for example

I use it also often for my debugging statements to ensure I don't clutter my RAM with debug strings and influence the program. the way to do this

#define DEBUG
  ....


#ifdef DEBUG
Serial.println(F("This string is stored in flash memory"));
#endif /* DEBUG */

Whandall; J-M-L: Agree with suggestions. All I had hoped to do was show the OP: 1) that not using the String class can save memory, and 2) indirectly show that there are alternative ways of producing the same results. I should also point out that most of the methods used in the String class have char array function counterparts str*() and mem*():

http://www.tutorialspoint.com/c_standard_library/string_h.htm

There is some overlap between the str*() and mem*() functions. Often, the mem*() functions leave out some of the error checking and, hence, may be a tad bit smaller/faster.