Populate array of char array

I need to work with an array of char array, something like this:

// N text strings with a max length of 24 each
char mytext[][25] =
{
  "hello",
  "world"
};

There is a forum question that discusses how to create and iterate an array of char array but my question is how can I populate it dynamically as my list could change a few times and I need to repopulate the array.

hope it's clear

// N text strings with a max length of 24 each
char mytext[N][25]

surely?

Use the strcpy() function.

...R

mesihas:

// N text strings with a max length of 24 each

char mytext[][25] =
{
 "hello",
 "world"
};




How can I populate it dynamically as my list could change a few times and I need to repopulate the array.
// 2 text strings with a max length of 24 each
char mytext[2][25];
void setup()
{
  // Dynamically populate the list
  strncpy(myText[0], "hello", 25);
  strncpy(myText[1], "world", 25);
};

Or a bit more generic

// 2 text strings with a max length of 24 each
const byte maxSize = 25;
char mytext[2][maxSize];
void setup()
{
  // Dynamically populate the list
  strncpy(myText[0], "hello", maxSize );
  strncpy(myText[1], "world", maxSize );
};

What a nice function strncpy() is. Thanks for suggesting this.

"hello" must be a char[] so is this correct?:

 char[]  variableText = "hello"
  strncpy(myText[0], variableText, maxSize );

mesihas:
What a nice function strncpy() is. Thanks for suggesting this.

"hello" must be a char[] so is this correct?:

 char[]  variableText = "hello"

strncpy(myText[0], variableText, maxSize );

Yes. But if you ever have to copy something else into the variableText array make sure it is not more than 5 characters because since you didn't specify a length the compiler only reserved enough for "hello".

mesihas:
"hello" must be a char[] so is this correct?:

 char[]  variableText = "hello"

strncpy(myText[0], variableText, maxSize );

The syntax is wrong. The '[]' go after the name and you need a ';' at the end:

char  variableText[] = "hello";

It compiles without error.
Note: The second argument to strncpy() does NOT have to be a character array. Any address of a null-terminated list of characters will be acceptable. That's why passing a string literal ("like this") works.

johnwasser:
The syntax is wrong. The '[]' go after the name and you need a ';' at the end:

char  variableText[] = "hello";

It compiles without error.
Note: The second argument to strncpy() does NOT have to be a character array. Any address of a null-terminated list of characters will be acceptable. That's why passing a string literal ("like this") works.

I see.. thanks for pointing it, I understand the point but still not sure about the whole thing / which is the approach for when I want to:

  • Define an array at upper level and then be able to access the array whenever I want and change it.
  • Don't know the length of the strings I have to replace.
  • Don't know the size of the new array.

Sometimes the user interaction defines how the data is gonna be so it has to be flexible.

I find really hard to work with arrays in C as I coming from JavaScript/C#.
The bigger problems I found is when I need to work with arrays and change its values dynamically, it is really frustrating. It is clear that requires to learn C properly If I want to do things more complicates than turn the built in led on/off.

@John:
How does the compiler handle strncpy() when you defined a char array with 10 characters, like this:

void setup() {
  char first = 'f';
  char buf[10];
  char test = 'A';

  Serial.begin(9600);
  strncpy(buf, "123456789012345", 10);
  Serial.println(buf);
  Serial.println(first);
  Serial.println(test);
  Serial.println(strlen(buf));

}

void loop() {}

which yields output like:

1234567890
f
A
10

My question is: where does the byte for the null come from? I defined first and test just to see if they would get trashed in the process.

You might like to consider using pointers

char * anArray[8] = {"zero", "one"};  //an array of 8 pointers to strings with 2 defined

void setup()
{
  Serial.begin(115200);
  while (!Serial);
  printArray();
  anArray[0] = "longer text in the first position";  //change the text in level 0
  printArray();
  anArray[0] = "now shorter text";
  anArray[1] = "but this one is longer";
  printArray();
  anArray[0] = 0;
  anArray[1] = 0;
  anArray[7] = "nulled the values of the first two entries and added the last entry in the array";
  printArray();
}

