Error: invalid array assignment

One of my hobbies is getting into Arduino programming projects that are way over my head. I have built an art machine involving 3 stepper motors, 3 servos, and even a color detector, and I have each of those operating as I had hoped (many error messages later.) I am a decent, not expert Arduino c++ programmer.

Now I am trying to convert individual letters of the alphabet into 25 character char strings that, broken into groups of fives and stacked, will allow me to represent each letter in white and red marbles in a 5 X 5 grid.

I have been messing around with formatting brackets, parentheses, this and that and chasing error messages on this forum for so long that even shy me finally breaks down and asks for help.

My current error message, one of several, is:

/Users/gordo/String_Play/String_Play.ino: In function 'void displayFont(char)':
/Users/gordo/String_Play/String_Play.ino:28:17: error: invalid array assignment
tempstr = "rwwwrrrrrrwrwrwwrwrwwwrww";
^~~~~~~~~~~~~~~~~~~~~~~~~~~
/Users/gordo/String_Play/String_Play.ino:31:17: error: invalid array assignment
tempstr = "wwrrrwrwwrwwrrrwrwwrwwrrr";
^~~~~~~~~~~~~~~~~~~~~~~~~~~
etc. for each subsequent line

My code as it currently stands, called by ā€œ displayFont(alphatext[i]);ā€ in Loop()

void displayFont(char letter){ //letter is single lower case letter
  char tempstr[26];       //create string 26 characters long
  
  switch(letter){        // depending on letter
    case 'a':            //if it is "a"
      tempstr = "rwwwrrrrrrwrwrwwrwrwwwrww"; //Assign this string ERROR!
      break;             // if it wasn't "a"
    case 'b':            // try "b" etc.
      tempstr = "wwrrrwrwwrwwrrrwrwwrwwrrr";
      break;
    case 'c':
      tempstr = "wrrrwwwwwrwwwwrrwwwrwrrrw";
      break;
    case 'd':
      tempstr = "wwrrrwrwwrwrwwrwrwwrwwrrr";
      break;
    case 'e':
      tempstr = "wrrrrwwwwrwwrrrwwwwrwrrrr";
      break;
    case 'f':
      tempstr = "wwwwrwwwwrwwrrrwwwwrwrrrr";
      break;
    case 'g':
      tempstr = "wrrrwwrwwrwrrwrwwwwrwrrrw";
      break;
    case 'h':
      tempstr = "wrwwrwrwwrwrrrrwrwwrwrwwr";
      break;
        
  }
  for (int ii = 0; ii < 25; ii = ii + 5){ // this part is included for your
                                         // amusement. I haven't gotten past
    for (int jj = 0; jj < 5; jj++){      // the part above so I haven't
        char tempLetter = tempstr[ii + jj]; // tested this yet.
        if (tempLetter == 'w'){  
          Serial.print (" ");//Eventually: Feed a white marble to the tray
        }
        else if (tempLetter == "r"){
          Serial.print("*"); //Feed a red marble to the tray
        }
        Serial.println(); //dump the tray in the 5 X 5 display
    }
  }      // and using the serial monitor the letters will appear          
}        // upside down. The marbles will stack bottom to top.

Program runs on an Arduino Mega, I’m using Arduino IDE 2.3.6

You can assign values to character arrays that way. Do an internet search for the functions strcpy() and strncpy().

Show all the code in code tags.

1 Like

Much more common to store a 5x5 font as five bytes with five bits each. A 1 bit representing one color, the 0 bit the other.

If you want to stay with the char array, then make an array of the entire font and assign a pointer to the element (character) you want.

strcnpy(tempstr, "rwwwrrrrrrwrwrwwrwrwwwrww", sizeof (tempstr));
1 Like

Thank you! I took your advice and the code is now compiling with no complaints.

This worked! My code is compiling now with no complaints.

replace it with

const char *tempstr = NULL;

No!
That simply creates a (NULL) pointer but allocates no space for the character string.

1 Like

Exactly.

He uses string constants, they are already ā€œallocatedā€œ. No point to malloc() and strcpy();

