Control de flujo condicional switch

Aunque el escalonamiento if - else if - else puede evaluar de forma anidada múltiples condiciones, si estas son muy numerosas, empieza a haber pérdida de legibilidad.

C/C++ posee una estructura condicional múltiple, switch, que ejecuta un bloque de sentencias si una variable o expresión entera coincide con alguno de los valores proporcionados en una lista de constantes enteras (literales int o char, por ejemplo).

switch (expresion)
{
   case valor_1:
      sentencias_1
   case valor_2:
      sentencias_2
   //Resto de bloques case
   case valor_n:
      sentencias_n
   default:
      sentencias_default;
}

La ejecución del programa consiste en comparar expresion de arriba a abajo con cada constante literal que aparece tras la palabra reservada case. Si se localiza una coincidencia, se ejecutan todas las sentencias por debajo de esa constante hasta:

  • finalizar el bloque switch

  • encontrar una sentencia break;

Opcionalmente se puede insertar una condición por defecto mediante default, cuyas sentencias asociadas se ejecutarían si no se ha encontrada previamente una coincidencia.

Para ilustrar el funcionamiento de la sentencia switch vamos a ver diferentes versiones de un programa con idéntica salida por pantalla, que muestra el númer de días de un mes.

Versión 1 con if anidados

#include <iostream>
using namespace std;

int main()
{
   cout << "Dame el mes: (1, 2, ..., 12): ";
   int mes;
   cin >> mes;

   if (mes > 0 && mes < 13)
      if (mes == 1)
         cout << "El mes tiene 31 dias.\n";
      else if (mes == 2)
         cout << "El mes tiene 28 o 29 dias.\n";
      else if (mes == 3)
         cout << "El mes tiene 31 dias.\n";
      else if (mes == 4)
         cout << "El mes tiene 30 dias.\n";
      else if (mes == 5)
         cout << "El mes tiene 31 dias.\n";
      else if (mes == 6)
         cout << "El mes tiene 30 dias.\n";
      else if (mes == 7)
         cout << "El mes tiene 31 dias.\n";
      else if (mes == 8)
         cout << "El mes tiene 31 dias.\n";
      else if (mes == 9)
         cout << "El mes tiene 30 dias.\n";
      else if (mes == 10)
         cout << "El mes tiene 31 dias.\n";
      else if (mes == 11)
         cout << "El mes tiene 30 dias.\n";
      else if (mes == 12)
         cout << "El mes tiene 31 dias.\n";
      else
         cout << "¡Imposible!\n";
   else
      cout << "El valor introducido no es válido\n";
}

Edita, compila y ejecuta el código

Versión 2 mejorada con if anidados

#include <iostream>
using namespace std;

int main()
{
   cout << "Dame el mes: (1, 2, ..., 12): ";
   int mes;
   cin >> mes;

   if (mes > 0 && mes < 13)
      if (mes == 1 || mes == 3 || mes == 5 || mes == 7 ||
          mes == 8 || mes == 10 || mes == 12)
         cout << "El mes tiene 31 dias.\n";
      else if (mes == 2)
         cout << "El mes tiene 28 o 29 dias.\n";
      else if (mes == 4 || mes == 6 || mes == 9 || mes == 11)
         cout << "El mes tiene 30 dias.\n";
      else
         cout << "¡Imposible!\n";
   else
      cout << "El valor introducido no es válido.\n";
}

Edita, compila y ejecuta el código

Versión 3 con switch

#include <iostream>
using namespace std;

int main()
{
   cout << "Dame el mes: (1, 2, ..., 12): ";
   int mes;
   cin >> mes;

   if (mes > 0 && mes < 13)
      switch(mes)
      {
         case 1:
         case 3:
         case 5:
         case 7:
         case 8:
         case 10:
         case 12:
            cout << "El mes tiene 31 dias.\n";
            break;
         case 4:
         case 6:
         case 9:
         case 11:
            cout << "El mes tiene 30 dias.\n";
            break;
         case 2:
            cout << "El mes tiene 28 o 29 dias.\n";
            break;
         default:
            cout << "¡Imposible!\n";
      }
   else
      cout << "El valor introducido no es válido.\n";
}

Edita, compila y ejecuta el código

La sentencia break, de la que hablaremos más adelante, es un tipo de sentencia de control de flujo incondicional. Su objetivo es forzar la salida inmediata del bloque en el que está declarada, en este caso, el bloque switch.

Realización de menús

La sentencia condicional switch se utiliza con frecuencia para gestionar la selección en menús.

En caso de que la opción elegida no sea válida, se realiza el código asociado al bloque default, visualizándose un mensaje de error.

Ejemplo de menú

// Transforma temperaturas de celsius <-> kelvin
#include <iostream>
using namespace std;
int main()
{
   int opcion;
   double celsius, kelvin;
   cout << "Este programa transforma temperaturas.\n";
   cout << "Elija una opcion:\n";
   cout << "1. De grados celsius a grados kelvin.\n";
   cout << "2. De grados kelvin a grados celsius.\n\n";
   cout << "Por favor, introduzca su opcion (1 o 2): ";
   cin >> opcion;
   switch(opcion)
   {
      case 1: // paso de Celsius a Kelvin
         cout << "Introduzca la temperatura en grados Celsius: ";
         cin >> celsius;
         if (celsius >= -273)
         {
            kelvin = celsius + 273;
            cout << celsius << " grados C son " << kelvin << " grados K.\n";
         }
         else
            cout << "Temperatura por debajo del cero absoluto.\n";
         break;
      case 2: // paso de Kelvin a Celsius
         cout<<"Introduzca la temperatura en grados kelvin:\n";
         cin >> kelvin;
         if (kelvin >= 0)
         {
            celsius = kelvin - 273;
            cout << kelvin << " grados K son " << celsius << " grados C.\n";
         }
         else
            cout << "Temperatura por debajo del cero absoluto.\n";
         break;
      default:
         cout << "La opcion escogida no es válida.\n";
   }
}

Edita, compila y ejecuta el código