Comprender el Control de Flujo Avanzado

Anuncio
Comprender el Control de Flujo Avanzado
Hasta ahora, hemos estado tratando con bucles individuales que sólo terminan cuando su
expresión booleano es evaluada como falsa . Ahora le mostraremos otras formas que
podrían terminar el bucle , o la rama ,y verá que el camino recorrido durante el tiempo de
ejecución puede no ser tan sencillo como en anteriores ejemplos.
Bucles anidados
En primer lugar , los bucles pueden contener otros bucles . Por ejemplo , considere el
siguiente código que itera a través de una matriz de dos dimensiones , una matriz que
contiene otras matrices así como sus miembros .Cubriremos las matrices
multidimensionales en detalle en el capítulo 3 , pero por ahora asuma que lo siguiente es
cómo se declare una matriz bidimensional .
int[][] myComplexArray = {{5,2,1,3},{3,9,8,9},{5,7,12,7}};
for(int[] mySimpleArray : myComplexArray) {
for(int i=0; i<mySimpleArray.length; i++) {
System.out.print(mySimpleArray[i]+"\t");
}
System.out.println();
}
Nótese que mezclamos intencionadamente un for y un for-each en este ejemplo .El bucle
exterior se ejecuta un total de tres veces . Cada vez que el bucle exterior se ejecuta, el
bucle interior se ejecuta cuatro veces. Cuando se ejecuta este código , vemos el siguiente
resultado :
5
3
5
2
9
7
1
8
12
3
9
7
Los bucles anidados pueden incluir while y do-while , como se muestra en este ejemplo .
Determinar que salida da este código.
int x = 20;
while(x>0) {
do {
x -= 2
} while (x>5);
x--;
System.out.print(x+"\t");
}
La primera vez este bucle se ejecuta , el bucle interno se repite hasta que el valor de x es
4. El valor será entonces decrementado a 3, y será la salida al final de la primera
iteración del bucle exterior . En la segunda iteración del bucle exterior , el interior do-while
se se ejecutará una vez , a pesar de que X ya no es mayor que 5. Como se recordará ,
do-while siempre ejecutan el cuerpo al menos una vez . Esto reducirá el valor a 1 ,que se
reducirá aún más por el operador de decremento en el bucle externo a 0. Una vez que el
valor alcance 0 , el bucle externo terminará. El resultado del código será el siguiente:
3
0
Adición de etiquetas opcionales
Una cosa que se saltó cuando presentamos if-them , switch, y los bucles es que todos
ellos pueden tener etiquetas opcionales . Una etiqueta es un puntero opcional a la cabeza
de una declaración que permite que el flujo de la aplicación salte a ella o rompa desde ella
. Es una sola palabra seguida de dos puntos ( :) . Por ejemplo , podemos añadir etiquetas
opcionales para uno de los anteriores ejemplos:
int[][] myComplexArray = {{5,2,1,3},{3,9,8,9},{5,7,12,7}};
OUTER_LOOP: for(int[] mySimpleArray : myComplexArray) {
INNER_LOOP: for(int i=0; i<mySimpleArray.length; i++) {
System.out.print(mySimpleArray[i]+"\t");
}
System.out.println();
}
Cuando se trata de un solo bucle , no añaden ningún valor , pero como veremos en la
siguiente sección ,son extremadamente útiles en entornos anidados.Las etiquetas
opcionales se utilizan a menudo solamente en estructuras de bucle . Si bien este tema no
está en el examen de OCA , es posible añadir etiquetas opcionales para estructuras de
control y bloques . Dicho esto , es raro que se considera una buena práctica de
codificación hacerlo.
Para el formato, las etiquetas siguen las mismas reglas que los identificadores . Para
facilitar la lectura , son comúnmente expresados en mayúsculas , con guiones entre
palabras , para distinguirlos de las variables regulares.
La sentencia break
Como se vio cuando se trabaja con las instrucciones switch , una sentencia break
transfiere el control de flujo fuera de la declaración de encerramiento . Lo mismo es cierto
para las sentencias break que aparecen en el interior de while, do-while , y para los bucles
, ya que terminará el bucle,como se muestra en la Figura 2.9
FIGURA 2 . 9 Estructura de una sentencia break
Observe en la figura 2.9 que la sentencia break puede tomar de parámetro una etiqueta
opcional .
Sin una etiqueta de parámetro, la sentencia break finalizará el bucle interno más cercano
en el proceso de ejecución . El parámetro de etiqueta opcional permite salir de un bucle
externo de nivel superior . En el siguiente ejemplo , buscamos las primeras ( x, y )
posiciones de índice de un array de un número dentro de una matriz de dos dimensiones
no clasificada:
public class SearchSample {
public static void main(String[] args) {
int[][] list = {{1,13,5},{1,2,5},{2,7,2}};
int searchValue = 2;
int positionX = -1;
int positionY = -1;
PARENT_LOOP: for(int i=0; i<list.length; i++) {
for(int j=0; j<list[i].length; j++) {
if(list[i][j]==searchValue) {
positionX = i;
positionY = j;
break PARENT_LOOP;
}
}
}
if(positionX==-1 || positionY==-1) {
System.out.println("Value "+searchValue+" not found");
} else {
System.out.println("Value "+searchValue+" found at: " +
"("+positionX+","+positionY+")");
}
}
}
Cuando se ejecuta, el código sería:
Value 2 found at: (1,1)
En particular , echar un vistazo al break PARENT_LOOP. Esta declaración romperá de
toda la estructura de bucle , tan pronto como se encuentra el primer valor . Ahora ,
imaginemos¿qué pasaría si sustituimos el cuerpo del bucle interno con lo siguiente:
if(list[i][j]==searchValue) {
positionX = i;
positionY = j;
break;
}
¿Cómo cambiaría esto nuestras flujo y cambiaría la salida ? En lugar de salir cuando el
primer valor coincidente se encuentra , el programa ahora solo saldrá del bucle interno
cuando se cumple la condición . En otras palabras, la estructura ahora hallará el primer
valor coincidente de el último bucle interno para contener el valor , dando como
resultado lo siguiente:
Value 2 found at: (2,0)
Por último , si hemos eliminado la ruptura por completo ?
if(list[i][j]==searchValue) {
positionX = i;
positionY = j;
}
En este caso , el código buscará el último valor de toda la estructura que tiene elvalor
coincidente . La salida tendrá el siguiente aspecto :
Value 2 found at: (2,2)
Se puede ver en este ejemplo que usar una etiqueta en una sentencia break en un bucle
anidado, o no usar la la sentencia break en absoluto, puede hacer que la estructura de
bucle se comporte de manera muy diferentemente.
La sentencia continue
Ahora vamos a completar nuestro análisis de control de bucle avanzado con la sentencia
continue , una declaración que hace que el flujo termine la ejecución del bucle , como se
muestra en la Figura 2.10 .
FIGURE 2 .10 The structure of a continue statement
Usted puede notar que la sintaxis de la instrucción continue refleja la de la sentencia
break .De hecho,las sentencias son similares en la forma en que se utilizan , pero con
diferentes resultados.Mientras que la sentencia break transfiere el control a la sentencia
que encierra , continue transfiere el control a la expresión booleana que determina si el
bucle debe continuar. En otras palabras , se termina la iteración actual del bucle. También
como break, continue se aplica al bucle interno más cercano en ejecución usando
etiquetas opcionales para modificar este comportamiento . Vamos a echar un vistazo al
siguiente ejemplo:
public class SwitchSample {
public static void main(String[] args) {
FIRST_CHAR_LOOP: for (int a = 1; a <= 4; a++) {
for (char x = 'a'; x <= 'c'; x++) {
if (a == 2 || x == 'b')
continue FIRST_CHAR_LOOP;
System.out.print(" " + a + x);
}
}
}
}
Con la estructura tal como se define , el bucle devolverá el control al bucle padre en el
momento que el primer valor es 2 o el segundo valor es b . Esto resulta en una ejecución
del bucle for-each interior por cada tres llamadas de bucle exteriores . La salida es el
siguiente :
1a 3a 4a
Ahora , imaginemos que hemos eliminado la etiqueta FIRST_CHAR_LOOP en la
sentencia continue para que continúe se devuelva el control al bucle interior en lugar del
exterior . Ver si se puede entender cómo la salida será cambiada a:
1a 1c 3a 3c 4a 4c
Por último , si quitamos la sentencia continue y las sentencias if-then asociadas por
completo ,llegamos a una estructura que da salida a todos los valores , tales como :
1a 1b 1c 2a 2b 2c 3a 3b 3c 4a 4b 4c
La Tabla 2.5 le ayudará a recordar cuando las etiquetas , break, y contiune estan
permitidas en Java . Aunque con fines ilustrativos nuestros ejemplos han incluido el uso
de estas sentencias en bucles anidados , pueden ser utilizadas dentro de los bucles
individuales también.
TABLE 2.5 Uso de control de flujo avanzado
* Las etiquetas están permitidas para cualquier sentencia de bloque , incluyendo los que
están precedidos con una sentencia if-then .
Descargar