26 de septiembre de 2018

Bucles (Loops)

Cuando ejecutamos nuestros pequeños ejemplo, se están ejecutando una única vez. La sentencia que se ejecuta no vuelve a llamarse más. En esta entrada aprendemos los distintos bucles que tiene Java que nos van a permitir iterar (repetir) un fragmento de código las veces que necesitemos.

Repetir algo es una de las partes que vimos más generales a la hora de programar. Ya sólo nos faltará ver la Entrada (Input) en la siguiente sesión.

En general vamos a tener tres partes a la hora de definir un bucle:
  1. Condición para ejecutar el código del cuerpo del bucle
  2. Actualización de valor/es que influyen en la condición
  3. Código a ejecutarse que no es propio del control del bucle
Con estas ideas vamos a ver las distintas formas de declarar un bucle

Los bucles nos permiten repetir fragmentos de código mediante el control de una expresión condicional



Bucle while

Su estructura es:
  while (condicion) {
    // cuerpo con actualizacion
  }
Su funcionamiento es evaluar la condición marcada y ejecutar el código de su cuerpo si se cumple. El código del cuerpo debe influir de alguna forma en la siguiente evaluación de la condición o se quedaría infinitamente iterando o nunca lo haría.

Vemos un ejemplo muy gráfico basado en la curiosa conjetura de Collatz:
  public static void collatz(int n) {
    while (n != 1) {
        System.out.println(n);
        if (n % 2 == 0) { // n es par
            n = n / 2;
        } else {          // n es impar
            n = n * 3 + 1;
        }
    }
  }

Bucle for

Su estructura es:
  for (inicio; condicion; actualizo) {
    // cuerpo
  }
Este bloque centraliza el control del bucle en su primera línea. Cada una de las expresiones se dedica a:
  • inicio: Normalmente declara un estado inicial. Se ejecuta sólo cuando se inicia el bucle.
  • condicion: Se evaluará cada iteración del bucle.
  • actualizo: Se ejecutará al final de cada iteración y servirá para influir en la condicion.
En este ejemplo hacemos una cuenta atrás desde un número:
  for (int i = 3; i > 0; i--) {
    System.out.println(i);
  }
  System.out.println("!BOOM!");

Bucle do-while

Su estructura es:
  do {
    // cuerpo
  } while (condicion);
Se puede ver como un caso especial de while. La diferencia es que la condición se evaluará al final de la iteración. Esto implica que al menos se ejecutará una vez el cuerpo hasta llegar a la condición.
  do {
    System.out.println("Itero");
  } while (false);
En el ejemplo vemos que el cuerpo se ejecutará aunque la condición sea false desde el principio. Es importante terminar toda la declaración con punto y coma ";" ya que podríamos pensar que no hace falta como en los otros dos casos, pero sería un error de compilación (Eclipse nos avisará).

Diferencias entre los distintos bucles

Ahora que tengo varias formas de iterar ¿Cuál uso?
Puedes seguir estos consejos para elegir el bucle más idóneo:
  • for: cuando sabes cuantas veces vas a tener que iterar porque tiene un numero finito de elementos.
  • while: cuando no sabes cuántas veces tienes que iterar, incluido ninguna.
  • do-while: cuando no sabes cuántas veces tienes que iterar pero al menos será una.
Los bucles en general están formados por una situación inicial, una condición que va evolucionando y un código a ejecutar en su cuerpo. Cuanto más sepamos del problema a solucionar mejor decidiremos el bucle a emplear


Controlar el bucle con break y continue

Hay dos palabras reservadas que se usan mucho con los bucles: break y continue.
  • break: termina la ejecución del bucle y sale directamente
  • continue: termina la ejecución de la iteración y vuelve a evaluar la condición
En el siguiente ejemplo vemos que continue hace que se salte los números pares y que break termina la ejecución en 7 en vez de llegar al 9:
  for (int i = 0; i < 10; i++) { // de 0 a 9
    
      if(i == 7) { // termina cuando es 7
          break;
      }
      if(i % 2 == 0) { // pasa al siguiente si es par
          continue;
      }
    
      System.out.println("i = " + i);
  }

Conversiones for y while

Todo for puede convertirse en while y viceversa pero no es aconsejable. Si miras los ejemplos verás que todo funciona bien, pero a simple vista no queda bien y hace el código menos legible. Por eso es importante elegir bien qué estructura usar.
  for (int i = 0; i < 10; i++) {
  }

  // equivale a

  int i = 0; // inicio
  while (i < 10) { // condicion
      i++; // actualizo
  }
A la inversa sería tan simple como borrar el inicio y actualizo del for y en condición usar la del while:
  while (condicion) {
    // ...
  }

  // equivale a

  for (;condicion;) {
  }

No hay comentarios:

Publicar un comentario

Compárteme

Entradas populares