Control del flujo de ejecución
El término flujo de ejecución de un programa involucra tres conceptos que se relacionan entre sí: i) flujo, ii) ejecución y iii) programa. Aunque los vamos a definir a continuación, debes saber que existe una relación muy cercana, a nivel semántico, entre el flujo de ejecución de un programa y la idea de diagrama de flujo, previamente abordado desde una perspectiva visual a la hora de introducir el concepto de algoritmo.
El concepto de programa, previamente discutido, se puede definir como una secuencia de instrucciones que el ordenador es capaz de entender y que tienen un objetivo bien definido. En segundo lugar, la palabra ejecución hace referencia, precisamente, a esa capacidad de la máquina para hacer que el programa haga lo que debe hacer, empleando para ello los recursos físicos o hardware disponibles. Por ejemplo, uno de estos recursos sería un registro del procesador del ordenador que se emplea para almacenar o guardar el valor de una variable. Finalmente, el concepto flujo refleja esa noción de dinamismo de la que gozan los programas en ejecución, y que establece el camino que el programa recorrerá desde que se arranca hasta que termina. Cada paso de este camino estará representado por una instrucción de código. En este punto, es importante destacar que, aunque un programa esté compuesto de una secuencia de instrucciones, no tiene por qué ejecutarlas todas y cada una de ellas en un determinado orden. Por el contrario, el programa ejecutará un subconjunto de dichas instrucciones en función de una serie de condiciones.
Estas condiciones las establece el programador, de forma directa, a través de instrucciones que modifican o controlan el flujo de ejecución del programa. Por otra parte, el flujo de ejecución del programa puede verse alterado dependiendo del valor puntual de las variables que se usan en el programa. Como veremos en ejemplos posteriores, las instrucciones que se usan para controlar el flujo de un programa suelen combinarse con el uso de variables.
Pero antes de discutir cómo se puede controlar el flujo de un programa mediante sentencias más complejas, veamos un ejemplo más sencillo. El siguiente listado muestra la estructura general de un programa, compuesto por 7 instrucciones.
De acuerdo a dicha estructura, un ordenador que ejecutara este programa procesaría primero sentencia 1
. Después, procesaría sentencia 2
. A continuación, procesaría la instrucción goto etiqueta
. En este punto, el lector podría pensar que el flujo de ejecución del programa continuaría ejecutando, en orden secuencial, sentencia 4
. Sin embargo, la instrucción goto
, que representa el ejemplo más sencillo de control de flujo en un programa, provocaría que este “saltara” a la instrucción etiqueta:
. Precisamente, la traducción literal de goto
podría ser “ir a”, en el contexto de ir a otro punto del código del programa. En otras palabras, la instrucción goto provoca un cambio o salto incondicional en el flujo de ejecución del programa, de forma que la siguiente instrucción a ejecutar, sentencia 5
, sea la que está escrita justo después de la instrucción etiqueta:
.
sentencia 1
sentencia 2
goto etiqueta
sentencia 3
sentencia 4
etiqueta:
sentencia 5
Atención
El código que abusa del uso de sentencias de salto incondicional puede convertirse en el denominado código espagueti, ya que estas sentencias complican la estructura del flujo de ejecución de un programa. Este término deriva de la comparación con un plato de espaguetis, donde el propio código se visualiza como un conjunto de hilos enredados. El espagueti anudado representaría la metáfora del flujo de ejecución del programa. Así, y con carácter general, se desaconseja el uso de sentencias de salto incondicional.
Si bien los saltos incondicionales no requieren de condición alguna para ejecutarse, las sentencias de control condicional, por otra parte, se basan en la idea de evaluar una condición o expresión para disparar posibles cambios en el flujo de ejecución de un programa. En este sentido, recuerda que las sentencias condicionales son las estructuras más básicas que permiten a un computador actuar tomando decisiones. En el ejemplo de sentencia condicional que ya conoces, “si el perro ladra, entonces encender la iluminación del jardín”, la palabra clave si
introduce una condición a modo de pregunta (¿ladra el perro?). Si la respuesta a esta pregunta es afirmativa, la parte inmediatamente posterior a la palabra clave entonces
será la acción que se ejecutará.
La condición a evaluar en una sentencia condicional suele estar relacionada con la consulta del valor de una determinada variable, o incluso de varias. El siguiente listado de código muestra un fragmento escrito en el lenguaje de programación Python que ejemplifica, de manera sencilla, esta situación. En las líneas 1 y 2 se declaran las variables a
y b
, a las que se le asignan, respectivamente, los valores 13 y 7. En la línea 4 aparece una sentencia condicional, representada en Python por la palabra clave if
. A continuación, aparece la condición a evaluar, a > b
. Así, si el valor de a es mayor que el valor de b, entonces se ejecutará la sentencia de la línea 5. Si no lo es, es decir, si el valor de a es menor o igual al valor de b, entonces se ejecutará la sentencia de la línea 7. Fíjate cómo en la línea 6 se utiliza otra palabra clave en Python, else
, para agrupar las sentencias que se ejecutarán cuando la evaluación de la condición equivale a un valor falso.
a = 13
b = 7
if a > b :
print(‘El valor de a es mayor que el valor de b’)
else:
print(‘El valor de a es menor o igual que el valor de b’)
Como puedes imaginar, si ejecutaras este código el resultado sería el siguiente:
El valor de a es menor o igual que el valor de b
Las sentencias condicionales se pueden complicar, encadenando unas con otras para así cubrir más situaciones.
Atención
El término utilizado para agrupar sentencias condicionales se denomina anidamiento. Así, puedes anidar o encadenar varias sentencias condicionales para controlar diferentes situaciones o condiciones, asociando diferentes conjuntos de acciones en función del resultado de la evaluación de la condición que gobierna la sentencia.
En este sentido, el fragmento de código anterior se puede extender tal y como se muestra a continuación. Concéntrate en la sentencia elif
de la línea 6. En esencia, lo que le estaríamos indicando al programa es que si la evaluación de la condición anterior, es decir, la de la línea 4, fue falsa, entonces prueba esta nueva condición, definida en la línea 6. Finalmente, y al igual que en el anterior ejemplo, la sentencia else
de la línea 8 se utiliza para indicar la acción que se debe ejecutar (línea 9) en caso de que todas las condiciones anteriores se hayan evaluado a falso.
a = 13
b = 7
if a > b:
print(‘El valor de a es mayor que el valor de b’)
elif a == b:
print(‘El valor de a es igual al valor de b’)
else:
print(‘El valor de a es menor que el valor de b’)
Hay otros lenguajes de programación que agrupan varias sentencias del tipo if-then-else
en una única sentencia. Por ejemplo, el lenguaje de programación Java proporciona la sentencia switch
, tal y como se muestra en el siguiente ejemplo de código.
int dia = 3;
switch (dia) {
case 1:
System.out.println(“Lunes”);
break;
case 2:
System.out.println(“Martes”);
break;
case 3:
System.out.println(“Miércoles”);
break;
/* Resto de días aquí: Jueves, Viernes, Sábado */
case 7:
System.out.println(“Domingo”);
break;
}
La expresión de la sentencia switch
de la línea 2 solo se evalúa una vez. Posteriormente, el valor de dicha expresión se compara con cada uno de los valores de la sentencia switch
, vinculados a las diferentes sentencias case
que la componen. En este ejemplo, se compara el valor de la variable dia
con cada uno de los valores de las sentencias case
. Así, el valor de dia
se comparará primero con el valor 1, después con el valor 2, etc. Cuando exista una coincidencia, es decir, cuando la comparación sea verdadera, entonces se ejecuta el código que existe a continuación de la sentencia case correspondiente. En este ejemplo, se ejecutará el código de las líneas 10 y 11, de forma que el resultado de ejecutar este programa sería Miércoles
.
Por otra parte, y como ya conoces, los lenguajes de programación ofrecen sentencias para repetir fragmentos de código. Normalmente, esta repetición se llevará a cabo mientras una determinada condición sea verdadera. Por ejemplo, y volviendo al lenguaje de programación Python, la sentencia while
permite la ejecución de un conjunto de sentencias en tanto en cuanto la condición que la gobierna sea verdadera. El siguiente listado de código muestra un caso concreto.
i = 1;
while i <= 5:
print(i)
i=i+1
Como puedes apreciar, es relativamente fácil identificar que el código contenido en el bucle while
, es decir, el código de las líneas 4 y 5, se ejecutará 5 veces. Esto es equivalente a afirmar que el bucle while
realizará 5 iteraciones. La condición que gobierna el bucle equivale a preguntarse en cada iteración si el valor de la variable i
es menor o igual que 5. La primera vez que se realiza esta comparación, el valor de la variable i
es 1. Como 1 es menor o igual que 5, la condición se evalúa a verdadero y, por lo tanto, el código del bucle (líneas 4 y 5) se ejecuta. Este código muestra el valor de la variable i
por pantalla y, aquí viene la parte importante, le suma una unidad al contenido de la variable i
. Posteriormente, el flujo de control del programa vuelve a la línea 3, evaluando, de nuevo, la condición. Ahora, el valor de la variable i
es 2, que se compara de nuevo con 5. Este proceso se repetirá hasta que la variable i
contenga el valor 6. En este punto, el bucle while
no ejecutará más iteraciones.
Finalmente, la inmensa mayoría de los lenguajes de programación incluyen sentencias que permiten escribir bucles con mayor flexibilidad. Una de las más clásicas es la sentencia for
. Típicamente, este tipo de sentencias permitirá incluir más funcionalidad a la hora de declarar el bucle, como por ejemplo la asignación de valor a variables o incluso la propia actualización de la variable que gobierna la ejecución del bucle. Así, el programador tiene más flexibilidad a la hora de escribir código. Discutamos otro ejemplo en Python.
for i in range(1, 6):
print(i)
Este fragmento de código produce exactamente el mismo resultado que el fragmento anterior, en el que se utilizó la sentencia while
. En otras palabras, el código de la línea 2 se ejecutará 5 veces (el bucle realizará 5 iteraciones). A diferencia del fragmento anterior, la variable i
se declara en la propia sentencia del bucle for
de la línea 1. Además, y mediante la sentencia range
, estamos indicando que el bucle iterará mientras el valor de la variable i
se encuentre en el rango de 1 a 6, es decir, mientras que el valor de la variable i
sea 1, 2, 3, 4 o 5. Como puedes apreciar, hemos sido capaces de recrear, con solo 2 líneas de código, la misma funcionalidad que en el listado anterior, que contenía 4 líneas de código (omitiendo la línea en blanco).