Thursday, July 8, 2010

Estructuras de Control

Las estructuras de programación o estructuras de control permiten tomar decisiones y realizar un proceso repetidas veces. Son los denominados bifurcaciones y bucles. En la mayoría de los lenguajes de programación, este tipo de estructuras son comunes en cuanto a concepto, aunque su sintaxis varía de un lenguaje a otro. La sintaxis de Java coincide prácticamente con la utilizada
en C/C++, lo que hace que para un programador de C/C++ no suponga ninguna dificultad adicional.

Sentencias o expresiones


Una expresión es un conjunto variables unidos por operadores. Son órdenes que se le dan al computador para que realice una tarea determinada.
Una sentencia es una expresión que acaba en punto y coma (; ). Se permite incluir varias sentencias en una línea, aunque lo habitual es utilizar una línea para cada sentencia. Por ejemplo:

i = 0; j = 5; x = i + j;// Línea compuesta de tres sentencias



Comentarios


Existen dos formas diferentes de introducir comentarios entre el código de Java (en realidad son tres, como pronto se verá). Son similares a la forma de realizar comentarios en el lenguaje C++. Los comentarios son tremendamente útiles para poder entender el código utilizado, facilitando de ese modo futuras revisiones y correcciones. Además permite que cualquier persona distinta al
programador original pueda comprender el código escrito de una forma más rápida. Se recomienda acostumbrarse a comentar el código desarrollado. De esta forma se simplifica también la tarea de estudio y revisión posteriores.

Java interpreta que todo lo que aparece a la derecha de dos barras “//” en una línea cualquiera del código es un comentario del programador y no lo tiene en cuenta. El comentario puede empezar al comienzo de la línea o a continuación de una instrucción que debe ser ejecutada. La segunda forma de incluir comentarios consiste en escribir el texto entre los símbolos /*...*/. Este segundo
método es válido para comentar más de una línea de código. Por ejemplo:

// Esta línea es un comentario
int a=1; // Comentario a la derecha de una sentencia
// Esta es la forma de comentar más de una línea utilizando
// las dos barras. Requiere incluir dos barras al comienzo de cada línea
/* Esta segunda forma es mucho más cómoda para comentar un número elevado de líneas
ya que sólo requiere modificar
el comienzo y el final. */

En Java existe además una forma especial de introducir los comentarios (utilizando /**...*/ más algunos caracteres especiales) que permite generar automáticamente la documentación sobre las clases y packages desarrollados por el programador. Una vez introducidos los comentarios, el programa javadoc.exe (incluido en el JDK) genera de forma automática la información de forma
similar a la presentada en la propia documentación del JDK. La sintaxis de estos comentarios y la forma de utilizar el programa javadoc.exe se puede encontrar en la información que viene con el JDK.

Bifurcaciones


Las bifurcaciones permiten ejecutar una de entre varias acciones en función del valor de una expresión lógica o relacional. Se tratan de estructuras muy importantes ya que son las encargadas de controlar el flujo de ejecución de un programa. Existen dos bifurcaciones diferentes: if y switch.

Bifurcación if

Esta estructura permite ejecutar un conjunto de sentencias en función del valor que tenga la expresión de comparación (se ejecuta si la expresión de comparación tiene valor true). Tiene la forma siguiente:

if (booleanExpression) {
statements;
}


Las llaves {} sirven para agrupar en un bloque las sentencias que se han de ejecutar, y no son necesarias si sólo hay una sentencia dentro del if.

Bifurcación if else

Análoga a la anterior, de la cual es una ampliación. Las sentencias incluidas en el else se ejecutan en el caso de no cumplirse la expresión de comparación (false),

if (booleanExpression) {
statements1;
} else {
statements2;
}


Bifurcación if elseif else

Permite introducir más de una expresión de comparación. Si la primera condición no se cumple, se compara la segunda y así sucesivamente. En el caso de que no se cumpla ninguna de las comparaciones se ejecutan las sentencias correspondientes al else.

if (booleanExpression1) {
statements1;
} else if (booleanExpression2) {
statements2;
} else if (booleanExpression3) {
statements3;
} else {
statements4;
}


Véase a continuación el siguiente ejemplo:

int numero = 61;
// La variable "numero" tiene dos dígitos
if(Math.abs(numero) < 10)
// Math.abs() calcula el valor absoluto. (false)
System.out.println("Numero tiene 1 digito ");
else if (Math.abs(numero) < 100) // Si numero es 61, estamos en este caso (true)
System.out.println("Numero tiene 1 digito ");
else {
// Resto de los casos
System.out.println("Numero tiene mas de 3 digitos ");
System.out.println("Se ha ejecutado la opcion por defecto ");
}

Sentencia switch

Se trata de una alternativa a la bifurcación if elseif else cuando se compara la misma expresión con distintos valores. Su forma general es la siguiente:

switch (expression) {
case value1: statements1; break;
case value2: statements2; break;
case value3: statements3; break;
case value4: statements4; break;
case value5: statements5; break;
case value6: statements6; break;
default: statements7;
}


Las características más relevantes de switch son las siguientes:

1. Cada sentencia case se corresponde con un único valor de expression. No se pueden establecer rangos o condiciones sino que se debe comparar con valores concretos. El ejemplo del Apartado 2.3.3.3 no se podría realizar utilizando switch.

2. Los valores no comprendidos en ninguna sentencia case se pueden gestionar en default, que es
opcional.

3. En ausencia de break, cuando se ejecuta una sentencia case se ejecutan también todas las case que van a continuación, hasta que se llega a un break o hasta que se termina el switch.

Ejemplo:

char c = (char)(Math.random()*26+'a'); // Generación aleatoria de letras minúsculas
System.out.println("La letra " + c );
switch (c) {
case 'a': // Se compara con la letra a
case 'e': // Se compara con la letra e
case 'i': // Se compara con la letra i
case 'o': // Se compara con la letra o
case 'u': // Se compara con la letra u
System.out.println(" Es una vocal "); break;
default:
System.out.println(" Es una consonante ");
}

Bucles


Un bucle se utiliza para realizar un proceso repetidas veces. Se denomina también lazo o loop. El código incluido entre las llaves {} (opcionales si el proceso repetitivo consta de una sola línea), se ejecutará mientras se cumpla unas determinadas condiciones. Hay que prestar especial atención a los bucles infinitos, hecho que ocurre cuando la condición de finalizar el bucle (booleanExpression) no se llega a cumplir nunca. Se trata de un fallo muy típico, habitual sobre todo entre programadores poco experimentados.

Bucle while

Las sentencias statements se ejecutan mientras booleanExpression sea true.

while (booleanExpression) {
statements;
}


Bucle for

La forma general del bucle for es la siguiente:
for (initialization; booleanExpression; increment) {
statements;
}


que es equivalente a utilizar while en la siguiente forma,

initialization;
while (booleanExpression) {
statements;
increment;
}

La sentencia o sentencias initialization se ejecuta al comienzo del for, e increment después de statements. La booleanExpression se evalúa al comienzo de cada iteración; el bucle termina cuando la expresión de comparación toma el valor false. Cualquiera de las tres partes puede estar vacía. La initialization y el increment pueden tener varias expresiones separadas por comas. Por ejemplo, el código situado a la izquierda produce la salida que aparece a la derecha:

Código:

for(int i = 1, j = i + 10; i < 5; i++, j = 2*i) {
System.out.println(" i = " + i + " j = " + j);
}

Salida:

i = 1 j = 11
i = 2 j = 4
i = 3 j = 6
i = 4 j = 8


Bucle do while

Es similar al bucle while pero con la particularidad de que el control está al final del bucle (lo que hace que el bucle se ejecute al menos una vez, independientemente de que la condición se cumpla o no). Una vez ejecutados los statements, se evalúa la condición: si resulta true se vuelven a ejecutar las sentencias incluidas en el bucle, mientras que si la condición se evalúa a false finaliza el bucle.

Este tipo de bucles se utiliza con frecuencia para controlar la satisfacción de una determinada condición de error o de convergencia.

do {
statements
} while (booleanExpression);


Sentencias break y continue


La sentencia break es válida tanto para las bifurcaciones como para los bucles. Hace que se salga inmediatamente del bucle o bloque que se está ejecutando, sin sin realizar la ejecución del resto de las sentencias.

La sentencia continue se utiliza en los bucles (no en bifurcaciones). Finaliza la iteración “i” que en ese momento se está ejecutando (no ejecuta el resto de sentencias que hubiera hasta el final del bucle). Vuelve al comienzo del bucle y comienza la siguiente iteración (i+1).

Sentencias break y continue con etiquetas

Las etiquetas permiten indicar un lugar donde continuar la ejecución de un programa después de un break o continue. El único lugar donde se pueden incluir etiquetas es justo delante de un bloque de código entre llaves {} (if, switch, do...while, while, for) y sólo se deben utilizar cuando se tiene uno o más bucles (o bloques) dentro de otro bucle y se desea salir (break) o continuar con la siguiente
iteración (continue) de un bucle que no es el actual.