void loop()
{
}

void printArray()
{
  for (int x = 0; x < 8; x++)
  {
    if (anArray[x] != NULL)  //only print levels where data exists
    {
      Serial.print(x);
      Serial.print("\t");
      Serial.println(anArray[x]);
    }
  }
  Serial.println();
}

I don't think that I have committed any programming sins here, but if I have then someone will surely point them out !

The compiler isn't doing what you expect. strncpy doesn't provide a null in this case, but because of the way the compiler laid out the variables on the stack, there's apparently a space with a zero in it. Here's my (very messy) experiment:

void setup()
{
  char first = 'f';
  char buf[10];
  char test = 'A';
  Serial.begin(115200);
  strncpy(buf, "123456789012345", 10);
  Serial.println(buf);
  Serial.println(first);
  Serial.println(test);
  Serial.println(strlen(buf));
  for (int lp=-2;lp<18;lp++)
    Serial.println((int)buf[lp]);
  int y=&first;
  Serial.println(y,16);
  int x=(int)buf;
  Serial.println(x,16);  
  int z=&test;  
  Serial.println(z,16);  
}

void loop()
{
}

So if there was an array of characters defined as a array of 300 or more or less characters and filled with nulls, char theThing [300] = {NULL};. Gives a reasonable sized character buffer that is null terminated.

You can put things in it, it stays null terminated.

When you want to clear the array you do the memset( theThing, NULL, 300 ); thing to set the buffer back to all NULL. Works well, last a long time.

Idahowalker:
So if there was an array of characters defined as a array of 300 or more or less characters and filled with nulls, char theThing [300] = {NULL};. Gives a reasonable sized character buffer that is null terminated.

You can put things in it, it stays null terminated.

When you want to clear the array you do the memset( theThing, NULL, 300 ); thing to set the buffer back to all NULL. Works well, last a long time.

NULL is intended to be used only in a pointer context (i.e., "null pointer"), not as in a null-terminated string. In other words, it's poor style to use NULL where you could use a plain 0 or '\0'.

And if you need to set a C string to zero length, all you need to do is set the first character to null. Ta-da! Zero length!

And if you need to set a C string to zero length, all you need to do is set the first character to null

Breaking your own rules there I see :slight_smile:

Using a NULL when you

could use a plain 0 or '\0'.

Naughty boy

christop:
NULL is intended to be used only in a pointer context (i.e., "null pointer"), not as in a null-terminated string. In other words, it's poor style to use NULL where you could use a plain 0 or '\0'.

And if you need to set a C string to zero length, all you need to do is set the first character to null. Ta-da! Zero length!

And, on this site, I get, complaints that:

it's poor style to use a plain 0 or '\0' where you could use a NULL.

shrug

UKHeliBob:
Breaking your own rules there I see :slight_smile:

Using a NULL when you Naughty boy

And when I post code where I use '\0' I get complain, complain, complain. Either way, it produces complaints.

Idahowalker:
And when I post code where I use '/0' I get complain, complain, complain. Either way, it produces complaints.

No wonder, since it's wrong. :slight_smile: It's '\0'.

I've only been programming in C++ and working with MCU's for 3ish years and I am still learning.

More complaints. Where where you guys when they were complaining, on this site, about my use of '\0' and was being badgered to use NULL instead of '\0'?

My wife is happy though.

UKHeliBob:
Breaking your own rules there I see :slight_smile:

Using a NULL when you Naughty boy

Nope. "NULL" in code, as in the preprocessor macro, is only for null pointers. Other uses of the word "null" outside of that can be used in other contexts like "null terminator", meaning a zero character (aka '\0') at the end of a string. No rules broken here.

Idahowalker: Any complaints of you using '\0' for a string terminator (which is a correct usage of '\0') are null and void.

:slight_smile:

Edit to add: C++ actually prefers nullptr over NULL (nullptr is type safe while NULL is not, among other things). NULL exists for backward compatibility with C.