1.9 Decisión múltiple: switch

La instrucción if se llama de decisión simple, porque sólo puede elegir entre dos caminos: si el resultado de la condición es verdadero, elige un camino; si es falso, elige el otro camino.

Cuando se desea poder elegir entre múltiples caminos, se debe recurrir a múltiples instrucciones if, o se puede utlizar la instrucción switch, denominada de decisión múltiple.

La instrucción switch analiza una variable y según el resultado de esa variable, selecciona el camino a seguir. Como la cantidad de caminos posibles a seguir debe ser finitas, la variable a analizar debe ser de un tipo discreto (int o char).

Veamos el siguiente ejemplo:



// ejemplo6.cpp: Instrucción switch
//

#include "stdafx.h"
#include <iostream>
using namespace std;

void main()
{
int n1,n2,r;
char op;
cout<<"Ingrese dos números:";
cin>>n1>>n2;
cout<<"Ingrese la operación a realizar:";
cin>>op;
switch(op)
{
case '+': r = n1 + n2;
               break;
case '-': r = n1 - n2;
               break;
case '*': r = n1 * n2;
               break;
case '/': if (n2 != 0)
                      {
                             r = n1 / n2;
                      }
               else
                   {
                          r = 0;
                          cout<<"No se puede dividir por cero.";
                   }
               break;
default:  cout<<"Operación inválida.";
}
cout<< "El Resultado es "<<r;


cin>>r;

}


La instrucción switch analiza el valor de la variable op, y elegirá el camino según dicho valor. Si el contenido de la variable es el caracter '+', continúa ejecutando el programa en el primer case. Si el contenido es '-' continúa ejecutando el segundo, y así con las cuatro operaciones matemáticas. La instrucción break al final de cada case hace que se finalice la ejecución del switch y pase a la instrucción siguiente, que muestra el resultado final. Si no se coloca el break al final de un case, se continúan ejecutando las instrucciones del case siguiente. (A veces, eso es lo deseado).
Si el valor ingresado en la variable no coincide con ninguno de los valores especificados en los case, se ejecutan las instrucciones que estén tras la etiqueta default. Esta etiqueta no es obligatoria, pero es muy recomendable colocarla siempre.
El último case de la instrucción (generalmente el default), no necesita de un break, ya que cuando termine no hay nada más dentro del switch, por lo que seguirá con la instrucción siguiente, que es lo mismo que haría si hubiera un break.

El siguiente ejemplo mustra diferentes alternativas de cases con y sin break.



// ejemplo7.cpp: Variantes de la instrucción switch
//

#include "stdafx.h"
#include <iostream>
using namespace std;

void main()
{
int r;
cout<<"Ingrese un número:";
cin>>r;
switch(r)
{
case 1: cout<<"Esta instrucción se ejecuta en el caso 1"<<endl;
               break;
case 2: cout<<"Esta instrucción se ejecuta en el caso 2"<<endl;

case 3: cout<<"Esta instrucción se ejecuta en los casos 2 y 3"<<endl;
               break;             
case 4:
case 5: cout<<"Esta instrucción se ejecuta en los casos 4 y 5"<<endl;
               break;
default:  cout<<"Esta instrucción se ejecuta para cualquier caso mayor a 5.";
}


cin>>r;

}



Uno de los usos más comunes de la instrucción switch es para presentar al usuario menúes de opciones, correspondiendo un case a cada opción de menú. 

1.10 Instrucciones de repetición: while

Hasta ahora, vimos dos tipos de instrucciones: Las de secuencia, que se ejecutan siempre linealmente una a continuación de la otra, y las de decisión, que permiten decidir si se ejecutará o no otra instrucción.

Vamos a empezar ahora a ver el tercer grupo de instrucciones, que son las que permiten ejecutar otras instrucciones más de una vez: las instrucciones de repetición o iteración. La primera de esas instrucciones es la instrucción while.

El formato de la instrucción es:

 while (condición)
  {
       ....
       (otras instrucciones)
       ....
  };

Lo primero que hace la instrucción while es analizar la condición. Si el resultado es verdadero, se dice que "entra al ciclo", y ejecuta las otras instrucciones que están dentro de la llave. Cuando termina de ejecutar las instrucciones, vuelve a analizar la condición. Si todavía es verdadera, vuelve a ejecutar las instrucciones que están dentro de las llaves. Cuando termina, vuelve a analizar la condición, y así seguirá repitiendo las instrucciones que están entre las llaves hasta que la condición sea falsa. Cuando esto ocurra, continuará ejecutando la instrucción que esté después del while normalmente.



