Bucle while

Un bucle while tiene asociado un bloque de sentencias que se ejecutarán secuencialmente mientras la condición de entrada al bucle sea cierta.

La condición se evalúa al comienzo de la estructura. Esto supone que el bloque de instrucciones puede no ejecutarse ninguna vez si la condición es inicialmente falsa.

while (condicion)
{
   bloque de sentencias;
}
../../_images/while.jpg

Diagrama de flujo de la sentencia while

Ejemplo

El siguiente ejemplo retoma la introducción del ordinal de un mes para conocer su número de días.

En las versiones basadas solo en sentencias condicionales, la única alternativa que tenemos cuando el usuario introduce un valor erróneo, es informar al usuario y dar por finalizado el programa. Ahora, podemos dar el aviso y volver a solicitar el valor al usuario.

#include <iostream>
using namespace std;
int main()
{
   cout << "Dame el mes: (1, 2, ..., 12): ";
   int mes;
   cin >> mes;
   while (mes < 1 || mes > 12)
   {
      cout << "El valor introducido no es válido.\n";
      cout << "Dame el mes: (1, 2, ..., 12): ";
      cin >> mes;
   }
   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";
}

Edita, compila y ejecuta el código

En el ejemplo, si la expresión mes < 1 || mes > 12 se evalúa como true y, por tanto, el usuario ha cometido un error, entonces:

  1. se ejecuta el bloque de sentencias:

    {
       cout << "El valor introducido no es válido.\n";
       cout << "Dame el mes: (1, 2, ..., 12): ";
       cin >> mes;
    }
    
  2. se regresa de nuevo a la sentencia while para una nueva evaluación de la condición.

Así de forma iterada hasta que la expresión de control mes < 1 || mes > 12 asociada al while se evalúe como false.

Se debe comprender que si la condición de control del bucle se evalúa inicialmente como false, las sentencias asociadas al bucle no serán ejecutadas ni siquiera una vez.

Por tanto, en el momento en que se realiza la programación, el número de veces que se repite un bucle while ¡no puede saberse de antemano!

Así, en el ejemplo anterior puede ocurrir:

  • que no se ejecute el cuerpo del while ninguna vez, si el usuario introduce un mes correcto desde el inicio.

  • que se ejecute un número arbitrariamente alto de veces, que dependerá de la mucha o poca habilidad del usuario en seguir correctamente las instrucciones que se le dan.

Bucle controlado por un contador

El anterior ejemplo muestra un bucle controlado por una condición lógica de carácter general. En muchas ocasiones, la condición de salida del bucle viene determinada por un contador, es decir, una variable encargada de contar cuantas veces se ejecuta el bucle.

Ejemplo

// Bucle controlado por un contador que suma un
// determinado conjunto de reales. (Versión 1)

#include <iostream>
using namespace std;

int main()
{
   cout << "Introduzca cuantos números reales quiere sumar: ";
   int contador;
   cin >> contador;

   if (contador > 0)
   {
      double suma = 0.0;
      while (contador > 0)
      {
         cout << "Deme valor real a sumar: ";
         double valor;
         cin >> valor;
         suma += valor;  // Equivalente a suma = suma + valor
         contador -= 1;  // Equivalente a contador = contador - 1
      }
      cout << "La suma de los números introducidos es " << suma << endl;
   }
   else
      cout << "No se introdujeron números para realizar la suma.\n";
}

Edita, compila y ejecuta el código

En el programa anterior se debe notar que antes de entrar al bucle, ya se conoce el número de veces que éste se va a repetir. Veremos enseguida que esta tarea se realiza de forma natural con los bucles for.

El acumulador

El ejemplo anterior implementa además una de las ideas básicas de mayor utilidad en programación: el concepto de acumulador.

Se quiere realizar una operación (la suma) que involucra un conjunto (no determinado en el momento de la programación) de operandos. La idea consiste en dedicar una variable, suma, para contener los resultados parciales de dicha operación.

Dicha variable acumulador ha de ser inicializada antes de entrar al bucle a un valor que sea neutro respecto a la operación seleccionada (el 0 en caso de la suma). Ya dentro del bucle, la variable acumulador es actualizada en cada iteración.

Podríamos haber programado el ejemplo anterior de otra forma, igualmente válida y legible, en la que no perdemos el valor inicial de cuantos números queremos sumar.

Ejemplo

// Bucle controlado por un contador que suma un
// determinado conjunto de reales. (Versión 2)

#include <iostream>
using namespace std;

int main()
{
   cout << "Introduzca cuantos números reales quiere sumar: ";
   int num_valores;
   cin >> num_valores;

   int contador = 0;
   double suma = 0.0;
   while (contador < num_valores)
   {
      cout << "Deme valor real a sumar: ";
      double valor;
      cin >> valor;
      suma += valor;  // Equivalente a suma = suma + valor
      contador += 1;  // Equivalente a contador = contador + 1
   }
   if (num_valores > 0)
      cout << "La suma de los " << num_valores <<
              " valores introducidos es " << suma << endl;
   else
      cout << "No se introdujeron números para realizar la suma.\n";
}

Edita, compila y ejecuta el código