Cambiar contenido de cadena dentro de un switch case

Hola, estoy haciendo un programa y en una parte me he quedado atascado y no veo el problema, necesito cambiar el texto en un array segun una condicion, el caso es que al principio del programa declaro el array y luego dentro de cada condicion del switch case cambio ese texto por otro, pero no lo hace y no veo porque.

Primero pense que al poner char delante de la cadena lo interprete como otra variable diferente asi que lo quite, entonces salia un error de que habia un cambio de string a char no aceptado asi que quite las comillas " y puse ’ , bueno he probado 1000 maneras y no veo el porque, os adjunto el codigo a ver si vosotros veis algo que me haga ver la luz.
Si pongo el monitor serial veo como entra dentro del CASE y envia correctamente el mensaje por el puerto serie, asi que descarto el problema de que no entre.

Gracias

#include <SoftwareSerial.h>      // Libreria para gestionar puerto serie virtual

SoftwareSerial mySerial(10, 11); // RX, TX
char textString[20] = "esperando mensaje";
char dato;

void setup() {
Serial.begin(9600);     // velocidad puerto serie hardware
mySerial.begin(9600);   // velocidad puerto serie virtual
}

void loop() {
  // put your main code here, to run repeatedly:
 if (mySerial.available()){      
     dato= mySerial.read();
     Serial.print("dato= ");
     Serial.println(dato);                                                                     
     Serial.write(mySerial.read());
  }
  if (Serial.available()){
     while(Serial.available()) {
     mySerial.write(Serial.read());
  }
     mySerial.println();
  }
   
     switch (dato) {                 // En funcion de la letra recibida actuamos sobre las salidas de los motores
    case '1': 
        {char textString[20] = "mensaje 1";
        Serial.print("m1");}
      break;
    case '2': 
        {char textString[20] = "mensaje 2";
        Serial.print("m2");}
      break;
    case '3': 
        {char textString[20] = "mensaje 3";
        Serial.print("m3");}
      break;
    case '4': 
        {char textString[20] = "mensaje 4";
        Serial.print("m4");}
      break;          
    default: 
        {char textString[20] = "Error mensaje";}
    break;
  }
  
  for (int y=0;  y<20;  y++){
    Serial.write(textString[y]);
   }
   Serial.println("");

   
}

Solución rápida: usar String con sus pros y contras recientemente comentados en el foro: ¿Qué problemas dan los objetos de tipo String?

Voy a tratar de explicar un poco de qué va esto de las "cadenas de C" que ha "heredado" C++ (sepan que "Arduino" es C++). Las cadenas de C son en realidad un array de char. Tengamos como ejemplo la declaracion:

char cadena1[] = "12345";

Los corchetes nos están indicando que estamos declarando un array sin indicar el tamaño. El compliador le asignará el númeo mínimo de elementos necesarios para guardar la cadena con la que se inicializa. ¿Cuántos elementos tendrá el array del ejemplo? Pues ni más ni menos que 6. ¿Seis? Sí, seis. El tamaño de la cadena es de cinco caracteres más el carárter nulo. El carácter nulo no es más que un char (o byte) cuyo valor es cero y que "delimita" el final de la cadena. Dicho de otra manera, una cadena en C es una serie consecutiva de bytes que "se da por finalizada" cuando uno de ellos vale cero. Hay que tener bien claro dos cosas, se necesita un char más para guardar el final de la cadena, y que una cadena finalice no quiere decir que el array tenga como tamaño el de la cadena más uno, puede tener un tamaño mayor aunque el resto de bytes no formen parte de la cadena (los que estén después del carácter nulo, ya que estarán pero no se consideran parte de la cadena).

char cadena1[] = "12345"; // Se le asigna automáticamente un tamaño de 6 elementos (5 para guardar 12345 y uno más para el carácter nulo)
char cadena2[5] = "12345"; // El compilador da error porque necesita que el array sea, como mínimo, de 6 elementos
char cadena3[6] = "12345";  // Bien, se necesitan mínimo 6 elementos
char cadena4[10] = "12345"; // Bien, aunque con sólo 6 elementos tendría, los otros 4 no se usan (por ahora)

Aviso que en C, Arduino y C++ no es lo mismo 3 que '3' que "3". Lo primero es el valor numérico tres (en base 10), lo segundo es el carácter ascii cuyo valor numérico (en base 10) es 51 (ver en una tabla ascii, buscar en Internet) y lo último es array de dos caracteres, el primero tiene como valor numérico el 51 y el segundo como valor numérico el cero (el famoso terminador de la cadena). Así que podríamos definir la cadena "12345" por sus valores numéricos o por los carácteres ascii "sueltos". Prueben el ejemplo siguiente a ver que aparece por el monitor serie:

char cadena1[] = {49, 50, 51, 52, 53, 0};
char cadena2[] = {'1', '2', '3', '4', '5', 0};

void setup() {
    Serial.begin(9600);
    while (!Serial)
        ;
    Serial.print("Valor de cadena1: ");
    Serial.println(cadena1); // Muestra 12345
    Serial.print("Valor de cadena2: ");
    Serial.println(cadena2); // Muestra 12345
}

void loop() {
}

En ambos casos he terminado las cadenas con un cero (el carácter nulo). Si prueban a quitar ese último elemento a ambos arrays verán que las cadenas ya no terminan ahí y continúan con los datos de las variables que se encuentren alojadas en memoria a continuación de los arrays, mostrando "basura". Aveces "no da problemas" porque justo el valor de la memoria que hay a continuación del array es cero, pero eso es "suerte", de la mala ya que no vemos que hay algo mal.

