Fundamentos de programación Tema 3. Estructuras de control Área de Lenguajes y Sistemas Informáticos Curso 2008-2009 1 Contenidos • Introducción a la programación estructurada • Estructuras de selección: if, else, switch • Estructuras de repetición: while, do/while, for • Enunciados break y continue. • Principios de la Programación Estructurada. 2 Introducción Programación imperativa o procedural: Programa: • Conjunto de instrucciones que se ejecutan de forma secuencial. • Saltos en el código, condicionales e incondicionales. Se usan variables que representan el contenido de las celdas de memoria. Se utilizan sentencias de asignación para cambiar el valor de las variables. Es la forma de programación que más se ajusta a la arquitectura del hardware. Existe una evolución histórica desde el paradigma imperativo al orientado a objetos: Prog. Imperativa → Estructurada → Modular (basada en objetos)→ Prog. Orientada a Objetos. 3 Introducción La programación imperativa es la forma de programar más antigua y la que mejor refleja la arquitectura de los microprocesadores. Sin embargo el uso indiscriminado de saltos en la secuencia del programa da lugar a: • Código spaghetti (la “infame” sentencia goto). • • Muy difícil de entender y mantener. En cuanto aumenta el tamaño de los proyectos se hace imposible su planificación y gestión. Se hacía absolutamente necesaria una estrategia para desarrollar y mantener eficientemente los programas Un nuevo paradigma de programación o una modificación del paradigma imperativo PROGRAMACIÓN ESTRUCTURADA 4 Introducción Se trata de: 1. Buscar una forma de estructurar los programas para que no sean un laberinto. 2. Desarrollar programas fáciles de entender por uno mismo y por los demás. La programación estructurada nace con el propósito de satisfacer ambos objetivos, para lo cual, entre otros principios, establece que: • Sólo se consideran tres estructuras de control: Secuencia, Selección y Repetición. • Todas ellas con un solo punto de entrada y un solo punto de salida. La idea fundamental es que los programas son un conjunto de bloques que encajan entre sí sobre la premisa de que cada bloque tiene un solo punto de entrada y un solo punto de salida, y la salida de uno se enchufa a la entrada del siguiente. 5 Estructuras de control de Java Java tiene 7 estructuras de control: Estructura de secuencia: Las instrucciones se ejecutan una a continuación de otra. Estructuras de selección: Se salta de una parte a otra del código según el cumplimiento de una condición. if if/else switch Estructuras de repetición: Se repite la ejecución de una instrucción o conjunto de instrucciones si se cumple una cierta condición. while do/while for • Todas estas estructuras cumplen los principios de la programación estructurada. • Los algoritmos de los programas Java se construyen a partir de estas estructuras de control combinadas de dos modos: Apilamiento y Anidamiento 6 Estructura de selección if Si se cumple la condición se Sentencia de selección única: if (condicion) sentencia_1; ejecuta la sentencia_1, si no, se salta hasta la siguiente instrucción. true Sentencia_1 condicion es una expresión lógica (booleana) cuyo resultado es verdadero (true) o falso (false) CONDICIÓN Ejemplo: if (calificación >= 5) false System.out.println(“Aprobado”); 7 Estructura de selección if/else Sentencia de selección doble: Si se cumple la condición se ejecuta la if (condicion) sentencia_1; else sentencia_2; sentencia_1, si no, ejecuta la sentencia_2. Ejemplo: S_2 false true condició condición S_1 if (calificación >= 5) System.out.println(“Aprobado”); else System.out.println(“Suspendido”); 8 Estructura de selección if/else Si se quiere indicar que se ejecuta más de una sentencia, hay que ponerlas entre llaves: if (condicion){ sentencia_1; sentencia-2; } else { sentencia_3; sentencia_4; sentencia_5; • ¡ No olvidar los paréntesis en la condición ! • ¡ No olvidar las llaves si hay más de una sentencia ! • ¡ Sangrar las sentencias para hacer el programa más legible ! } 9 if/else en cascada (I) if (calificación >= 9) System.out.println(“Sobresaliente”); else if (calificacion >= 7) System.out.println(“Notable”); else if (calificacion >= 5) System.out.println(“Aprobado”); else System.out.println(“Suspendido”); Para hacer el programa más legible se suele escribir: if (calificación >= 9) System.out.println(“Sobresaliente”); else if (calificacion >= 7) System.out.println(“Notable”); else if (calificacion >= 5) System.out.println(“Aprobado”) else System.out.println(“Suspendido”); 10 if/else en cascada (II) ¡¡ else siempre se refiere al if anterior !! if (x>5) if (y>5) System.out.println(“x e y son mayores que 5”); else System.out.println(“x es menor o igual que 5”); Pero lo que realmente pretendemos es esto: if (x>5){ if (y>5) System.out.println(“x e y son mayores que 5”); } else System.out.println(“x es menor o igual que 5”); 11 if/else en cascada (III) Errores típicos: Punto y coma mal colocado • Puede producir un error de lógica: if (nota >= 5); // No haría nada después de evaluar condición System.out.println(“Aprobado”); //Siempre se ejecuta • Puede producir un error de sintaxis: if (calificación>= 5); // if/else System.out.println(“Aprobado”); // Siempre else System.out.println(“Suspendido”); // ¿A qué acaba aquí se ejecuta if se refiere? 12 Estructura de selección switch Sentencia de selección múltiple: switch (expresión) { case valor_1: sentencia_1; break; case valor_2: sentencia_2; break; sí Caso a Acción a break Acción b break Acción i break no sí Caso b no ... case valor_i: sentencia_i; break; default: } sentencia_por_defecto; break; sí Caso i no La expresión después de cada case debe ser una expresión entera constante, es decir, una combinación de constantes de carácter y constantes enteras que al evaluarse produzca un valor entero constante. Una constante de carácter se representa como el carácter en cuestión encerrado entre apóstrofos: ´A´ 13 Estructura de selección switch (II) Particularidades de la estructura switch • ¿Qué ocurre si falta la palabra break? Si falta break se siguen ejecutando todas las sentencias en las que haya coincidencia hasta encontrar el siguiente break. Si no hay break se ejecutaría el default aunque haya habido coincidencia con otras antes. • La inclusión de un caso por defecto es opcional, pero es aconsejable ponerlo. • Después de cada caso (case) no se incluyen llaves { } aunque haya más de una sentencia. case valor_i: sentencia_a; sentencia_b; break; 14 Estructura de repetición while Permite al programador especificar que una acción se repita en tanto se cumpla una condición. while (condicion) sentencia; int producto = 2; while (producto <= 1000) while (condicion){ sentencia_1; ……… sentencia_n; } producto = 2 * producto; true CONDICIÓ CONDICIÓN Ejemplo: Encontrar la primera potencia de 2 mayor que 1000. Sentencia false 15 Estructura de repetición do/while Permite al programador especificar que una acción se repita en tanto se cumpla una condición. do sentencia; while (condicion); T do{ sentencia_1; …… sentencia_n; } while (condicion) Ejemplo: Encontrar la primera potencia de 2 mayor que 1000. int producto = 2; do producto = 2 * producto; while (producto <= 1000) F OBSERVACIONES: • Ojo con los bucles infinitos: hay que asegurarse de que la condición deja de cumplirse. • Diferencia con sentencia while: La sentencia o sentencias se ejecutan al menos una vez. La condición se comprueba después de haber realizado la primera iteración. 16 Estructura de repetición for (I) Repetición controlada por contador: for (inicialización del contador; condición; expresión incremento del contador) sentencia; Inicialización Incremento true for (inic. cont.; cond.; inc. cont.){ sentencia_1; …… sentencia_n; } Ejemplos: Variable de control de 7 a 77 en incrementos de 7. for (int i = 7; i <= 77; i += 7){…}; Variable de control de 99 a 0 en incrementos de -11 for (int i = 99; i >= 0; i = i - 11) {…}; Condició Condición Sentencia false Semántica (pasos): (1) (2) • • Se inicializa contador (sólo la primera vez). Se evalúa condición. Si true → ejecutar sentencias. Si false → a paso 5 (salir del bucle). (3) Se incrementa contador según expresión de incremento. (4) Volver al paso 2. (5) Salir del bucle. 17 Estructura de repetición for (II) Las tres expresiones de la estructura for son opcionales: • Se puede omitir la inicialización del contador si se ha inicializado antes. int i = 1; for( ; i < 10; i++) { ... } • Si se omite la comprobación de la condición, Java supone que la condición para continuar el ciclo se cumple, creándose un bucle infinito. for( ; ; i++) { ... } for( ; ; ) { ... } // Bucle infinito. Posible desbordamiento de i. // Bucle infinito. • La propia variable de control se puede utilizar dentro del cuerpo del for. for( ; i < 10; i++ ) { if ( i%2 == 0) { ... } // Se hace algo cuando i es par. } • El incremento del contador puede omitirse si se hace dentro del cuerpo del for. for( ; i < 10; ) { ... i++ ... } // Nada aconsejable. 18 Estructura de repetición for (III) Las expresiones de un for pueden contener expresiones aritméticas. Por ejemplo, int x = 2; int y = 10; for ( int j = 2; j <= 80; j += 5 ) System.out.println(j); for ( int j = x; j <= 4 * x * y; j += y / x ) System.out.println(j); Pero cuidado con las expresiones: Ambos bucles for son equivalentes si x e y no se modifican en el cuerpo del ciclo, pero el primero es claro y el segundo difícilmente comprensible. 19 Estructura de repetición for (IV) La sentencia for (int contador = 1; contador <= 10; contador ++) sentencia; es equivalente a: int contador = 1; while (contador <= 10) { sentencia; contador++; } Inicialización Incremento true Condició Condición Sentencia false Elección de una estructura de repetición: • Si número fijo de veces, elegir for • Si 1 o más veces, elegir do { } while { } • Si 0 o más veces, elegir while ( ) { } ¡ Se trata de elegir la que mejor se ajuste al concepto para mejorar la legibilidad ! 20 Break y continue en estructuras de repetición (I) La palabra reservada break en el cuerpo de un ciclo causa la terminación inmediata de dicho ciclo. Continue: Causa el salto a la int i = 0; int s = 0; while (i <= 5) { s = s + 1; for (int i = 0; i < 100; i++) { siguiente iteración del ciclo, pero sin salirse del ciclo . if (i % 2 == 1) continue; // Sólo se pasa aquí si i es par if ( s == 7) break; // sale // otras sentencias … i++; } // Se pasa aquí si i > 5 o // otras sentencias ... } s == 7 • En las estructuras while y do/while la condición para continuar el ciclo se evalúa inmediatamente después de ejecutarse continue. • En la estructura for se incrementa el contador y luego se evalúa la condición. 21 Break y continue en estructuras de repetición (II) Las siguientes porciones de código son equivalentes: for (int i = 1; // sentencia // sentencia } i <= 10; i++ ) { 1 n int i = 1; while ( i <= 10 // sentencia // sentencia i++; } ) { 1 n Pero las dos siguientes NO son equivalentes: for (int i = 1; // sentencia continue; // sentencia } // Incremento i <= 10; i++ ) { 1 n antes de continue. int i = 1; while ( i <= 10 ) { // sentencia 1 continue; // sentencia n i++; } // Incremento después del continue 22 break etiquetado • El enunciado break sólo causa la salida de la estructura while, do/while o for que lo encierra directamente. • Para salirnos de una serie de estructuras anidadas se usa el enunciado break etiquetado: • La ejecución del programa continúa con el primer enunciado después del enunciado compuesto etiquetado, el cual consiste en una serie de enunciados encerrados en llaves y precedidos por una etiqueta. // Enunciado compuesto rotulado o etiquetado stop: for (int fila = 1; fila <= 10; fila++) { for (int columna = 1; columna <= 5; columna++) { if (fila == 5) break stop; System.out.println(“Fila es menor que 5”); } } System.out.println(“La fila es 5”); 23 continue etiquetado • El enunciado continue continúa con la siguiente iteración de la estructura while, do/while o for que lo encierra directamente. • El enunciado continue etiquetado se salta el resto de los enunciados del cuerpo de la estructura de iteración que lo contiene y cualquier cantidad de estructuras de iteración que la encierren y continúa con la siguiente iteración de la estructura de repetición etiquetada. // Enunciado compuesto rotulado o etiquetado stop: for (int fila = 1; fila <= 10; fila++) { for (int columna = 1; columna <= 5; columna++) { if (fila == 5) continue stop; System.out.println(“Fila es distinta que 5”); } } System.out.println(“La fila es 10”); 24 Advertencias sobre break y continue break y continue suponen una violación de las reglas de la programación estructurada, si bien de alcance limitado. • El uso de break está justificado en pocas ocasiones. Puede evitarse con una escritura más cuidadosa de las condiciones de terminación del ciclo int i; char s; while (i <= 5 || s != ´a´) { if (s == ´a´) break; // Sentencias i++; } int i; char s; while (i <= 5 && s != ´a´){ // Sentencias i++; } Si hay más de una salida del ciclo del programa se hace más difícil de leer y analizar y se va en contra de los principios de la programación estructurada. 25 Advertencias sobre break y continue • El uso de continue puede evitarse con una escritura más cuidadosa del cuerpo del ciclo y de la expresión de incremento de la variable de control. for (int i = 0; i < 100; i ++) { if (i%2 == 1) continue; // Procesamiento según valor de i } for (int i = 0; i < 100; i += 2) { // Procesamiento según valor de i } • continue ayuda a reducir los niveles de anidado en el cuerpo de la estructura de iteración, • pero es peligroso si no se hacen explícitas las condiciones para ejecutar el resto del ciclo. // int a, b (declaradas antes) // posible bucle ∞ si b es cero al entrar while (a < 5){ if (b == 0) continue; continue; // otras sentencias; a++; } // int a, b (declaradas antes) while (a < 5) { if (b == 0){ a++; continue; } // otras sentencias; a++; } 26 Principios de la programación estructurada 1. Comenzar con el diagrama de flujo más sencillo. 2. Regla de apilamiento: Cualquier acción puede ser sustituida por dos o más acciones en secuencia. 3. Regla de anidamiento: Cualquier acción puede ser sustituida por cualquier estructura de control y sólo se consideran tres estructuras de control: • Secuencia. • Selección. • Repetición. Todas ellas con un solo punto de entrada y un solo punto de salida ¾ 4. Sólo hay una forma de entrar en cada estructura de control y sólo hay una forma de salir de ella. Las reglas 2 y 3 (apilamiento y anidamiento) pueden aplicarse tantas veces como se desee y en cualquier orden. 27