Fundamentos de programación Estructuras de Control Estructuras de control Estructuras de control Estructura secuencial Estructura alternativa Sentencias if, if – else Sentencias if – else anidadas El operador condicional ? : Sentencia switch Estructura iterativa Estructura for Estructura while Estructura do – while Bucles Sentencias break y continue Estructuras de control En programación, las estructuras de control marcan el flujo de ejecución de un programa (por tanto en C, de cada una de las funciones definidas). Existen tres estructuras de control básicas: • • • Secuencial Alternativa Repetición Estructura secuencial Sentencia compuesta: conjunto de instrucciones, encerradas entre llaves, que forman un bloque. { } sentencia_1; sentencia_2; ··· ··· ··· sentencia_n; El control fluye correlativamente de la sentencia_1 a la sentencia_2, después a la sentencia_3, y así sucesivamente. Cada sentencia sólo se ejecuta una vez. Estructura alternativa Alternativa simple if if (condición) sentencia; if (condición) { sentencia_1; sentencia_2; ··· ··· ··· sentencia_n; } Si la evaluación de la expresión es cierta (no cero), entonces se ejecuta la sentencia o grupo de sentencias. Si la expresión es falsa (evalua cero), se ignora la sentencia o grupo de sentencias, y se ejecuta la siguiente instrucción. Estructura alternativa Alternativa simple if #include <stdio.h> void main() { int a; scanf(“%d”, &a); if (a == 0) printf(“valor nulo\n”); printf(“Finalizar”); } Estructura alternativa Alternativa simple if #include <stdio.h> void main() { int a; scanf(“%d”, &a); if (a % 2) { printf(“El numero es impar\n”); a = a + 1; } printf(“El numero %d es par\n”, a); } Estructura alternativa Alternativa doble if-else if (condición) sentencia_1; else sentencia_2; if (condición) { grupo de sentencias_1; } else { grupo_de_sentencias_2; } Si la evaluación de la expresión es cierta (no cero), entonces se ejecuta la sentencia_1 o grupo de sentencias_1. Si la expresión es falsa (evalua cero), entonces se ejecuta la sentencia_2 o grupo de sentencias_2. Estructura alternativa Alternativa doble if-else #include <stdio.h> void main() { int a, b, max; scanf(“%d %d”, &a, &b); if (a > b) max = a; else max = b; printf(“El máximo es: %d\n”, max); } Estructura alternativa Alternativa múltiple if-else-if if (condición_1) { grupo_de_sentencias_1; } else if (condición_2) { grupo_de_sentencias_2; } ··· ··· ··· else if (condición_N) { grupo_de_sentencias_N; } else { grupo_de_sentencias_por_defecto; } • Evaluación secuencial de las condiciones. • Si ninguna condición es cierta ⇒ sentencias por defecto. • Uso adecuado de { } y sangrado/indentación ⇒ mejor legibilidad Estructura alternativa Sentencias if anidadas #include <stdio.h> void main() { int num; scanf(“%d”, &num); if (num == 0) printf(“Valor nulo\n”); else /* num > 0 ó num < 0 */ if (num > 0) printf(“Valor positivo\n”); else /* num < 0 */ printf(“Valor negativo\n”); } Estructura alternativa Alternativa múltiple if-else-if #include <stdio.h> void main() { int num; } scanf(“%d”, &num); if (num >= 0 && num < 20) printf(“De 0 a 19”); else if (num >= 20 && num < 30) printf(“De 20 a 29”); else if (num >= 30 && num < 40) printf(“De 30 a 39”); else printf(“Mayores que 40”); Estructura alternativa Alternativa doble if-else • Puede existir ambigüedad en anidaciones. • La parte else se asocia al if más cercano. • Para romper esta regla anterior se usa { } if (n > 0) if (a > b) z = a; else z = b; if (n > 0) { if (a > b) z = a; } else z = b; L1 El operador condicional ? : expresión_1 ? expresión_2 : expresión_3; c = (a > b) ? a : b; if (a > b) c = a; else c = b; Puede usarse en lugares donde no está permitido if-else: printf(“El minimo es %d \n”,(x < y) ? x : y); Diapositiva 15 L1 Ojo ver resultado expresiones de diferentes tipos LPSI; 03/11/2010 Estructura alternativa Estructura switch switch ( selector ) { case etiqueta: sentencias; case etiqueta: sentencias; ··· ··· ··· ··· case etiqueta: sentencias; } default: grupo_sentencias_por_defecto; Estructura alternativa • La expresión del selector debe ser de tipo ordinal (int, char o tipo enumerado). • La expresión del selector se evalúa y se compara con cada una de las etiquetas asociadas a case. • Cada etiqueta es un valor único y constante, y debe ser diferente de las otras etiquetas. • Si el valor del selector coincide con alguna de las etiquetas case, entonces se ejecutará el grupo de sentencias asociadas, hasta el final de la sentencia switch o hasta encontrar una sentencia break. • Es habitual que exista la parte default correspondiente al caso donde no hay coincidencia previa de etiqueta. Estructura alternativa Estructura switch switch ( expresión ) { case constante_1: grupo_de_sentencias_1; break;/* si se omite se ejecutan las sentencias del siguiente case */ case constante_2: grupo_de_sentencias_2; break; ··· ··· ··· case constante_N: grupo_de_sentencias_N; break; default: grupo_de_sentencias_por_defecto; break; } Estructura alternativa Estructura switch #include <stdio.h> void main() { int num; scanf(“%d”, &num); } switch (num) { case 1 : printf(“Uno\n”); break; case 2 : printf(“Dos\n”); break; ··· ··· ··· case 5 : printf(“Cinco\n”); break; default: printf(“No esperado\n”); break; } Estructura alternativa Estructura switch #include <stdio.h> void main() { char caracter; scanf(“%c”, &caracter); switch (caracter) { case ‘a’: case ‘b’: case ‘c’: printf(“Grupo a b c\n”); break; case ‘d’: case ‘e’: printf(“Grupo d e\n”); break; default : printf(“Otras letras\n”); break; } } Estructura iterativa Iterar es repetir un grupo de sentencias. En C el número de repeticiones siempre depende de una condición (expresión es su sentido amplio). Estructuras: for while do - while Estructura iterativa Estructura for for (expresión_1; expresión_2; expresión_3) sentencia; Tanto las expresiones como la sentencia son opcionales. Sinopsis de ejecución: 1. Ejecutar expresión_1 2. Si expresión_2 == 0 entonces FIN 3. Ejecutar sentencia 4. Ejecutar expresión_3 5. Ir al paso 2 Estructura iterativa Estructura for Σ 10 Calcular 3 i i=1 #include <stdio.h> void main() { int i, cubo, suma; } for (suma = 0, i = 1 ; i <= 10 ; i++) { cubo = i * i * i; suma += cubo; } printf(“La suma es %d\n”, suma); Estructura iterativa Estructura for • En bucles for de ciclo (con variable de control): - formato ascendente, la variable de control se incrementa. for (i = 0, j = 1; i < N; i++); - formato descendente, la variable de control se decrementa. for ( ; k; k -= 3); • Los intervalos de incremento/decremento de la variable o expresión de control pueden ser cualquier valor. Estructura iterativa Estructura while while (expresión) sentencia; Tanto las expresión como la sentencia son opcionales. Sinopsis de ejecución: 1. Si expresión == 0 entonces FIN 2. Ejecutar sentencia 3. Ir al paso 1 La estructura while es equivalente a for ( ; expresión ; ) sentencia; Estructura iterativa Estructura while /* Imprime hasta 10 */ int x = 0; /* inicialización variable */ while (x < 10) /* comprobación condición */ printf( “x : %d\n”, x++ ); /* El incremento de x modifica la condición */ Estructura iterativa Estructura while #include <stdio.h> void main() { int num, cont = 0, suma = 0; scanf(“%d”, &num); while (num != -1) { cont++; suma += num; scanf(“%d”, &num); } } if (cont) printf(“La media es %f\n”, suma/cont); else printf(“Secuencia vacia\n”); Estructura iterativa Estructura do-while do sentencia; while (expresión); do { grupo_de_sentencias; } while (expresión); Sinopsis de ejecución: 1. Ejecutar sentencia o grupo de sentencias 2. Si expresión == 0 entonces FIN 3. Ir al paso 1 La estructura do – while es equivalente a sentencia; while( expresión ) sentencia; Estructura iterativa Estructura do-while Verificar la entrada de un dígito. unsigned int digito; ··· ··· ··· do { printf(“Introducir un digito (0-9): ”); scanf(“%u”, &digito); } while (digito < 0 || digito > 9); ··· ··· ··· Estructura iterativa Estructura do-while #include <stdio.h> void main() { int num, cont = 0; do { scanf(“%d”, &num); if (num == 3) cont++; } while (num != -1); } printf(“El 3 aparece %d veces\n”, cont); Bucles • Bucles contador Se conoce con exactitud el número de datos que serán procesados antes de comenzar su ejecución. • Bucles suceso o condicionales No se conoce a priori cuántos datos se procesarán antes de comenzar su ejecución. ¾ Bucles centinela ¾ Bucles indicador Bucles Bucles centinela ¾ Un centinela es un dato específico (y distinto de los demás) que se utilizará como ULTIMO DATO a procesar por el bucle. ¾ La condición del bucle comprobará cada dato introducido, haciendo que éste termine cuando se alcance el valor centinela. Bucles Bucles centinela /* Suceso : Fin de datos cuando valor de nota == -1 */ const int centinela = -1; ··· ··· ··· printf(“Introducir primera nota: ”); scanf(“%d”, &nota); while (nota != centinela) { cuenta++; suma += nota; printf(“Introducir siguiente nota: ”); scanf(“%d”, &nota); } puts(“Se sigue con el proceso de notas”); ··· ··· ··· Bucles Bucles indicador ¾ Para controlar la ejecución del bucle, se utiliza un indicador de estado (generalmente en C se utiliza como indicador o bandera una variable entera que suele tomar los valores 0 - 1). ¾ El indicador se inicializa a un valor que permita ejecutar el bucle correctamente la primera vez. ¾ Un bucle controlado por indicador se ejecuta hasta que se produce un suceso anticipado, momento en el que se cambia el valor del indicador obligando a la terminación del bucle. Bucles Bucles indicador /* Suceso : El dato de entrada x debe ser positivo */ #include <stdio.h> #include <math.h> int main () { float x; int positivo = 0; /* inicialmente a falso */ while ( ! positivo ) /* comprobar indicador */ { scanf(“%f”, &x); positivo = (x > 0.0); /* actualizar indicador */ } } printf(“%f”,x * log(x)); return 0; Bucles Bucles habituales de captura de datos desde stdin while((c = getchar()) != EOF) ··· ··· ··· while(scanf(fmt, &x1, &x2,...) != EOF) ··· ··· ··· while(gets(buffer) != NULL) ··· ··· ··· ¾ c es una variable de tipo int. ¾ fmt es una cadena de formato. ¾ buffer es un array de caracteres. Bucles Contar nº de letras que hay en la entrada estándar #include <stdio.h> #include <ctype.h> void main() { int c, cont = 0; while((c = getchar()) != EOF) if(isalpha(c)) cont++; printf(“\n Numero de letras = %d\n”, cont); } Bucles Contar número de parejas par - impar consecutivas #include <stdio.h> void main() { int ant, act, nump = 0; } if(scanf(“%d”, &ant) != EOF); while(scanf(“%d”, &act) != EOF) { if(ant % 2 == 0 && act % 2 != 0) nump++; ant = act; } printf(“\n Numero parejas = %d\n”, nump); Sentencias break y continue • La sentencia break fuerza la salida inmediata de una sentencia iterativa (for, while, do-while). • Una sentencia break siempre provoca la salida del bucle más interno, es decir, sólo termina el bucle donde está situada la sentencia break. • La sentencia continue es menos común, y fuerza la siguiente iteración del bucle donde está situada. Sentencias break y continue /* Sumar enteros antes del primer negativo */ #include <stdio.h> void main() { int entero, suma = 0; for(;;) { scanf(“%d”,&entero); if (entero < 0) break; suma += entero; } /* ¿Que pasaría si no hay negativos? */ printf(“La suma es %d”, suma); } Sentencias break y continue /* Sumar enteros ignorando negativos, fin al leer un cero */ #include <stdio.h> void main() { int entero, suma = 0; for(;;) { scanf(“%d”,&entero); if (entero < 0) continue; if (entero == 0) break; suma += entero; } printf(“La suma es %d”, suma); }