Palabras clave: Estrucutura de control, Estructuras condicionales, Condiciones booleanas.

Preguntas de repaso
  • ¿Los operadores que retornan valores booleanos son los llamados operadores booleanos?

  • ¿Qué es una expresión booleana?

  • Indica qué es una secuencia de estructuras condicionales anidadas.

No sigas si no conoces las respuestas.

1. Instrucción Iterativa

Una instrucción iterativa o repetitiva, también conocida como bucle, tiene la misión de ejecutar las mismas instrucciones de código una y otra vez mientras que se cumpla una determinada condición.

Se llama ciclo a la secuencia de sentencias que se repiten en un bucle.

Una instrución iterativa requiere de una serie de componentes o instrucciones para su correcto funcionamiento. Dichas componentes, expresadas en pseudocódigo, son:

1 2 3 4 5
Inicialización. (1) MIENTRAS (expresion booleana) HACER { (2) Cuerpo. (3) } Finalización. (4)
1 La Inicialización es el conjunto de instrucciones que se ejecutan para inicializar las variables que participan de la iteración.
2 MIENTRAS-HACER es la instrucción iterativa. Ejecutará el cuerpo, lo contenido entre las llaves, siempre que la expresión booleana sea cierta.
3 El Cuerpo es el conjunto de instrucciones que se ejecutan mientras que se cumpla la expresión booleana. Es imprescindible que en el cuerpo haya alguna instrucción que modifique para el siguiente ciclo la expresión booleana (de no modificarse nunca, el bucle no tendría fin).
4 La finalización es el conjunto de instrucciones que se ejecutarán cuando la iteración termina.

2. Instrucción while

Los lenguajes de programación suele traducir los bucles MIENTRAS-HACER por la instrucción while.

En Processing la instrucción iterativa while se escribe de esta forma:

Inicialización.
while (expresion booleana) {
    Cuerpo.
}
Finalización.

3. Bucle controlado por variable centinela

Se denomina variable centinela a aquella variable tal que si tomara un cierto valor el bucle debe parar.

Cuando se utiliza una variable centinela, el esquema general presenta esa forma:

1 2 3 4 5
Inicialización - incluye inicialización de la variable centinela C - MIENTRAS (expresion booleana dependiente de C) HACER { Cuerpo - incluye modificar el valor de C - } Finalización.

Es necesario en la inicialización que la variable centinela tome un valor que permita la ejecución del ciclo; pero una vez inicializado el bucle en algún momento debe cambiar su valor para que la expresión booleana sea falsa y pueda continuar por la componente de Finalización.

  • Si no se inicializa adecuadamente la variable centinela, nunca se ejecutará el bucle.

  • Si no se actualiza adecuadamente al variable centinela en el cuerpo, el bucle nunca finalizará.

Ejemplo 1. Dibuja círculos concéntricos

El siguiente código permite dibujar círculos concéntricos centrados en la pantalla gráfica.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
/* Introducción al Sw Científico y a la Programación Dibujando círculos concéntricos. */ // Tamaño de la ventana gráfica: 500px de lado. size(500,500); /* Inicialización */ // Radio del círculo. Será la variable centinela del bucle. int n = width; // El bucle se realizará mientra que el valor // de la variable centinela sea mayor a 10. while (n > 10) { // Instrucción iterativa de Processing: while(expresion) /* Cuerpo */ // Se establece un relleno de color aleatorio fill(random(255), random(255), random(255)); // Dibujar un círculo centrado en la pantalla y // con un radio ellipse(width/2,height/2,2*n,2*n); // IMPRECINDIBLE. Actualización de la variable centinela. n = n/2; } /* Finalización */ println("Todo OK");

Puedes verlo en acción:

¿Qué pasaría si en el ejemplo anterior escribíesemos n=n+1 en vez de n=n/2? ¿Parará el programa en algún momento?

Entre las variables centinelas destacan los contadores y los acumuladores.

  • Un contador es una variable que en cada ciclo incrementa (o decrece) su valor en una cantidad fija.

  • Un acumulador es una variable que en cada ciclo incrementa (o decrece) su valor en una cantidad variable.

Explica qué hace el siguiente código:

1 2 3 4 5 6 7 8 9 10 11
int n=1; int s=n; int max=100; while (s<max) { n = n + 1; s = s + n; } n = n-1; println("** Solución: " + n);

Observa que la variable s es una acumulador, pues en cada ciclo incrementa su valor en una cantidad variable (1, 2, 3, …​). Por contra, la variable n es un contador, pues en cada ciclo incrementa su valor en una cantidad fija (una unidad).

Este es un bucle controlado por un acumulador, pues un acumulador es lo que aparece en la expresión de control del bucle (aunque el acumulador a su vez dependa de un contador).

4. Estructuras iterativas pre y post condicionales: instrucción do.

La instrucción iterativa que acabamos de estudiar es una estructura iterativa pre-condicional. Se llama así a aquellas estructuras cuya componentes son tales que la expresión booleana se comprueba antes de ejecutar el cuerpo (o ciclo) del bucle: primero se evalúa la condición y si es verdadera se ejecuta el bloque de acciones.

Por contra están los bucles post-condicionales. Son aquellos en los que primero se ejecuta el bloque de acciones y luego se evalúa la condición. Existen dos tipos de bucles pot-condicionales.

  • Aquellos donde si es falsa la condición se ejecuta nuevamente el bloque de acciones. El ciclo finaliza cuando la condición toma el valor de verdadero. Esta instrucción suele conocerse como do-until.

  • Aquellos otros donde el ciclo se ejecutará mientras el valor de la condición sea verdadero. Esta instrucción suele conocerse como do-while.

