Está en la página 1de 14

ESTRUCTURAS DE CONTROL

PR UD2 – Tema 1

IES Armando Cotarelo Valledor


Adrián Fernández González
Tabla de contenido
1. Introducción .............................................................................................................................. 2
2. Operadores................................................................................................................................ 2
2.1. Operadores relacionales .................................................................................................... 2
2.2. Operadores condicionales o lógicos................................................................................... 3
2.2.1. Doble operador o simple. ............................................................................................ 3
2.2.2. Leyes de De Morgan .................................................................................................... 3
3. Instrucciones alterativas o condiciones .................................................................................... 4
3.1. If.......................................................................................................................................... 4
3.1.1. Else .............................................................................................................................. 4
3.1.2. Anidamiento y else if ................................................................................................... 5
3.2. Switch ................................................................................................................................. 5
3.3. Operador ternario. ?: ......................................................................................................... 7
4. Instrucciones iterativas o bucles ............................................................................................... 7
4.1. Por. For ............................................................................................................................... 7
4.1.1. Variable auxiliar. Pre-bucle ......................................................................................... 8
4.1.2. Condición..................................................................................................................... 8
4.1.3. Modificar valor. Post-bucle ......................................................................................... 8
4.1.4. Recorrer arrays ............................................................................................................ 8
4.2. Mientras. While .................................................................................................................. 8
4.3. Hacer mientras. Do-while................................................................................................... 9
4.4. Por cada. Foreach y for each .............................................................................................. 9
4.5. Break, continue y return .................................................................................................... 9
4.5.1. Break ........................................................................................................................... 9
4.5.2. Return ........................................................................................................................ 10
4.5.3. Continue .................................................................................................................... 11
4.6. Bucle infinito .................................................................................................................... 11
4.7. Anidamiento de bucles..................................................................................................... 12
5. Recursividad ............................................................................................................................ 12
5.1. Uso y optimización ........................................................................................................... 13
5.3. Desbordamiento de pila. Stack Overflow......................................................................... 13
Estructuras de control
1. Introducción
Las instrucciones son las órdenes que forman los programas, las operaciones que ha de
efectuar el ordenador.

Dos de las más esenciales son las alterativas y las repetitivas, también denominadas
estructuras de control, ya que modifican o controlan el flujo normal del programa.

2. Operadores
Tal como se vio anteriormente, existen varios tipos de operadores y, en cuestión de las
estructuras de control, los esenciales son los relacionales y los lógicos.

2.1. Operadores relacionales


Los operadores relacionales son aquellos que evalúan si se cumple o no una condición y
devuelven como resultado un valor booleano.

Igualdad: El operador de igualdad ‘==’ evalúa si ambos operandos son iguales.

En este caso, devolverá true si la variable de tipo char letr contiene la letra C.

Distinto: El operador distinto ‘!=’ evalúa si ambos operandos son distintos.

En este caso, devolverá true si la variable de tipo int num1 NO contiene el valor 5.

Cuantitativos: Estos operadores evalúan si un número es mayor ‘>’, menor ‘<’, mayor o igual
‘>=’ o menor o igual ‘<=’ a otro número.

En este ejemplo, la primera línea devuelve true si el valor de la variable de tipo int num1 es
mayor que 8. En el segundo caso, devolverá true si el valor de la variable num2 es menor o
igual al de la variable num3.

Hay que tener en cuenta que, en Java, un carácter puede ser transformado en un entero, ya
que cada uno tiene asignado un valor número en la tabla UNICODE, por lo que pueden ser
comparados cuantitativamente. En este sentido, por orden alfabético, la letra ‘a’ será menor
que la letra ‘b’ y la letra ‘A’ será menor que la ‘z’, ya que las mayúsculas van antes de las
minúsculas.
2.2. Operadores condicionales o lógicos
Los operadores condicionales o lógicos son los que evalúan valores booleanos entre sí.

Este tipo de operador permiten unir varias expresiones relacionales para realizar una condición
mayor.

AND: Más comúnmente ‘&&’. Evalúa que ambas expresiones son ciertas.

En este caso, devolverá true si la variable de tipo int num1 es mayor que 5 y es menor que 10.

OR: Más comúnmente ‘||’. Evalúa que alguna de las expresiones es cierta.

En este ejemplo, devolverá true si la variable de tipo char ltr contiene un carácter ‘A’ o ‘X’.

NOT: Invierte el valor booleano, pasando de true a false y viceversa.

En este caso, invierte el valor interior, devolviendo true si la variable de tipo char ltr no
contiene el carácter ‘A’ ni ‘X’.

2.2.1. Doble operador o simple.


Hay que tener en cuenta que no es lo mismo poner ‘&&’ que ‘&’ o ‘||’ que ‘|’. El símbolo doble
es la operación condicional, mientras que la simple es una operación binaria.

A nivel de condición, lo que hay que tener en cuenta es que, los dobles evalúan elemento a
elemento y si alguno cumple o incumple la condición, deja de leer, evitando posibles errores.

En este ejemplo, si num1 es menor que 5, ya no evalúa la siguiente parte, puesto que el
resultado será false automáticamente.

En este otro caso, si la variable ltr contiene el valor ‘A’, ya no sigue evaluando, ya que
automáticamente será true.

2.2.2. Leyes de De Morgan


Las leyes de De Morgan (por Augustus De Morgan) permiten resumir expresiones mediante la
equivalencia de negaciones e inversas.

La negación de la conjunción (AND) es la disyunción (OR) de las negaciones.

La negación de la disyunción (OR) es la conjunción (AND) de las negaciones.


Esto quiere decir que, si una expresión se niega, es igual a la negación de cada operando y la
inversión del operador que los une.

En este ejemplo, ambas expresiones son equivalentes, devolviendo el mismo resultado en las
mismas condiciones.

En este otro ejemplo sucede lo mismo. Hay que prestar especial atención a los operadores y
sus inversas.

3. Instrucciones alterativas o condiciones


Las instrucciones alterativas o condiciones, son aquellas que modifican la ejecución normal del
flujo del programa mediante condiciones. Dependiendo del valor de una serie de datos y
variables que evalúan, se ejecutan o no un grupo de instrucciones determinadas.

3.1. If
La sentencia if es la más sencilla, pues agrupa un conjunto de instrucciones que se ejecutan si
se cumple la condición establecida. En caso de que dicha condición no se cumpla, no hará
nada, y el programa seguirá tras el bloque de código.

En este caso, se mostrará el mensaje por pantalla si la variable de tipo int nota es igual o
mayor que 5.

3.1.1. Else
Con else se puede complementar el if, de tal forma que, si no se cumple la condición, se
realizan otras operaciones distintas.

En este caso, se mostrará por pantalla un mensaje u otro dependiendo de si se cumple o no la


condición.
3.1.2. Anidamiento y else if
Las condiciones se pueden anidar, de tal forma que se ponen una dentro de otra para verificar
un conjunto de condiciones.

En este caso, si la variable de tipo int nota es mayor que cinco, se comprueba si es igual a diez
y mostrará un mensaje u otro dependiendo de si cumple esa condición o no. En caso de que
sea menor que 5, verificará si es igual a 0 y mostrará un mensaje u otro dependiendo de esa
condición.

Como puede observarse, esto es aplicable tanto al if como al else.

Para abreviar, el else con un if en su interior se puede establecer mediante else if.

Este ejemplo es el mismo que el anterior, solo que con el else más compacto. Ambas
aproximaciones son igual de válidas, aunque hay un debate de qué resulta más legible.

3.2. Switch
La instrucción switch es una sentencia condicional múltiple, permite establecer múltiples
valores posibles para una expresión y actuar en consecuencia para cada uno de ellos.
La expresión o variable a evaluar se pone junto al switch, mientras que cada opción de valor se
establece con un case en el interior del switch.

Como puede observarse, dependiendo del valor de la variable tipo char letra, se efectuarán
unas operaciones u otras. En este caso, si establecen tres casos, si vale ‘a’, si vale ‘b’ o,
mediante el uso del default, si no cumple nada de lo anterior.

Las instrucciones switch son muy versátiles en sus opciones y ejecutarán línea a línea todo lo
que va desde el case que cumple hasta que se encuentra un break o termina el switch.

En este caso, si la variable de tipo String sistema tiene el valor “Linux” o “Ubuntu”, mostrará lo
mismo por pantalla, puesto que no hay un break que lo pare.
En este otro ejemplo, puede verse que se pueden realizar operaciones y continuar realizando
otras dependiendo de la condición.

En este caso, una persona tiene nombre, apellidos y edad, y un animal nombre y edad, por lo
que, se puede aprovechar el switch de tal forma que se tengan que repetir varias veces los
mensajes.

3.3. Operador ternario. ?:


El operador ternario es un tipo especial de operador que funciona como una instrucción
alterativa, de tal forma que, en base a una condición, devuelve un valor u otro.

Su escritura es sencilla, se pone la condición entre ‘()’, el signo de interrogación ‘?’, el resultado
en caso de que se cumpla la condición, los dos puntos ‘:’ y el resultado en caso de que no se
cumpla.

Como puede observarse, este operador permite realizar operaciones de forma más sencilla,
como la asignación o la muestra de datos por pantalla, entre otras muchas cosas.

El operador es completamente intercambiable con una instrucción if-else.

4. Instrucciones iterativas o bucles


Las instrucciones iterativas, como su nombre indica, permiten realizar un conjunto de
operaciones repetidas veces.

Existen varios tipos de bucles, cada uno con sus características y enfocados a un tipo de
operación, pero todo bucle tiene un inicio y un fin establecidos mediante una condición.

Cada una de las repeticiones de un bucle, se denomina iteración.

4.1. Por. For


El bucle for está diseñado para realizar operaciones un número determinado de veces, usando
una variable auxiliar como contador, que aumentará o disminuirá su valor en cada iteración.

Este bucle está formado por tres secciones pre-bucle, condición y post-bucle separadas por
punto y coma ‘;’. Estas secciones se suelen utilizar para la variable auxiliar, la condición y la
modificación del valor en cada iteración.

Las tres son opcionales, pero ha de respetarse su posición, funcionalidad y siempre aparecer el
punto y coma, esté o no dicha sección.
4.1.1. Variable auxiliar. Pre-bucle
La primera sección del bucle suele ser la creación e inicialización de variable auxiliar. Esta se
crea y se inicializa directamente en la sección, por lo que su ámbito solo es el propio bucle.

Como estándar de facto, se denomina i, aunque se puede estipular un nombre significativo.

4.1.2. Condición
La condición establece si se realiza otra iteración o no, evaluándose antes de realizar cada
iteración, incluyendo la primera. Mientras esta sea cierta, el bucle continuará.

Habitualmente, la condición suele conllevar evaluar si la propia variable auxiliar es menor o


mayor que un número determinado, lo que establece el número de iteraciones a realizar. Pese
a esto, puede ser una expresión tan compleja como se requiera.

4.1.3. Modificar valor. Post-bucle


El modificador del valor suele ser un incremento (++) o un decremento (--) en uno de la
variable auxiliar, pero puede estipularse otro tipo de modificación.

4.1.4. Recorrer arrays


El uso más común del bucle for es recorrer colecciones, como un array.

En este caso, se utiliza el bucle para mostrar por pantalla el valor de cada elemento del array.
Como puede observarse, se ha utilizado el atributo length para saber cuándo parar. Dado que
la longitud es el número de elementos, esta siempre es un número más que la última posición
del array, por lo que se compara con menor que y no menor o igual.

4.2. Mientras. While


El bucle while está diseñado para realizar operaciones mientras se cumpla una condición. Esta
se evalúa antes de realizar cada iteración, incluyendo la primera.

Su sintaxis es sencilla, tan solo la palabra reservada while seguido de la expresión a evaluar
entre paréntesis.

En este caso, es necesario realizar algo en el bucle que cambie el valor de esa condición para
que pare.
4.3. Hacer mientras. Do-while
El bucle do-while es similar al while, con la salvedad de que primero se ejecuta cada la
iteración y luego se evalúa la condición.

En este caso, la sintaxis está invertida, primero la palabra reservada do y al final, while y la
condición.

En este caso, aunque la variable que establece la condición es falsa, se realiza la primera
iteración del bucle igualmente, ya que esta se evalúa al final.

4.4. Por cada. Foreach y for each


El bucle for dispone de otro método de iteración comúnmente llamado for each. Este permite
recorrer una colección de elementos uno a uno sin importar los índices.

El bucle for each está diseñado para recorridos de lectura, en los que no importan índices ni
posiciones.

Su sintaxis tiene una forma fija, primero la palabra reservada for, luego una variable auxiliar
del mismo tipo que el tipo de la colección, luego dos puntos ‘:’ y luego la colección a recorrer.

En este ejemplo, se utiliza el bucle para recorrer un array de caracteres, concatenarlos en una
variable de tipo String y así formar la palabra “hola”.

4.5. Break, continue y return


Los bucles están diseñados para ejecutar un número de iteraciones y luego terminar, pero su
ejecución puede ser cortada o alterada antes de tiempo si se cumple alguna condición, por
ejemplo.

Esto es costoso para el sistema y solo ha de hacerse si el coste de no hacerlo es mucho mayor.

4.5.1. Break
Para terminar el bucle se utiliza el break, el cual rompe el bucle actual, como si la condición no
se cumpliese.
En este ejemplo, se busca un número en concreto entre 50 mil y, una vez encontrado, se
realizan las operaciones oportunas y se rompe el bucle. Esto se hace porque solo se necesita
ese dato en concreto y continuar con la ejecución es una pérdida de tiempo y recursos.

Hay que tener en cuenta que, si hay bucles anidados, solo cierra el actual, no toda la cadena.

4.5.2. Return
Un return en un método termina el método directamente una vez se encuentra, por lo que
puede utilizarse para terminar la ejecución de una operación bajo una circunstancia.

En este ejemplo, se busca un número en un array y, una vez encontrado, se lanza el return,
cortando todo el método.

El uso de un return para terminar una ejecución es mucho más eficiente que el uso de un
break, por lo que, suele ser preferible pasar la lógica a un método y romperla mediante un
return.

El uso de múltiples return no es intercambiable con el anidamiento de estructuras y el uso


correcto de if-else.
4.5.3. Continue
Continue permite saltarse la iteración actual, de tal forma que, aunque haya instrucciones
posteriores, no se ejecutarán en esa iteración.

En este caso, si la condición del if se cumple, el continue hará que salte a la siguiente iteración
sin mostrar el mensaje por pantalla ni lo que pudiese estar después.

4.6. Bucle infinito


Se denomina bucle infinito a aquel que nunca va a acabar porque su condición siempre será
cierta.

Este tipo de bucles colapsan el programa, ya que lo mantienen funcionando indefinidamente y


la única opción es cortar la ejecución del programa.

Por esto, es de vital importancia detectarlos mientras se crea y prueba el código, ya que
podrían echar abajo todo un sistema. Luego, habría que analizar todo el código del programa,
buscar el fallo y corregirlo, cosa que puede llevar tiempo durante el cual el sistema no
funcione.

Los IDE permiten cortar la ejecución mediante un botón en la consola de resultado/ejecución.

Nunca se ha de realizar un bucle infinito, si un diseño conlleva realizarlo y romperlo con un


break, por ejemplo, el diseño está mal.
4.7. Anidamiento de bucles
Los bucles, como cualquier otra estructura de control, se pueden anidar para realizar
recorridos más complejos, como puede ser el recorrido de elementos multinivel.

En este caso, hay que tener en cuenta que las variables auxiliares tienen que tener nombres
distintos, puesto que comparten ámbito del bucle externo.

Como los internos están dentro de los anteriores, tienen acceso a todo lo creado
anteriormente.

Cada iteración del bucle externo se realiza cuando se realizan todas las del interno.

En este ejemplo, se utilizan dos bucles for para recorrer una matriz, de tal forma que el primer
bucle recorre cada array de la matriz y el segundo, cada elemento de cada array.

Como puede observarse, la variable auxiliar interna, por estándar de facto, se denomina
siguiendo el alfabeto, aunque puede establecerse un nombre significativo.

5. Recursividad
La recursividad es el proceso por el cual un método se llama a sí mismo para realizar su misma
operación en un subconjunto de datos.

Estos métodos suelen ser cortos, de pocas líneas y siguiendo una misma estructura, un if con
una condición que parará la recursividad con un return (caso base) y en el else, la operación
recursiva realizada en un return.

En este ejemplo, el método devuelve un String con los num primeros números pares.

Por tanto, si se invoca pasándole por parámetro 4, devolverá “8 6 4 2”.

Su funcionamiento es inverso, es decir, primero se adentra en todas las llamadas recursivas


hasta el caso base y luego volverá en cascada hasta la llamada realizando las operaciones.
Dado que primero llama y luego devuelve realmente, todas las llamadas, todos los recursos
necesarios para la ejecución de cada llamada se almacenan en memoria, por lo que su coste es
muy alto. Pese a esto, el proceso es extremadamente rápido, por lo que, en ciertas
operaciones, compensa una cosa con la otra.

5.1. Uso y optimización


Todo algoritmo recursivo se puede realizar de forma iterativa y viceversa, aunque la primera
ha de reservarse para casos muy concretos, dado su alto coste de recursos.

Las operaciones en las que compensa son recorridos de ciertas estructuras, búsquedas,
ordenaciones y operaciones matemáticas. Normalmente, estas operaciones suelen ser muy
complejas de realizar mediante bucles y extremadamente simples de forma recursiva.

Hay que tener en cuenta que la llamada recursiva debe ser lo último a realizar, debe estar
dentro del return para que su coste sea menor, pues así están diseñado proceso.

Dado que todo el método va a repetirse una y otra vez y almacenarse en memoria, es de vital
importancia no crear nada en su interior, ni siquiera variables, o el coste será exponencial.

5.3. Desbordamiento de pila. Stack Overflow


La recursividad consume muchos recursos y, si el programa no dispone de suficiente memoria,
la máquina virtual de Java parará el proceso, lanzando java.lang.StackOverflowError.

Esto puede suceder por dos razones, o bien el proceso recursivo no está correctamente
confeccionado y nunca termina, o este proceso es demasiado extenso y la máquina virtual de
Java no dispone de suficiente memoria para realizarlo.

También podría gustarte