Por tanto, la sentencia break labelName finaliza el bloque que se encuentre a continuación de labelName. Por ejemplo, en las sentencias,

bucleI: // etiqueta o label

for ( int i = 0, j = 0; i < 100; i++){
while ( true ) {
if( (++j) > 5) { break bucleI; } // Finaliza ambos bucles
else { break; } // Finaliza el bucle interior (while)
}
}

La expresión break bucleI; finaliza los dos bucles simultáneamente, mientras que la expresión break; sale del bucle while interior y seguiría con el bucle for en i. Con los valores presentados ambos bucles finalizarán con i = 5 y j = 6 (se invita al lector a comprobarlo).
La sentencia continue (siempre dentro de al menos un bucle) permite transferir el control a un bucle con nombre o etiqueta. Por ejemplo, la sentencia,
continue bucle1;
transfiere el control al bucle for que comienza después de la etiqueta bucle1: para que realice una nueva iteración, como por ejemplo:
bucle1:
for (int i=0; ibucle2:
for (int j=0; j...
if (expression) continue bucle1; then continue bucle2;
...
}
}


Sentencia return

Otra forma de salir de un bucle (y de un método) es utilizar la sentencia return. A diferencia de continue o break, la sentencia return sale también del método o función. En el caso de que la función devuelva alguna variable, este valor se deberá poner a continuación del return (return value; ).

Bloque try {...} catch {...} finally {...}


Java incorpora en el propio lenguaje la gestión de errores. El mejor momento para detectar los errores es durante la compilación. Sin embargo prácticamente sólo los errores de sintaxis son detectados en esta operación. El resto de problemas surgen durante la ejecución de los programas.

En el lenguaje Java, una Exception es un cierto tipo de error o una condición anormal que se ha producido durante la ejecución de un programa. Algunas excepciones son fatales y provocan que se deba finalizar la ejecución del programa. En este caso conviene terminar ordenadamente y dar un mensaje explicando el tipo de error que se ha producido. Otras excepciones, como por ejemplo no
encontrar un fichero en el que hay que leer o escribir algo, pueden ser recuperables. En este caso el programa debe dar al usuario la oportunidad de corregir el error (definiendo por ejemplo un nuevo path del fichero no encontrado).

Los errores se representan mediante clases derivadas de la clase Throwable, pero los que tiene que chequear un programador derivan de Exception (java.lang.Exception que a su vez deriva de Throwable). Existen algunos tipos de excepciones que Java obliga a tener en cuenta. Esto se hace mediante el uso de bloques try, catch y finally.

El código dentro del bloque try está “vigilado”. Si se produce una situación anormal y se lanza como consecuencia una excepción, el control pasa al bloque catch, que se hace cargo de la situación y decide lo que hay que hacer. Se pueden incluir tantos bloques catch como se desee, cada uno de los cuales tratará un tipo de excepción. Finalmente, si está presente, se ejecuta el bloque finally, que es opcional, pero que en caso de existir se ejecuta siempre, sea cual sea el tipo de error.

En el caso en que el código de un método pueda generar una Exception y no se desee incluir en dicho método la gestión del error (es decir los bucles try/catch correspondientes), es necesario que el método pase la Exception al método desde el que ha sido llamado. Esto se consigue mediante la adición de la palabra throws seguida del nombre de la Exception concreta, después de la lista de argumentos del método. A su vez el método superior deberá incluir los bloques try/catch o volver a pasar la Exception. De esta forma se puede ir pasando la Exception de un método a otro hasta llegar al último método del programa, el método main().

En el siguiente ejemplo se presentan dos métodos que deben "controlar" una IOException relacionada con la lectura ficheros y una MyException propia. El primero de ellos (metodo1) realiza la gestión de las excepciones y el segundo (metodo2) las pasa al siguiente método:

void metodo1() {
...
try {
... // Código que puede lanzar las excepciones IOException y MyException
} catch (IOException e1) {// Se ocupa de IOException simplemente dando aviso
System.out.println(e1.getMessage());
} catch (MyException e2) {
// Se ocupa de MyException dando un aviso y finalizando la función
System.out.println(e2.getMessage()); return;
} finally {
// Sentencias que se ejecutarán en cualquier caso
...
}]
...
}
// Fin del metodo1


void metodo2() throws IOException, MyException {
...
// Código que puede lanzar las excepciones IOException y MyException
...
} // Fin del metodo2

Fuente: http://multiprogrammers.foroactivo.com/

0 comentarios:

Post a Comment