// ejemplo5.cpp: Calcular el factorial de un número
// El factorial de un número n es el producto de todos los números naturales desde 1 hasta n.

#include "stdafx.h"
#include <iostream>
using namespace std;
void main()
{
       int n, fact, i;
       cout<<"Ingrese un número:";
       cin>>n;
       i = 1;   // i es una variable auxiliar que cuente la cantidad de veces que se ejecuta el ciclo;
       fact = 1;  // le asigno un valor inicial 1
       while (i <= n)
       {
             fact = fact * i;
             i = i+1;
       }
       cout<<"El factorial de "<<n<<" es "<<fact<<endl;


       cin>>i;
}

En este ejemplo, el usuario ingresa el valor de n, y luego comienza el ciclo. Inicialmente, i vale 1 y se guarda ese valor en factorial. Luego se suma uno a i, y se llega al final de las instrucciones que están dentro del ciclo: se compara i (que ahora vale 2) con n (valor ingresado por el usuario), y si sigue siendo menor o igual, vuelve a comenzar el ciclo: se multiplica ese valor por el factorial, y se pasa al valor siguiente.  Así, hasta que i sea mayor a n (valdrá n+1). En ese caso, el ciclo no vuelve a comenzar, y el cout final muestra el valor del factorial calculado.

En este ciclo, la condición es evaluada antes de ejecutar las instrucciones que están dentro del ciclo, por lo que si la condición no se cumple de entrada, las instrucciones dentro del ciclo no se ejecutarán nunca.