Ya debemos de tener claro (o no) que una cadena de C no es más que un array de bytes donde el último ha de ser cero (para considerarse una cadena de C). Bien, pues un array en C se puede tratar como un puntero al primer elemento del array (¡Punteros! ¡Sálvese quien pueda!). De hecho se podría definir de ambas maneras:

char cadena1[] = "12345";
const char *cadena2 = "12345";

Lo del const es para que el compilador no se queje diciendo algo de "una cadena constante". Así que le decimos que está apuntando a algo constante porque se supone que la cadena a la que apunta no se puede modificar (se supone, pero bajo ciertas circunstancias sí que se puede, pero no lo recomiendo hacerlo ya que depende el hardware y puede tener efectos "colaterales").

¿Cuál es la diferencia entre uno y otro? Digamos que cadena1 es un array que se crea en memoria y se inicializa con una copia de los valores indicados. Mientras que cadena2 es un puntero a un array que apunta a un array con la cadena indicada y en este caso se supone que el contenido del array no se puede modificar ya que no se inicializa con una copia de ella, sino que apunta a ella y se supone que la cadena es una constante. Aparte de eso, cadena1 es la referencia al array y no se puede modificar (sólo podría ser modificable lo que contiene) mientras que cadena2 es la referencia a un puntero y es el puntero el que "apunta" al array, con lo que se puede modificar "a donde apunta" y hacer que apunte a otro array (no sólo cambiar los datos del array). Así que hay que diferenciar entre "el que tiene los datos" y "el que apunta a los datos". Este último el dato que tiene es "dónde están los datos" y esto es lo que se conoce como puntero. Menudo galimatías. Pero para "verlo" un poco ¿más claro? veamos el "tamaño" en bytes de las variables cadena1 y cadena2, es decir, lo que cada variable "gasta" de memoria para almacenar sus datos, así como la longitud de sus cadenas.
char cadena1 = "12345";
const char* cadena2 = "12345";

void setup() {
    Serial.begin(9600);
    while (!Serial)
        ;
    Serial.print("Tamaño de la variable cadena1: ");
    Serial.println(sizeof(cadena1));  // 6
    Serial.print("Tamaño de la variable cadena2: ");
    Serial.println(sizeof(cadena2));  // 2
    Serial.print("Longitud de la cadena de cadena1: ");
    Serial.println(strlen(cadena1));  // 5
    Serial.print("Longitud de la cadena de cadena2: ");
    Serial.println(strlen(cadena2));  // 5
}

void loop() {
}

Aclarar que sizeof() se evalúa en tiempo de compilación y da como resultado el número de bytes que ocupa una variable u objeto. Y strlen() es una función que da como resultado la longitud de una cadena, sin tener en cuenta el carácter nulo ya que cuenta justo los caracteres que hay antes de encontrarse el "carácter nulo".

¿Se ve más claro la diferencia entre lo que "miden" las cadenas y lo que "gastan" u "ocupan" las variables? ¡Ojo! que no piense nadie que con cadena2 ahorramos memoria porque "gasta" menos que cadena1, ya que si bien cadena2 sólo guarda el puntero a una cadena, esa cadena ha de estar en algún sitio "ocupando" memoria. Así que en realidad con cadena2 se está "gastando" dos bytes más que con cadena1.

¿Y qué "ventajas" tiene cadena2 con respecto a cadena1? Una cosa es modificar el contenido de cadena1 y otra muy distinta el modificar el contenido de cadena2. Si modificamos cadena1 estamos cambiando el contenido de la cadena (el contenido del array) y hemos de indicar qué elemento del array queremos modificar (mediante [índice]). Mientras que si modificamos cadena2 lo que estamos cambiando es a qué array "apunta", sin cambiar el contenido de ningún array. Y es esto último lo que creo que se quiere hacer, cambiar de texto, no cambiar el texto. Así que en lugar de declarar la variable textString como un array e inicializarlo con un valor dado:

char textString[20] = "esperando mensaje";

Habría que declararlo como un puntero que inicialmenta apunta a cierto valor constante:

const char* textString = "esperando mensaje";

Para luego, cuando proceda, cambiar el puntero para que apunte a otra cadena constante y en lugar de poner:

char textString[20] = "mensaje 1";

no habría más que poner:

textString = "mensaje 1";

Haciendo esto último con el resto de asignaciones, debería de funcionar sin problemas.

Por cierto, usando String sería aplicar una solución parecida, salvo poner:

String textString = "esperando mensaje";

:wink: en lugar de:

const char* textString = "esperando mensaje";

Y aunque en este caso lo parezca, no es lo mismo String que const char*

Pido perdón por tanto palique.

Buenos dias,
primero de todo agradecerte no solo que dieras la solución al problema, que a veces suele ser lo que la gente busca, sino que dieras esa extensa explicación del funcionamiento de las cadenas ya que al poner en mi programa las lineas que modificaste hizo que otras cosas no funcionaran bien por la forma de declarar la cadena y con lo aprendido por tus palabras lo pude solucionar al haber entendido el funcionamiento.

Muchas gracias de nuevo

p.d: tu post lo he copiado en un fichero .txt donde tengo apuntes para tenerlo como referencia como consulta para futuros proyectos :smiley: