Fundamentos de programación/Control de flujo

De Wikiversidad
Lección 7
Control de flujo

Los programas se diseñan para procesar datos, manejándolos de formas diferentes dependiendo de los valores que tengan. Los lenguajes de programación deben proveer estructuras que le permitan a los programadores controlar el flujo de ejecución de un programa dependiendo de los datos que procesan de forma que puedan realizar esas transformaciones.[1] Sin importar la complejidad de los algoritmos que se desea implementar, todos se pueden expresar con cuatro estructuras básicas que todos los lenguajes ofrecen de una forma u otra: ejecución secuencial, selección, repetición e invocación.[2]

La ejecución secuencial es el más básico de los mecanismos de control de flujo y consiste en la ejecución de instrucciones en el orden en que se encuentran en el código fuente del programa (o en el código máquina una vez que han sido compilados). La selección consiste en ejecutar instrucciones diferentes dependiendo del resultado de evaluar una expresión o del valor de una variable. La repetición es la ejecución reiterada de instrucciones por un número fijo de ocasiones o dependiendo del resultado de evaluar una expresión. La invocación transfiere el control a otra sección del programa, normalmente regresando automáticamente al punto posterior a dicha invocación una vez que finaliza la ejecución de la sección invocada.[2]

La ejecución secuencial se ha utilizado en lecciones anteriores y consiste simplemente en ejecutar las instrucciones en el orden en que se encuentran en el programa. En el resto de esta lección estudiaremos las estructuras de selección y repetición y en la siguiente lección estudiaremos las invocaciones o subrutinas.

Selección[editar]

Las estructuras de selección permiten ejecutar diferentes instrucciones dependiendo del valor de una variable o expresión. También se les llama ramificaciones,[1] estructuras de decisión o alternativas.[2] Cuando se usan, no todas las instrucciones del programa se ejecutan, solo las especificadas para el valor de la variable durante esa ejecución. Las estructuras de selección más comunes son las que proporcionan ramificaciones dobles y múltiples.[1]

Selección doble[editar]

Las instrucciones de selección doble permiten seleccionar la instrucción a ejecutar dependiendo del valor de una variable lógica o de una expresión cuyo resultado es un valor lógico.[2] Este tipo de instrucciones normalmente tiene la siguiente estructura:

si [expresión lógica] entonces
[Instrucción a ejecutar si la expresión lógica es verdadera.]
sino
[Instrucción a ejecutar si la expresión lógica es falsa.]
fin_si

La expresión lógica es cualquier expresión que da un resultado lógico (verdadero o falso) o incluso una variable de tipo lógico. La instrucción después de las palabras reservadas entonces y sino es cualquier instrucción válida del lenguaje de programación. Si el valor de la expresión lógica es verdadero, la computadora ejecutará la instrucción después de la palabra entonces y no ejecutará la instrucción después de la palabra sino. Por el contrario, si el valor de la expresión lógica es falso, la máquina omitirá la instrucción después de la palabra entonces y procederá a ejecutar la instrucción después de la palabra sino.

Este tipo de instrucciones se puede aprovechar para calcular cosas como el valor absoluto de un número, que matemáticamente se define de la siguiente forma:

En el siguiente fragmento de código, la expresión lógica regresa verdadero si el valor de la variable es menor a 0. En ese caso el valor absoluto se calcula como la negación aritmética del valor de la variable. Si el valor de la variable es mayor a cero, la expresión regresa el valor falso y el valor absoluto se calcula simplemente como el valor de la variable.

// Variable con el valor a calcular
entero x := -45

// Variable con el resultado
entero valor_absoluto_de_x

// Instrucción de selección
si x < 0 entonces
    valor_absoluto_de_x := -x
sino
    valor_absoluto_de_x := x
fin_si

Al escribir programas, es frecuente que nos interese tomar una acción si se cumple una expresión lógica pero no nos interesa tomar ninguna acción si la condición no se cumple. En esos casos podemos omitir la palabra sino y la instrucción que le sigue. En el siguiente ejemplo se hace uso de esa posibilidad para aplicar un impuesto de 10% a las compras con un valor superior a 10 000 unidades monetarias.

// Valor de la compra
real valor_compra := 45 000

// Porcentaje del impuesto: 10%
real porcentaje_impuesto := 0.1

// Sumamos el impuesto si el valor de la compra es superior a 10 000 unidades
si valor_compra > 10 000 entonces
     valor_compra := valor_compra + valor_compra * 0.1
fin_si

Selección múltiple[editar]

Las estructuras de selección múltiple permiten evaluar expresiones que regresan valores de tipos diferentes al tipo de datos lógico. Cada uno de los posibles valores que puede tomar una variable o expresión se conoce como un caso y para cada caso el programador puede indicar una instrucción diferente. A diferencia de las instrucciones de selección doble, las de selección múltiple evalúan todos los casos y los ejecutan si la expresión evaluada los satisface.[2] Normalmente las instrucciones de selección múltiple tienen la siguiente estructura:

según_sea [expresión lógica] hacer
caso Valor 1:
[Instrucción a ejecutar si la expresión regresa el valor indicado.]
caso Valor 2:
[Instrucción a ejecutar si la expresión regresa el valor indicado.]
caso Valor 3:
[Instrucción a ejecutar si la expresión regresa el valor indicado.]
otros:
[Instrucción a ejecutar si la expresión regresa un valor que no corresponde a ninguno de los casos.]
fin_según_sea

La estructura anterior muestra casos para 3 posibles valores pero se pueden especificar todos los casos que sean necesarios. También es posible indicar múltiples valores para cada caso, separados con una coma. El siguiente ejemplo usa una estructura 'según sea' con múltiples valores en cada 'caso' y con más de un 'caso' para cada valor con el fin de identificar si un estudiante de un curso es destacado y si aprobó el curso.

// Variable con la nota del estudiante usando 
// el mecanismo de evaluación con letras de 
// la A a la F
carácter nota_estudiante := 'B'

// Variable con el resultado del curso: tiene el 
// valor verdadero si el estudiante aprobó el curso
lógico curso_aprobado

// Variable con el estado del estudiante. Es 
// verdadera si el estudiante es destacado.
lógico estudiante_destacado

// Estructura de selección por casos.
según_sea nota_estudiante hacer
     caso 'A', 'B', 'C':
          curso_aprobado := verdadero
     caso 'D', 'E', 'F':
          curso_aprobado := falso
     caso 'A':
          estudiante_destacado := verdadero
     caso 'B', 'C', 'D', 'E', 'F':
          estudiante_destacado := falso
fin_según_sea

En este programa tenemos casos para todos los valores posibles de las notas de los estudiantes. Por eso no requerimos de una sección otros así que la omitimos.

Repetición[editar]

Las estructuras de repetición, también llamadas bucles o ciclos, permiten ejecutar la misma instrucción cero, una o múltiples veces. Además de la instrucción a ejecutar, tienen una sección de control. Esta sección de control, en conjunto con el cuerpo del ciclo, se encarga de ejecutar tres tareas necesarias para el correcto funcionamiento de la estructura: inicialización, comprobación y actualización. La inicialización consiste en establecer un estado que será modificado progresivamente hasta llegar a la condición de terminación. La comprobación consiste en comparar el estado inicial con el estado final deseado para determinar si se debe finalizar la ejecución del ciclo. Finalmente, la actualización consiste en modificar el estado inicial de forma que avance progresivamente hacia el estado final y permita que eventualmente la ejecución termine.[3]

Existen muchos tipos de estructuras de repetición y cambian significativamente entre ellas dependiendo del lenguaje de programación pero se pueden clasificar en dos tipos de estructuras principales: estructuras controladas por una condición y estructuras controladas por un contador.[4]

Ciclos controlados por una condición[editar]

Los ciclos controlados por una condición suelen tener la siguiente estructura:

mientras Expresión lógica hacer
Instrucción a ejecutar múltiples veces
fin_mientras

Con estos ciclos, el programa evalúa la expresión lógica y si esta es verdadera, ejecuta la instrucción en el cuerpo del ciclo y regresa la sección de control para comprobar la condición nuevamente. Este proceso continua hasta que en algún momento la expresión sea falsa. En ese momento el programa salta a la instrucción que sigue al final del ciclo.[4]

En este programa, se usa un ciclo mientras para calcular la primera potencia de 2 mayor a 1000.

// Declarando la variable.
entero potencia_de_2 := 2

// Ciclo para calcular el valor.
mientras potencia_de_2 <= 1000 hacer
    potencia_de_2 := potencia_de_2 * 2
fin_mientras

Un aspecto importante a tener en cuenta al trabajar con ciclos controlados por condiciones es que la instrucción en el cuerpo del ciclo debe modificar la condición de alguna manera para que eventualmente se evalúe como falsa y permita que el programa salga del ciclo. Si eso no ocurre, el ciclo se seguirá ejecutando indefinidamente y el programa nunca terminará.[4]

Ciclos controlados por un contador[editar]

La repetición controlada por un contador se usa cuando se conoce la cantidad de repeticiones que se desea ejecutar o al menos cuando esta es fija.[2] Este tipo de estructuras requiere una variable de control, típicamente de tipo entero, un valor inicial para la variable, un incremento o decremento y una condición que compruebe que la variable de control ha llegado al valor final deseado.[4]. Este tipo de estructuras suele tener la siguiente forma general:

desde Inicialización de la variable
hasta Valor final
incremento o decremento
paso Valor del cambio
hacer
Instrucción a ejecutar
fin_desde

La inicialización de la variable le asignará un valor antes de la primera ejecución del ciclo, una vez asignado, se comparará con el valor final. Si es menor a este, se procederá a ejecutar la instrucción en el cuerpo del ciclo. Una vez ejecutado, el programa aumenta o reduce el valor de la variable según la palabra clave indicada y lo hará por el monto indicado luego de la palabra paso. Una vez modificado el valor de la variable, se comprueba de nuevo para identificar si es necesario ejecutar el cuerpo del ciclo una vez más. La mayoría de los lenguajes asumen que se desea incrementar la variable si no se especifica una operación, de forma que solo es obligatorio especificar una operación si se desea decrementar la variable. También permiten omitir la palabra paso si el valor del cambio es 1, de forma que solo es necesario especificarla si se desean hacer cambios de más de una unidad.

El siguiente ejemplo usa un ciclo controlado por contador para sumar todos los números pares menores o iguales a 100.

// Variable para controlar el ciclo
entero i

// Variable para almacenar el resultado de la suma.
entero total_suma

// Ciclo para realizar el cálculo
// Se omite la palabra incremento ya que es la
// operación por defecto.
desde i := 2 hasta 100 paso 2 hacer
    total_suma := total_suma + i
fin_desde

Bloques de código[editar]

Los lenguajes de programación suelen definir las estructuras de control de flujo de forma que procesen solamente una instrucción en cada sección. Por eso los ejemplos mostrados hasta este momento solo tienen una instrucción en las diferentes secciones de las estructuras que usan. Sin embargo, la mayoría de los programas requerirá la ejecución de múltiples instrucciones. Para solventar ese problema introducen el concepto de bloque de código.[4]

Un bloque de código es una secuencia de varias instrucciones demarcada por indicadores especiales como las llaves ({ y }) o algunas palabras reservadas (por ejemplo inicio y fin). Generalmente es posible colocar un bloque de código en todos los lugares donde se puede colocar una instrucción individual.[4]

Otra función importante de los bloques de código es limitar la visibilidad de las variables, de forma que las variables declaradas en su interior no son visibles fuera de esa sección del programa. El bloque de código donde las variables están declaradas determina el alcance que tienen ya que no es posible usarlas fuera del mismo.[1] Esta función permite mejorar la organización de los programas, facilitar la detección de errores y reutilizar los mismos nombres de variables en diferentes secciones del programa. Las variables declaradas en un bloque se llaman «variables locales» a ese bloque y las variables declaradas en el programa principal se llaman «variables globales».[2] Es importante tener en cuenta que si se declara una variable local con el mismo nombre de una variable global o con el nombre de una variable local declarada en un bloque más externo, el compilador usará el nombre de la variable para referirse a la declarada en el bloque más interno y las otras variables no se podrán accesar.[1]

El siguiente ejemplo reescribe el ejemplo de la sección de iteraciones múltiples usando varias instrucciones en el cuerpo de cada caso. Para evitar el uso excesivo de palabras reservadas en los ejemplos, se utiliza el sangrado de las instrucciones para indicar que pertenecen al mismo bloque de código.

// Variable con la nota del estudiante usando 
// el mecanismo de evaluación con letras de 
// la A a la F
carácter nota_estudiante := 'B'

// Variable con el resultado del curso: tiene el 
// valor verdadero si el estudiante aprobó el curso
lógico curso_aprobado

// Variable con el estado del estudiante. Es 
// verdadera si el estudiante es destacado.
lógico estudiante_destacado

// Estructura de selección por casos.
según_sea nota_estudiante hacer
     caso 'A':
          curso_aprobado := verdadero
          estudiante_destacado := verdadero
     caso 'B', 'C':
          curso_aprobado := verdadero
          estudiante_destacado := falso
     caso 'D', 'E', 'F':
          curso_aprobado := falso
          estudiante_destacado := falso
fin_según_sea

Estructuras anidadas[editar]

Dado que las estructuras de control de flujo son instrucciones como cualquier otra, es posible colocarlas en las secciones de otras instrucciones de control de flujo donde se debe colocar una instrucción. Este mecanismo permite organizar las estructuras de forma anidada para resolver problemas complejos.[2] En el siguiente ejemplo se usa una estructura de selección doble dentro de una estructura de repetición para calcular dos valores diferentes de forma simultánea.

// Declaración de las variables.
entero total_pares := 0
entero total_impares := 0
entero i

// Ciclo para sumar los valores de los números del uno al 100
desde i := 1 hasta 100 hacer
    if i % 2 = 0 entonces
       total_pares := total_pares + i
    sino
        total_impares := total_impares + i
    fin_si
fin_desde

Resumen de la lección[editar]

  • La ejecución secuencial ejecuta un conjunto de instrucciones en el orden en que se encuentran en el código del programa.
  • La selección doble permite escoger un conjunto de instrucciones a ejecutar dependiendo del resultado de evaluar una expresión lógica.
  • La selección múltiple permite ejecutar diversos conjuntos de instrucciones dependiendo del valor de variables o expresiones de tipo no lógico.
  • La repetición controlada por una condición ejecuta un conjunto de instrucciones mientras la condición sea verdadera.
  • La repetición controlada por un contador ejecuta un conjunto de instrucciones una cantidad fija de repeticiones.
  • En todos los lugares donde se puede colocar una instrucción sencilla es posible colocar bloques de código con instrucciones múltiples.
  • Las estructuras de control de flujo se pueden anidar.

Términos clave[editar]

Lecturas adicionales[editar]

Bibliografía[editar]

  1. 1,0 1,1 1,2 1,3 1,4 Appleby, Doris; Vandekopple, Julius J. (1998). Programming Languages: Paradigm and practice [Lenguages de programación: Paradigma y práctica] (1.ª edición). México D. F., México: McGraw Hill. p. 492. ISBN 970-10-1945-8. 
  2. 2,0 2,1 2,2 2,3 2,4 2,5 2,6 2,7 Joyanes Aguilar, Luis (2013). Fundamentos generales de programación (1.ª edición). Ciudad de México, México: McGraw Hill. p. 368. ISBN 978-607-15-0818-8. 
  3. Brookshear, J. Glenn (2012). Computer Science: An overview [Introducción a la computación] (11.ª edición). Madrid, España: Pearson Educación, S. A. p. 704. ISBN 978-84-78-29139-7. 
  4. 4,0 4,1 4,2 4,3 4,4 4,5 Deitel, H. M.; Deitel, P. J. (1995). C How to program [Cómo programar en C/C++] (2.ª edición). México: Prentice Hall Hispanoamericana, S. A. p. 927. ISBN 968-880-471-1. 


Proyecto: Fundamentos de programación
Anterior: Segunda evaluación parcial — Control de flujo — Siguiente: Evaluación de la lección 7