While y do-while en Java: bucles centinela

Los bucles while y do-while en Java son bucles basados en centinela. Como explicamos sobre estos bucles en el artículo que hablaba de las estructuras repetitivas, los bucles basados en centinela ejecutan repetidas veces un bloque de instrucciones mientras se siga cumpliendo cierta condición.

Los bucles centinela son buenos cuando no sabemos exactamente el número de veces que se va a ejecutar un bucle, pero sabemos qué se debe cumplir para que se siga ejecutando.

Sentencia while en Java

Esta es su estructura más sencilla:

// inicialización de variables
boolean centinela = true;
while (centinela) { // Condición para que se itere una vez más
    // Cuerpo de instrucciones
} 
// resto del programa

Es muy importante que comprendas y aprendas el orden de ejecución partes integrantes de un bucle while en Java. Observa la siguiente imagen:

Secuencia de ejecución del bucle while en Java
Secuencia de ejecución del bucle while en Java

En este trozo de programa se pide por el teclado una cadena, que se supone debe ser un nombre, y se saluda escribiendo ese nombre. Esto se repetirá mientras que no se introduzca la palabra ‘fin’.

Como puedes ver, la siguiente sería la secuencia de ejecución de la estructura while:

  1. Inicialización de variables antes de entrar en el bucle.
  2. Se comprueba la condición: si es verdadera se pasa al paso 3 (cuerpo del bucle) y si no al 5 (se terminaría su ejecución).
  3. Ejecución del cuerpo del bucle.
  4. Vuelta al paso 2.
  5. Fin del bucle, se ejecuta la siguiente instrucción al mismo.

Como verás, si no se introduce la palabra ‘fin’ el programa no parará nunca. Además, hay también un pequeño error de diseño en el programa. Piénsalo y luego lo resolveremos.

Inicialización antes del bucle while

No es que haya una sección de inicialización que pertenezca al bucle while propiamente dicha, pero imagina que escribimos lo siguiente:

while (encontrado==false) {
    if (contador==numeroBuscado) {
        encontrado=true;
    } else {
        contador++;
    }
}

¿Crees que eso, así como está, se ejecutará bien? Y qué pasa si no le hemos dado valor a encontrado, ni a contador ni a numeroBuscado, ¿nos podremos fiar de lo que vaya a ejecutar?

Es por eso que aunque no exista como tal una sección de inicialización, nosotros debemos preparar todas las variables que vayan a participar en el bucle de forman que tengan los valores necesarios para que todo se ejecute como esperamos.

boolean encontrado=false;
int contador = 1;
// Generamos un número aleatorio entre 0 y 100
int numeroBuscado = (int)(Math.random()*100);
while (encontrado==false) {
    if (contador==numeroBuscado) {
        encontrado=true;
    } else {
        contador++;
    }
}
System.out.println("El número aleatorio ha sido alcanzado en " + contador + " iteraciones");

La condición en el while

Un bucle while se estará ejecutando mientras que la condición sea cierta. Ten en cuenta también una cosa: si la condición no es cierta antes de entrar en el bucle, nunca se llegará a ejecutar el cuerpo.

La condición puede ser tan sencilla o tan compleja como nos deje el propio lenguaje expresarla. Observa bien esta condición, que necesitas haber programado bastante para entender a primera vista.

Scanner sc = new Scanner(System.in);
String nombre;
while (!(nombre = sc.nextLine()).equals("fin")) {
    System.out.println("Hola "+nombre);
} 

Si no entiendes la condición puede que te ayuden dos cosas:

  1. El error del que hablamos más arriba cuando explicábamos la secuencia de ejecución del while era que cuando el usuario introducía fin, el programa escribía ‘Hola fin’, y eso no es algo que quisiéramos que hiciera.
  2. La condición que hay en este bucle soluciona de un plumazo ese problema.

Te dejo que lo pienses. Por otro lado, por si no te has dado cuenta, mediante un while podemos simular la ejecución de un bucle for:

// Inicialización
int i=0;
// Condición
while (i<10) {
    System.out.println(i);
    // Incremento
    i++;
} 

Pero como te dije en el for, cada bucle debe usarse para lo que se ideó y en el while está indicado cuando no sabemos el número concreto de veces que se va a ejecutar algo, pero sí sabemos qué se debe cumplir para que se siga ejecutando.

Sentencia do-while en Java

El bucle do-while no es más que un while en el que la condición se comprueba después de cada iteración, y no antes. De esta forma el cuerpo del bucle siempre se ejecutará al menos una vez.

Mira este ejemplo en el que planteamos un menú sencillo:

Scanner sc = new Scanner(System.in);
String entrada;
do {
    // Escribimos las opciones del menú
    System.out.println("Introduzca la opción deseada:\n"
            + "leer\n"
            + "escribir\n"
            + "fin");
    // Leemos la opción elegida por el usuario
    entrada = sc.nextLine();
    // Comprobamos la opción, pasándola a minúscula
    switch (entrada.toLowerCase()) {
        case "leer":
            // Código de leer
            break;
        case "escribir":
            // Código de escribir
            break;
        case "fin": // no hacemos nada
            break;
        default: 
            System.out.println("Opción no válida.");
    }
} while ( !(entrada.toLowerCase().equals("fin")) );

Resumen: Bucles centinela en Java

Los bucles con centinela se basan en una condición para ejecutar o no una nueva iteración del cuerpo de instrucciones.

Esa condición puede ir al principio del bucle, como en la sentencia while, de forma que si antes de entrar en el cuerpo no se cumple, no se ejecutará ninguna iteración. Pero como en el caso del do-while la condición puede ir al final del cuerpo, con lo que nos aseguramos que al menos se ejecuta una iteración del mismo.

Es muy importante que tengas claro que una vez dentro del bucle, depende de ti, el programador, el hacer que la condición para que se siga ejecutando el bucle se cumpla o no se cumpla. Si la condición nunca se modifica, tendrás un bucle infinito.