2 dimensional array of chars.

If I have a 1 dimensional array of chars

char command[20];

Which contains a set of chars which are zero terminated.

So

command[0]="H" command[1]="E" command[2]="L" command[3]="L" command[4]="O" command[5]=(char)0

I can refer to that as command so Serial.println(command); works and prints HELLO

Now the problem:

If I have a 2 dimensional array of chars

char commands[20][5];

Which contains a set of chars which are zero terminated.

So

commands[0][0]="H" commands[1][0]="E" commands[2][0]="L" commands[3][0]="L" commands[4][0]="O" commands[5][0]=(char)0 commands[0][1]="W" commands[1][1]="O" commands[2][1]="R" commands[3][1]="L" commands[4][1]="D" commands[5][1]=(char)0

How can I refer to a group in that

Serial.println(commands[][0]); obviously can't work and Serial.println(commands[0]); obviously can't work because it wouldn't know which element it was talking about......

Is there a way ????

Unless you've got very peculiar requirements, I'd say you've got your array indices the wrong way round.

commands[0][0]="H" commands[0][1]="E" commands[0][2]="L" commands[0][3]="L" commands[0][4]="O"

If it makes it easier then I could swap them but they are basically just chars in a grid....

char commands[20][5];

should be

char commands[20][6];

to have place for the '\0' Needed if you want to use println()

and single quotes!!!

commands[0][0]='H' commands[0][1]='E' commands[0][2]='L' commands[0][3]='L' commands[0][4]='O' commands[0][5]=0

Sorry - Rob is correct - I missed the double quotes.

Thanks, I just wrote the above using copy and paste in order to populate the array. The array is populated ok at the moment so

if I have the array as per your spec (which just means swapping the indices round) how do I actually print HELLO?

Thanks for taking the time.

You can use them that way, but you need to use them like you entered them.

for(int x=0; x<20;x++)
{
   if(commands[x][0] == 0) break;
   Serial.print(commands[x][0]);
}

Now, when you look at the alternative, doesn’t AWOL’s plan sound better?

Sorry if there was any confusion here…

I will swap the indices round happily and the array does have the correct values in it…

the following code shows me that:

  Serial.println("\n>>>>>");
  for (i = 0; i < numcommands+1; i++) {
    Serial.print(i);
    Serial.print(" = '");
    for (int k = 0; k < 20; k++) {  
      Serial.print(commands[k][i]);
    }
    Serial.println("'");
  }
  Serial.println(">>>>>\n\n");

So with the indices swapped around which I will happily do…

can I refer to one string in the same way that I would if it were 1 dimensional

commands[0]='H'
commands[1]='E'
commands[2]='L'
commands[3]='L'
commands[4]='O'
commands[5]=0

Serial.println(commands)

Thanks

If you put proper code tags around that, it'll remove the italics, and start to make sense.

If you switch the array dimensions around (and use the code tags) as AWOL suggests, then you can use these:

Serial.println(commands[0]);
Serial.println(commands[1]);

SurferTim: If you switch the array dimensions around (and use the code tags) as AWOL suggests, then you can use these:

Serial.println(commands[0]);
Serial.println(commands[1];

Thanks, I will swap the indices around and check....

Thanks everyone for your help it is appreciated.

I was writing a parsing function which handles double quotes too. It now works :slight_smile:

I’m new to C++ normally programming in assembler or Pascal (delphi)

char commands[5][20];

byte getwords(char s[30]){
  byte i=0;
  byte pos=0;
  byte numcommands=0;
  boolean inquotes=false;
  for (i = 0; i < 6; i++) {
    for (pos = 0; pos < 20; pos++) {
      commands[i][pos]=(char)0;
    }
  }
  pos=0;
  for (i = 0; i < 30; i++) {
    if (s[i]==NULL){break;}
    if (s[i]==(char)34){
      inquotes=!inquotes;
    } else {
      if ((s[i]==(char)32) && !inquotes){
        pos=0;
        numcommands++;
      } else {
        commands[numcommands][pos++]=s[i];
      }
    }
  }
  return numcommands+1;
}

I am trying to get my head round C++, is this written in the best way? Can anyone see anything that is best done another way?

Thanks for looking.

BTW, there is a quick way to initialize that array.

char commands[2][16] = {
   "Hello ",
   "world!"
};

void setup() {
   Serial.begin(9600);
   Serial.print(commands[0]);
   Serial.println(commands[1]);
}

void loop() {
}

Thanks, I actually know that but I was trying to make sure it was very obvious what I was doing.

just looking for quick and/or smaller ways of doing stuff.

  for (int i = 0; i < 6; i++) {
    for (int k = 0; k < 20; k++) {
      commands[i][k]=(char)0;
    }
  }

As an example: To empty the array, is there an easier/smaller way of doing this?

You could use memset, but if all you're using is string functions (strcmp, strcat, strlen etc) then all you need to do is set the first element of each string to null '\0'.

cowasaki: but they are basically just chars in a grid....

That is actually incorrect.

Multidimensional arrays are only multidimensional in concept. In actuality, they are stored in memory as a single dimensional array, with some indexing math being handled for you behind the scenes to give the appearance of multidimensionality.

jraskell:

cowasaki: but they are basically just chars in a grid....

That is actually incorrect.

Multidimensional arrays are only multidimensional in concept. In actuality, they are stored in memory as a single dimensional array, with some indexing math being handled for you behind the scenes to give the appearance of multidimensionality.

I think the word "basically" is enough there!

You get a value from the grid by giving it the 2 indices. The important thing I didn't know was that IF they were indexed the other way then it would have worked. This was the missing bit of information which people helped with and I thank them for that. I did explain my background is not in C++ but assembler and Pascal. Some of C's concepts appear a little strange unless you are used to them.

Actually, seeing memory as a one-dimensional series of storage bytes is a concept as well. We do not want to know how multiplexing and adressing is handled behind the scenes ;)

