Calculadora básica Arduino

Hola buenas, estoy intentando hacer una calculadora básica con arduino y se me a ocurrido que es buena idea implementar un switch... case, el problema es que nunca he usado esta estructura, esto es lo que tengo hecho de momento pero no tengo ni idea de cómo hacerlo funcionar, alguna sugerencia?

/*escribir un programa que implemente una calculadora básica,
pudiendo realizar las siguientes operaciones con esta sintaxis:
2+3 ENTER
8-2 ENTER
2*2 ENTER
6/3 ENTER
sqrt(4) ENTER
2^2 ENTER
*/
void setup()
{
  Serial.begin(9600);
  Serial.println("Introduzca la operación: ");
}

void loop()
{
  if Serial.available(){
    Serial.println("Qué operacion quieres hacer: ");
    Serial.println("Suma: +");
    Serial.println("Resta: -");
    Serial.println("Multiplicacion: *");
    Serial.println("Division: /");
    String Operacion = Serial.readStringUntil('\n');
    switch (Operacion){
      case 1:
      if (Operacion == '+'){ 
}

hola:
No he husado nunca el CASE con string, pero si funciona igual que con enteros deberias poner algo asi:

switch (Operacion){
  case "Suma +":
  //Hago lo que sea
  break;

  case "Resta: -"
  //Hago lo que sea
  break;
  // etc.

Saludos.

Hola de nuevo, sigo peleando con este ejercicio y me sale un error que soy incapaz de solucionar; el cacho de código donde me señara el error es este:

  switch (Operacion){
      
      case "+":
      Serial.println("Introduce la operación: ");
      String Calc = Serial.readStringUntil('\n');
      int Operador = Calc.indexOf("+");
      String Op1 = Calc.substring(0, Operador);
      String Op2 = Calc.substring (Operador, '\n');
      break;
    }

Y el error en cuestión dice:
'In function 'void loop()'
28:22: error: switch quantity not an integer
30:12: error: could not vonvert '"+"' from 'const char [2]' to ''
exit status 1'

Adjunto el código completo que tengo hasta el momento por si ayuda, me sale el mismo error en todos los 'case ...'

/*escribir un programa que implemente una calculadora básica,
pudiendo realizar las siguientes operaciones con esta sintaxis:
2+3 ENTER
8-2 ENTER
2*2 ENTER
6/3 ENTER
sqrt(4) ENTER
2^2 ENTER
*/
void setup()
{
  Serial.begin(9600);
  Serial.println("Introduzca la operación: ");
}

void loop(){
  if (Serial.available()>0){
    
    Serial.println("Qué operacion quieres hacer: ");
    Serial.println("Suma: +");
    Serial.println("Resta: -");
    Serial.println("Multiplicacion: *");
    Serial.println("Division: /");
    String Operacion = Serial.readStringUntil('\n');
    
    switch (Operacion){
      
      case '+':
      Serial.println("Introduce la operación: ");
      String Calc = Serial.readStringUntil('\n');
      int Operador = Calc.indexOf("+");
      String Op1 = Calc.substring(0, Operador);
      String Op2 = Calc.substring (Operador, '\n');
      int Operando1 = Op1.toInt();
      int Operando2 = Op2.toInt();
      int Resultado = Operando1 + Operando 2;
      Serial.println(Resultado);
      break;
      
      case '-':
      String Calc = Serial.readStringUntil('\n');
      int Operador = Calc.indexOf("-");
      String Op1 = Calc.substring(0, Operador);
      String Op2 = Calc.substring (Operador, '\n');
      int Operando1 = Op1.toInt();
      int Operando2 = Op2.toInt();
      int Resultado = Operando1 - Operando 2;
      Serial.println(Resultado);
      break;
      
      case '*':
      String Calc = Serial.readStringUntil('\n');
      int Operador = Calc.indexOf("*");
      String Op1 = Calc.substring(0, Operador);
      String Op2 = Calc.substring (Operador, '\n');
      int Operando1 = Op1.toInt();
      int Operando2 = Op2.toInt();
      int Resultado = Operando1 * Operando 2;
      Serial.println(Resultado);
      break;
      
      case '/':
      String Calc = Serial.readStringUntil('\n');
      int Operador = Calc.indexOf("*");
      String Op1 = Calc.substring(0, Operador);
      String Op2 = Calc.substring (Operador, '\n');
      int Operando1 = Op1.toInt();
      int Operando2 = Op2.toInt();
      int Resultado = Operando1/Operando 2;
      Serial.println(Resultado);
      break;
      
    }
  }
        
}

Hola:
Como dije anteriormente nunca use el case con string, porque con solo oir sring me chirrian los dientes.. En fin con el codigo siguiente te funcionaran los case.

int operacion;

void setup()
{
  Serial.begin(9600);
  operaciones();
}

void loop(){
  // Para alguien que entienda: ¿porque si aqui pongo lo que
  //lleva la función operaciones no se para el bucle?
  if (Serial.available()>0){  
    operacion = Serial.read();
    Serial.read(); Serial.read();
   
    switch (operacion){
     
      case '+':
      Serial.println("Estoy sumando");
      operaciones();
      break;
      
      case '-':
      Serial.println("Estoy restando");
      operaciones();
      break;
   
      case '*':
      Serial.println("Estoy multiplicando");
      operaciones();
      break;
 
      case '/':
      Serial.println("Estoy dividiendo");
      operaciones();
      break; 
    }
  }
}

void operaciones(){
    Serial.println("");Serial.println("");Serial.println("");
    Serial.println("Introduzca la operación: ");
    Serial.println("Suma: +");
    Serial.println("Resta: -");
    Serial.println("Multiplicacion: *");
    Serial.println("Division: /");
  }

De lo que intentas hacer dentro de los case ni idea, comenta alguna línea a ver si me entero y aprendo algo mas de los string de las narices.

PD:
Ya lo se, ya lo se ,el código no es muy elegante , pero funcionar funciona.

Oído, he comentado una parte del switch para ver si entiendes las operaciones que he hecho. Son básicamente distintas funciones que puedes hacer con las strings.

 switch (Operacion){
      
      case '+':
      Serial.println("Introduce la operación: ");
      String Calc = Serial.readStringUntil('\n');//El programa lee hasta ENTER 
      int Operador = Calc.indexOf("+");//Calcula qué posición tiene en la string el símbolo +
      String Op1 = Calc.substring(0, Operador); //hace una substring desde el principio de la string introducida inicialmente hasta la posición del operador +
      String Op2 = Calc.substring (Operador, '\n'); //lo mismo pero desde la posición del operador hasta el final
      int Operando1 = Op1.toInt(); //Convertimos las substrings en enteros (también se podrían convertir a Floats con '.toFloat()')
      int Operando2 = Op2.toInt();
      int Resultado = Operando1 + Operando 2;
      Serial.println(Resultado);
      break;

@gonpezzi no entiendo nada, tengo la estructura del case exactamente igual a ti (haciendo excepción en las funciones extra que yo tengo) y me sale el siguiente error: "error: switch quantity not an integer"

Alguien tiene idea? Estoy por intentar algo parecido a lo que tu has hecho y en cada switch case llamar a una función y hacer en ella las diferentes operaciones.

Creí que ya te lo había dicho días atrás, se ve que no pulsé "Post"...

Tu error es que estás usando una variable String donde debes usar char o int.
switch/case trabaja con enteros y char (o sea byte) solamente, no trabaja con String.

No es lo mismo
"+" que es un string que '+' que es un char.
Uno se limita con comillas dobles el otro con comillas simples.

Tampoco es lo mismo

String operacion = Serial.readStringUntil('\n');

que

char operacion = Serial.read();

La primera lee varios bytes hasta que encuentra un final de línea y los devuelve en un String, no puede usarse para las comparaciones con case
La segunda lee un solo byte y lo devuelve en un char, sí se puede usar con case.

Igual, para solo 4 operaciones, ¿por qué no usas if y listo?
Así puedes comparar lo que sea.

Saludos

Hola: Hazle caso a @gatul y observa que en el ejemplo que te subi lo primero que hago es defini "operacion" como entero.
Saludos.

Otra solución es hacer un pequeño cambio al código original

switch(operacion[0]) {

Así se usa para la comparación solo el primer caracter del string, el compilador lo pasará a char y se puede usar sin problemas (siempre y cuando operacion tenga al menos un caracter).

Recordar que los char se delimitan con comillas simples por lo tanto, como expliqué antes la comparación en el case es, por ej.

case '+':

Saludos

Al final lo solucioné de otro modo usando enteros pero me estoy atascando en una cosa que creo debería ser muy sencilla, aquí va el código:

void setup()
{
  Serial.begin(9600);
  Serial.println("Introduce operacion: ");

}

void loop(){
  if (Serial.available()>0){
    
	
    String operacion = Serial.readStringUntil('\n');
    Serial.print(operacion);
    int longitudOperacion = operacion.length();
    
    int suma = operacion.indexOf('+');
    int resta = operacion.indexOf('-');
    int multiplicacion = operacion.indexOf('*');
    int division = operacion.indexOf('/');
    
    if (suma > 0){
      int signo = 1;
      Serial.print("Signo: ");
      Serial.println(signo);
    }
    
    if (resta > 0){
      int signo = 2;
      Serial.print("Signo: ");
      Serial.println(signo);
    }
    
    if (multiplicacion > 0){
      int signo = 3;
      Serial.print("Signo: ");
      Serial.println(signo);
    }
    
    if (division > 0){
      int signo = 4; 
    }
    
    Serial.print("El valor del signo es: ");
    Serial.print(signo);
    
    
    switch (signo){// open switch
      
      case 1:
      	Serial.print(operacion);
      	int separador = operacion.indexOf('+');
      	String Op1 = operacion.substring(0, separador); 
      	String Op2 = operacion.substring (separador,longitudOperacion); 
      	int Operando1 = Op1.toInt(); 
      	int Operando2 = Op2.toInt();
      	int Resultado = Operando1 + Operando2;
      	Serial.println(Resultado);
      	break;
  /* aquí abajo el resto de operaciones

Estoy intentando acceder al switch a través de la variable signo, el problema es que, dependiendo de la situación, en cada if le doy un valor a la variable signo, pero al salir del bucle no se guarda ese valor para después entrar a las acciones del switch. Al principio había declarado esta variable al principio del loop void dandole el valor -1, pero al salir de los ifs no cambiaba este valor. Alguna idea??

Hola otra vez: ¡Valla dos nos hemos juntado para manejar string!.
Veamos: si defino la variable operación antes del setup, (por errores de compilación), y quito el switch si funciona perfectamente,. Luego por tanto el error esta dentro del case 1: .
Sigo estudiando lo que me comentaste anteriormente dentro del case a ver si me entero de como funcionan las funciones que operan con los string.
Saludos.

Lo pille.
Recuerda que estos chismes cuentan en binario, luego para ellos el primer "lo que sea"" no es el uno sino el cero. si cambias la siguiente línea de código la suma funciona. Es de suponer que igual para el resto de operaciones.

//String Op2 = operacion.substring (separador,longitudOperacion);
 String Op2 = operacion.substring (separador+1,longitudOperacion);//SUMO 1 A SEPARADOR

Saludos.

Vamos por partes dijo Jack y de paso a ver si entendí lo que intentas hacer

Ahora el código estaría bien encarado y cumple con la consigna, algo que el original no hacía, pero hay un detalle...

Hay algo que se llama "ámbito de una variable" que dice que una variable se extingue al salir de su ámbito de definición, o sea ya no se puede usar.
Por eso hay variables globales y variables locales, las primeras se mantienen para todo el programa, las otras solo donde fueron definidas.

Tú estás definiendo (definir no es lo mismo que asignar) la variable "signo" dentro de las sentencias if(), por lo tanto se pierden al salir de if() porque se sale de su ámbito de definición. Es por eso, además, que el compilador no te da error por definición múltiple de variables, porque si bien la defines varias veces, inmediatamente se extingue su uso.

Un ejemplo muy claro de ámbito de una variable es el típico

for(int i = 0; i < unas_cuantas; i++) {
 // acá hace algo unas_cuantas veces;
}

Supongamos que dentro del lazo pusiéramos break ante determinada condición y luego para guardar el punto en que salió del lazo hiciéramos

int a = i;

Tendríamos un error al compilar que diría que "i" no está definida (porque la variable "i" dejó de existir al terminar el lazo for()) .
Para que eso no ocurra deberíamos hacer

int i;
for(i = 0; i < unas_cuantas; i++) {
 // acá hace algo unas_cuantas veces;
}
int a = i;

Así el ámbito de "i" se declara fuera del for() y al salir de éste se conserva.

Todas las variables que no quieres que se pierdan dentro del loop() debes definirlas al principio del mismo (serían locales) o definirlas globales al principio del código (para ser prolijo).

Y fíjate porque has hecho lo mismo con todas las variables, es probable que luego tengas errores con otras. Por ejemplo hay variables definidas dentro de los case que (ahora ya lo sabes) se van a crear al entrar a un case pero se van perder al salir del mismo.

Otra cosa a tener en cuenta es cómo manejas la resta, puedes tener conflictos si se empieza ingresando un número negativo.

Ten cuidado porque lo que al principio era un error casi menor (usar string donde iba char) lo estas complicando cada vez más, lo que lleva a que cometas nuevos errores porque no interpretas, o no entiendes bien, las instrucciones que estas agregando y como usarlas.

Saludos

Hola @gatul he intentado las dos opciones que has dado, tanto definir el signo en el void setup como definirlo antes de los ifs y usar otra variable y sigue sin funcionar :(. Al acabar los ifs he puesto un serial.print para saber qué valor le asigna al signo y me da que vale 8967. Vamos, que sigo sin saber cómo acceder a los distintos case del switch. Lo estoy haciendo así porque es lo que me recomendó mi profesor al preguntarle :frowning: gracias de todos modos, a ver si me podéis ayudar.

Además, al hacerlo como lo tenía pensado al principio no es nada elegante porque eliges la operación antes de realizarla y una calculadora en verdad no funciona así.

Si, pero la mayoría de los ejercicios para principiantes hacen eso. ¿Por qué? No sé, supongo que a los que los diseñaron les gustaba la Notación Polaca. :smiley:

Y hablando en serio, esa es una más de las formas que puedes entrar datos en una calculadora (que acepte ese método de ingreso, obvio).
De verdad, esa forma se llama Notación Polaca pero la más usada es la Notación Polaca Inversa (ingresas op1, op2 y por ultimo el signo) y hasta no hace muchos años era la manera "profesional" de usar una calculadora. Bueno, sí, hace unos cuantos... :wink:

Saludos

Te lo sirvo en bandeja, complétalo

void setup()
{
  Serial.begin(9600);
  Serial.println("Introduce operacion: ");
}

void loop() {
  int signo = 0;
  int longitudOperacion, suma, resta, multiplicacion, division;
  String operacion = "", op1 = "", op2 = "";
  int separador, Operando1, Operando2;
  long Resultado;
  
  if(Serial.available()>0) {
    operacion = Serial.readStringUntil('\n');
    Serial.println(operacion);
    longitudOperacion = operacion.length(); // en realidad no es necesaria esta variable
    
    suma = operacion.indexOf('+');
    resta = operacion.indexOf('-');
    multiplicacion = operacion.indexOf('*');
    division = operacion.indexOf('/');
    
    if(suma > 0) {
      signo = 1;
      separador = suma;
    }
    
    if(resta > 0) {
      signo = 2;
      separador = resta;
    }
    
    if(multiplicacion > 0) {
      signo = 3;
      separador = multiplicacion;
    }
    
    if(division > 0) {
      signo = 4;
      separador = division;
    }
    
//    Serial.print("El valor del signo es: ");
//    Serial.println(signo);
        
    op1 = operacion.substring(0, separador);
    op2 = operacion.substring(separador + 1);
    
//    Serial.print("op1 = "); Serial.print(op1);
//    Serial.print("  op2 = "); Serial.println(op2);
    
    Operando1 = op1.toInt();
    Operando2 = op2.toInt();

    Serial.print(operacion); Serial.print(" = ");
    
    switch (signo){
      case 1: Resultado = Operando1 + Operando2;
      	break;
      case 2: Resultado = Operando1 - Operando2;
      	break;
  /* aquí abajo el resto de operaciones */
     }

   Serial.println(Resultado);
   }
}

Está probado, no hay errores.
El tuyo no estaba tan mal pero aparte de lo que te mencioné antes sobre las variables, haces mal el corte para extraer los operandos. Te olvidaste que si el signo está en la posición X entonces el segundo operando empieza en X+1.

Muéstranos el código terminado.

Saludos

hmmm vale, miraré tu solución y veré qué tenemos distinto a ver si lo puedo hacer con mis propias manos. Al tenerlo lo postearé; gracias !!!