Notar que a diferencia de la pre-condicional, en las post-condicionales el ciclo se ejecuta al menos una vez.

Processing solo tiene una instrucción iterativa post-condicional y se escribe de esta forma:

Inicialización.
do {
    Cuerpo.
while (expresion booleana); // Observa el punto y coma.
Finalización.

5. Estructuras iterativas exactas: instrucción for.

Como hemos visto, puede ocurrir que un bloque de instrucciones se tenga que ejecutar desconociendo el numero exacto de veces que lo hará. En estos casos los lenguajes ofrecen estructuras de control iterativas que están condicionadas a la evaluación de una condición booleana (que depende de cierta variable centinela).

Podemos usar una variable centinela y una condición de evaluación para que la estructura repita el cuerpo de acciones una cantidad fija de veces. Para ello basta usar un contador, para contar el número de veces que se ha realizado el cuerpo, y establecer la condición de ejecutar el cuerpo mientra que el contador no alcance el número de veces deseado. Un esquema general sería:

1 2 3 4 5 6 7 8
Inicialización - incluye la inicialización tanto de la variable contador c=0 (puede ser otro valor) como de la variabe numVeces, que indica cuántas veces realizar el cuerpo MIENTRAS (c != numVeces) HACER { Cuerpo - incluye modificar el valor de c según c=c+1; - } Finalización.

Una estructura iterativa que presente este esquema es una estructura iterativa exacta.

Para este tipo de estructuras, los lenguajes de programación incluyen la instrucción for.

En Processing la instrucción iterativa exacta for se escribe de esta forma:

Inicialización.
for (int c=0; c<numVeces; c=c+1) {
    Cuerpo.
}
Finalización.
Observa que una estructura iterativa exacta se puede realizar tanto con un while como con un for. Las dos requiere de un contador.
Ejemplo 2. Cuadrados rotados

El siguiente código permite dibujar exáctamente n-cuadrados cuya esquina superior izquierda se situa en el origen de coordenadas y con una rotación de \(\frac{2\times \pi}{n}\) radianes con respecto al lado superior del cuadrado anterior.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
/* Introducción al Sw Científico y a la Programación Rotación de cuadrados */ size(300,300); // Tamaño de la ventana gráfica: 300px de lado. background(255); // Fondo de color blanco. translate(width/2, height/2); // Se desplaza el origen de coordenadas. /* Inicialización */ // Número de cuadrados que queremos dibujar int n = 5; // Bucle donde ejecutaremos exáctamente n-veces el cuerpo for (int i=0; i<n; i++) { // Instrucción for de Processing /* Cuerpo */ // Se establece un relleno de color aleatorio fill(random(255), random(255), random(255)); rotate(PI*2/n); // Rotamos el plano rect(0,0,width/3, width/3); // Se dibuja un cuadrado } /* Finalización */ println("Todo OK"); // Mensaje de finalización

Puedes verlo en acción:

Dibuja exáctamente 10 líneas horizontales que estén separadas por una cantidad constante y no inferior a 20 píxeles. La longitud, grosor y separación establécelas como quieras. Aquí tiene un ejemplo:

Incluye en tu programa una estructura condicional para que informe cuándo no es posible mostrar todas las líneas.

Constrasta tu solución con la mía:

6. Anidamiento

En el cuerpo de un instrucción iterativa se puede incluir cuantas estructuras iterativas consideres. Estas a su vez puede contener a otras y así sucesivamente.

Cuando una estructura iterativa está en el cuerpo de otra se habla de bucles anidados.

Ejemplo 3. Dibujar una malla cuadrada

El siguiente programa dibuja una ventana gráfica con una malla de \(10\times 10\) celdillas

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
/* Introducción al Sw Científico y a la Programación Dibuja una malla de 10x10 celdillas, usando una secuencia de while. */ int numCeldillas = 10; // Número de celdillas, por lado, que queremos dibujar int ancho = 30; // Ancho de la celdilla // Ajustamos el tamaño de la ventana gráfica para un tablero "perfecto" size(numCeldillas*ancho, numCeldillas*ancho); int fila=0; // Inicialización del contador del primer bucle while (fila<numCeldillas) { // Primer bucle <<<< int columna = 0; // Inicialización del contador del segundo bucle while (columna<numCeldillas) { // Segundo bucle (anidado) <<<< fill(random(255)); // Relleno con un gris aleatorio rect(columna*ancho, fila*ancho, ancho, ancho); // Dibujar un rectángulo columna = columna + 1; // Actualización del contador del segundo bucle } fila = fila + 1; // Actualización del contador del primer bucle }

Modifica el código del ejemplo y sustituye las instrucciones while por instrucciones for. Respeta el nombre de las variables.

Constrasta tu solución con la mía:

7. Repaso

  • Una estructura repetitiva ejecuta una y otras vez las mismas líneas de código en función de una expresión booleana.

  • En la expresión boolenana pueden intervenir operadores de comparación u operadores lógicos (o los dos).

  • Hay 3 tipos de estructuras repetitivas.

    • la estructura while, donde se repite una serie de instrucciones si se cumple una cierta condición.

    • la estructura do-while, donde se ejecuta una serie de intrucciones, para a continuación repetirse una y otra vez si se cumple una cierta condición.

    • la estructura for-to, donde se repite una serie de instrucciones un número determinado de veces.

  • Es usual que los condicionales de las estructuras repetitivas dependan de contadores o acumuladores.

  • Las estructuras repetitivas pueden anidarse unas en otras.