BTW: if the lengths of those strings is very different, you might benefit from

char* commands[2] = { "Hi", " world !!!!!"};

void setup() {
   Serial.begin(9600);
   Serial.print(commands[0]);
   Serial.println(commands[1]);
}

void loop() {
    commands[1][1] == 'w'; // this is true and valid
}

In this case, you really do not have a 2 dimensional grid.

cowasaki:
The important thing I didn’t know

That is directly tied to my statement.

Understanding the ‘actuality’ of how arrays work (of any dimension) is the same as knowing that important thing you didn’t know.

michael_x:
Actually, seeing memory as a one-dimensional series of storage bytes is a concept as well.

Actually, it is not. Memory IS a one-dimensional series of storage bytes with linear addressing, even at the hardware level. Nothing conceptual about that.

Do you know what the difference is between:

char* const chrptr = (char*)malloc(2);

and

char array1[2];

It’s really nothing more than a syntactically different declaration. Functionally, they’re identical because you can use them both in exactly the same manners. The following code is perfectly valid:

  chrptr[0] = 't';
  chrptr[1] = 0;
  
  *array1 = 't';
  *(array1+1) = 0;

Arrays ARE const pointers to a block of memory (and thus can also be treated as const pointers).
And conversely, const pointers to blocks of memory can be treated exactly like Arrays.

michael_x:
We do not want to know how multiplexing and adressing is handled behind the scenes

That’s unfortunate. There are definite benefit to having such knowledge. For example, if I were to give you this:

char array[10][10] =
  {
    "asdfqwera",
    "qadwdghsd",
    "qsdvthefd",
    "kdiejksuw",
    "djuekwjsd",
    "dujehsgcd",
    "wujdhskdf",
    "dujwhajsv",
    "dujwkdidj",
    "idkwjushc"
  };

And ask you to count the number of ‘s’ in that array, an array syntax method would look something like this:

  int count = 0;
  for(int x = 0; x < 10; x++)
    for(int y = 0; y < 10; y++)
    {
      if(array[x][y] == 's') count++;
    }

But this, would also be a valid method, utilizing a pointer and pointer arith:

  int count = 0;
  char* p = (char*)array;
  for(int x = 0; x < 100; x++)
    if(*p++ == 's') count++;

There is more than just a syntactic difference there. The latter method utilizing pointers is about 20% faster than the former method using array indexes.

I am picking C++ up but I’ve basically not used C until recently. I grew up with assembler and Pascal with BASIC years before that, I’ve been programming since the VIC20! in 1982 :).

There are lots of things that I’m picking up as I go along. char arrays are something that Pascal DID use but all recent versions use more powerful “strings”.

Manipulation of “char arrays” C++ style is my biggest headache at the moment. The Arduino sub-set of commands does not include the ones I would pick to use out of the full implementation of C++ I think…

This is my current mental work out :slight_smile:

I have two char arrays

commands[0] = “WRITE”

whilst

commands[1] = either an integer stored as a char array OR a “%” sign followed by a number with the number referring to an integer array nums[100]

SO

I need to take %0 to %65535 and remove the “%” and get the value of the rest of it so 0 to 100.

In BASIC for example I could use: a=INT(mid(s$,2,len(s$)-1)) whilst in Pascal something similar and in assembler I’d work backwards subtract ASC"0" and multiply each number by it’s column so units, tens, hundreds etc…

What would peoples take be on this as a code snippet using C++ ??