If your strings are constants, then just assign and forget :slight_smile:

1 Like

strcpy has evolved to strncpy, which was still bad, and now everybody uses strlcpy() :).

It is more safe.

1 Like

No, not "everybody". One must pay attention, regardless. There remain unfortunate surprises.

For fun, predict what this program was intended to print, and explain what it actually prints (at least on Arduino Uno R3, IDE 1.8.19).

char t[]="test string";
char n[3]={0};

void setup() {
Serial.begin(115200);
while(!Serial) delay(1);
Serial.println("Starting");
strlcpy(n,t, sizeof (t));
Serial.println(n);
}

void loop() {
}

Didn’t you get a warning here?

Classic buffer overrun.

Will print lots of garbage, i think. You MAY damage the memory (depending on the size of .bss section). If the .bss is large enough then it will print the phrase above plus some garbage.

If .bss is small, then god knows what will happen. On ESP32 (has MMU) it will be memory access exception. On UNO (ancient CPU, afaik) probably no exception

Bit of offtopic (however it is about strings, arrays, assignments and printf!):

#include <stdio.h>
#include <math.h>

                        #define o(x,o)x##o
                                        char X[
                                             1<<16
                      ][4],Z[1<<28],*N=         X[1]
                  ,*P=Z,*H,A[12];char*C(int       i,o(u
               ,nsigned)             x){char*B      =0,*
             D;if((x                     >>16)||      0==*
           (B=X[x        ])){int a,b        =(sqrt     (x)+
          0.5),      c=x-b*b;D=C(0,65535      &b);o     (spr
        ,intf      )(A,"%s"       "*%s%c%"     "s",D     ,D,c
        ?c<0     ?45:43               :0,C(0    ,c<0?    -c:c
       ));B     =B?a=       *N,b=       N[1],    c=N[2    ],*B
      =a+!b    -90?a     =='z'?65:a+     1:(b     ='z'    -b?b
      -90?    b%64+     65:97   :(c=c    ?'z'-    c?-~     c:48
     :'a',    65),     'j')      ,B[1     ]=b,    B[2]     =c,o
     (prin    ,tf)    (",%"    "s=%s"    ,B,A)    ,(N=     B):A
     ;;}o(    ret,     urn)     i>0     ?P+=o     (spr    ,intf
      )(P,    ",%s"    ,B):B           ;}int     main     (){;
      ;int     a,i=     **X=Z[1     ]='a',c     ,n=0;    *X[1]
       =98;     for(      printf("#inclu"      "de "    "<st"
       "dio"     ".h>"        "\nint"        " a;i"     "nt"
        " ma"     "in()"                   "{int"     " b="
         "-~a")      ;i>3&&P-           Z+33<1<<     28;C(
           i,a))       for(a=i=0;i<4&&0<=(c=       o(get,
            char)(         ));n++)((char         *)&a)[
              i++]=c;                         H=P;C(1
                ,n);*H++=                 0;printf(
                   ",Z[]={%s};fwrite(Z,b,%s,std"
                        "out);}\n",Z+1,H);}

The code above is ANSI C code, can be compiled by anything.

Once compiled you can use it like this:

prog.exe < SomeText.txt >Result.c

File SomeText.txt is a text file. Any text. For example, text of the programm above.

The Result.c is a compilable .c code, which does not use literals nor strings and displays content of the SomeText.txt

Generated Result.c is as easy to read as the code above.

Cool code example, thanks.

No, nothing, and that was the point (at least with that version of avr-gcc).

It is a very common sort of careless mistake, made by not paying attention, and strlcpy does not protect from the potentially disastrous consequences.

GCC 12 will issue a warning:

stinky.cpp:9:10: warning: ā€˜size_t strlcpy(char*, const char*, size_t)’ writing 12 bytes into a region of size 3 overflows the destination [-Wstringop-verflow=]
    9 |   strlcpy(n,t, sizeof (t));
      |   ~~~~~~~^~~~~~~~~~~~~~~~~
stinky.cpp:5:6: note: destination object ā€˜n’ of size 3
    5 | char n[3]={0};
      |      ^