Una vez dentro del ciclo, las intrucciones dentro del ciclo se repetirán hasta que se modifique el resultado de la condición, por lo es necesario que por lo menos una de dichas instrucciones modifique las variables presentes en la condición. (En este ejemplo, la instrucción i = i + 1 puede modificar la condición ( i <= n ).

1.11 instrucción for

En muchos casos, los ciclos se deben repetir una cantidad fija de veces. Cuando esto ocurre, es posible utlizar otra instrucción en lugar de while, pensada específicamente para este tipo de ciclos. Veamos de vuelta el ejemplo anterior:


// ejemplo5.cpp: Calcular el factorial de un número
// El factorial de un número n es el producto de todos los números naturales desde 1 hasta n.

#include "stdafx.h"
#include <iostream>
using namespace std;
void main()
{
       int n, fact, i;
       cout<<"Ingrese un número:";
       cin>>n;
       i = 1;   // i es una variable auxiliar que cuente la cantidad de veces que se ejecuta el ciclo;
       fact = 1;  // le asigno un valor inicial 1
       while (i <= n)
       {
             fact = fact * i;
             i = i+1;
       }
       cout<<"El factorial de "<<n<<" es "<<fact<<endl;


       cin>>i;
}

Las instrucciones que controlan el ciclo están resaltadas en amarillo:

i = 1;   indica el valor inicial de la variable i
while (i <= n)  indica la condición que se debe cumplir para seguir iterando dentro del ciclo
i = i+1  indica el cambio de la variable i en cada iteración (será en definitiva la que haga finalizar el ciclo luego de n repeticiones).

La instrucción for permite agrupar estas tres instrucciones en una sola, facilitando la escritura de ciclos:

    for (valor inicial; condición de iteración; incremento)


Así, el ejemplo queda re-escrito de la siguiente forma:



#include "stdafx.h"
#include <iostream>
using namespace std;
void main()
{
       int n, fact, i;
       cout<<"Ingrese un número:";
       cin>>n;
       fact = 1;  // le asigno un valor inicial 1
       for (i=1; i <= n; i = i +1)
       {
             fact = fact * i;
       }
       cout<<"El factorial de "<<n<<" es "<<fact<<endl;


       cin>>i;
}


Al llegar a la instrucción for, el programa ejecuta la instrucción de valor inicial ( i = 1) y luego analiza la condición ( i <= n). Si la condición es verdadera, ingresa al ciclo y ejecuta las instrucciones que estén dentro del mismo. Una vez ejecutadas las instrucciones, ejecuta la instrucción de incremento (i = i + 1), y vuelve a analizar la condición. Si sigue siendo verdadera, vuelve a ejecutar las instrucciones del ciclo. Así continuará ejecutando el incremento una vez al final de cada ejecución del ciclo, hasta que la condición deje de ser verdadera y salga del ciclo. Como se puede ver, el for hace exactamente lo mismo que el while en el ejemplo anterior.

Por la simplicidad con que los resuelve, es especialmente útil para ciclos que se deben ejecutar una cantidad fija de veces.

1.12 Instrucción do ... while

La tercera instrucción de repetición es la instrucción do.... while, y su formato es el siguente:

do
{
   ...
   (otras instrucciones)
   ...
}
while (condición);

Esta instrucción primero ejecuta las instrucciones dentro del ciclo (las que están entre el do y el while) y luego analiza la condición. Si la condición es falsa, finaliza el ciclo y continúa ejecutando las instrucciones que están a continuación del while. Si la condición es verdadera, vuelve a ejecutar las instrucciones dentro del ciclo y  analizar la condición, ciclo que se repetirá hasta que la condición sea falsa.
La principal diferencia con el ciclo while que vimos antes es que aún en el caso de que la condición sea falsa, las instrucciones del ciclo se ejecutan por lo menos una vez. Esto sucede porque a diferencia del while que primero analiza la condición y luego ejecuta las instrucciones del ciclo, el do...while primero ejecuta las instrucciones a repetir y luego analiza la condición por lo que siempre se ejecutarán las instrucciones al menos una vez.


 
Esta instrucción es particularmente útil cuando se desea que el usuario ingrese un dato, y se desea asegurar que el dato sea válido.

Por ejemplo, en el siguiente caso:

cout<<"Ingrese el mes"<<m;
cin>>m;

Si quiero asegurar que el mes sea correcto, debería preguntar si el valor ingresado está entre 1 y 12. Si es incorrecto, debería ingresarlo de vuelta y preguntar de vuelta, y aún podría ingresarse un valor erróneo. Con la instrucción do...while, es muy sencillo escribirlo de la siguiente forma:

do
{
    cout<<"Ingrese el mes"<<m;
    cin>>m;
}
while ((mes< 1) || (mes > 12) );


En este ejemplo, se ingresa el valor de mes,y deberá seguir ingresando dicho valor mientras se ingrese un valor incorrecto (menor a 1 ó mayor a 12).
Esta verificación de los datos ingresados por el usuario se llama validación, y debería hacerse siempre que el dato ingresado pueda estar equivocado. La validación de datos es uno de los principales usos de la instrucción do...while.




1.13 Contadores y Acumuladores

Veamos el siguiente ejercicio:

Realizar un programa que permita al usuario ingresar las temperaturas medidas para un lugar en una serie de días y calcule el promedio de dichas temperaturas. No se sabe cuántas mediciones se ingresarán; para finalizar se indica -300 como valor de temperatura.

El programa constará de un ciclo que se repetirá ingresando las sucesivas temperaturas. Para obtener el promedio se necesita saber la cantidad total de mediciones y la suma total de las mediciones, para lo que utilizaremos las variables cant y suma:



#include "stdafx.h"
#include <iostream>
using namespace std;

void main()
{
       int temp,cant,suma;
       float prom;
       cant = 0;
       suma = 0;
      
       cout<<"Ingrese la temperatura(-300 para terminar):";
       cin>>temp;
      
       while (temp!=-300)
       {
             cant = cant + 1;
             suma = suma + temp;
             cout<<"Ingrese la temperatura(-300 para terminar):";
             cin>>temp;  //SIEMPRE dentro del ciclo while debe haber una instrucción que    
                         // modifique la condición del mismo
       }
       prom = (float) suma/cant; // para forzar la división float
       cout<<"El promedio de temperaturas es: "<<prom;

       cin>>temp;
}


La variable cant incrementa su valor en 1 cada vez que se ejecuta el ciclo.  Está contando la cantidad de veces que se ejecuta el ciclo.
Si por ejemplo quisiera saber la cantidad de días de más de 30°C, debería hacer:



if (temp > 300)
       {
             cant30 = cant30 + 1;

             }

Y la variable cant30 tendría la cantidad deseada. Estas variables, que cuentan la cantidad de veces que el programa pasa por un punto dado se llaman contadores.
Siempre se inicializan en cero y se incrementan en uno en el lugar deseado.
Análogamente, la variable suma no se incrmenta en 1, sino en el valor de de temp; se llama acumulador.