Fundamentos de Informática ETSII Tema 3: Estructuras de Selección. Departamento de Sistemas Informáticos y Computación Universidad Politécnica de Valencia Índice Introducción. Selección simple y doble: if, if... Instrucciones if anidadas. Detección de errores en la apertura de un fichero Selección múltiple: switch. 1
Objetivos Entender los conceptos de la ejecución condicional Conocer funcionamiento y utilización de sentencias if, if... empleadas de forma sencilla Combinar estructuras de selección switch break 1. Introducción secuencia_de_instrucciones = instrucción ; instrucción Instrucción: acción u operación del programa que conduce a la resolución del problema. Programa: secuencia de instrucciones separadas por ;. Bloque de instrucciones: conjunto de instrucciones encerrado entre llaves. 2
Ejemplo Orden de ejecución: secuencial. 1 int i=25, numero; printf( Dame un número ); 2 scanf( %d, &numero); 3 i = i + numero; 4 printf( Resultado=%d\n,i); 5 Cambio de la secuencia de ejecución de instrucciones Instrucciones de selección: se ejecutan unas instrucciones u otras según el valor de una condición. Condicionales: if, if-, switch. Incondicionales: goto No usarlo. Instrucciones de repetición (bucles): repite un conjunto de instrucciones un número determinado de veces. Condicionales: la secuencia de instrucciones se ejecuta hasta o mientras se cumple una determinada condición. Incondicional: la secuencia de instrucciones se repite un número determinado de veces. 3
Instrucción 1 Ejecución secuencial Instrucción 2 Instrucción 3 Ejecución secuencial: las instrucciones se ejecutan en el orden en que aparecen en el programa y una sola vez. Instrucción 1 Instrucción 2 Instrucción 3 Instrucción 1 Instrucción 2 Instrucción 3 Selección Bucle Selección condicional Determina qué conjunto de instrucciones se ejecutan de acuerdo con algún criterio definido por el programador. Tipos: Selección simple (if) Selección doble (if-) Selección múltiple (switch) 4
2. Selección simple y doble: if, if... Selección simple: if Selección doble: if- Selección simple: if if (condición) instrucción Si la condición es cierta se ejecutará la instrucción. Instrucción: puede ser una sentencia simple, un bloque de instrucciones (entre llaves) o sentencias compuestas. if (condición) instrucción if (condición) instrucción 1 instrucción 2 instrucción 3 Simple Bloque 5
Diagrama de flujo de la instrucción if Condición Cierto Instrucción Falso if (condición) instrucción; Resto de Instrucciones; Resto de instrucciones Ejemplo X>0 Cierto printf( Mayor que 0\n ); Falso if (x>0) printf( Mayor que 0\n ); printf( Adiós\n ); printf( Adios\n ); 6
Ejemplo Identación: lo que está dentro del if se pone con varios espacios delante. Sirve únicamente para ver rápidamente que hay dentro del if. if (n>0) printf ( Mayor que cero\n ); Cuando más de una instrucción está dentro del if se deben utilizar llaves if (edad>65) sueldo = SueldoActual*0.75+Complementos; printf( Lo que cobras es %f\n, sueldo); Ejemplo int n=0; if (n>0) n++; n = n+25; printf( n=%d\n, n); int n=0; if (n>0) n++; n = n+25; printf( n=%d\n, n); int n=0; if (n>0); n++; n = n+25; printf( n=%d\n, n); n=25 n=0 n=26 7
Ejemplo Leer la edad de dos personas y decir cuál es la de mayor edad. #include <stdio.h> El cuerpo del if contiene una única instrucción, por lo que no hace falta poner int n1, n2; llaves. printf( Introduce las edades: ); scanf( %d%d, &n1, &n2); if (n1>n2) printf( La edad de la mayor es %d años.\n,n1); if (n1<n2) printf( La edad de la mayor es %d años.\n,n2); if (n1==n2) printf( Tienen la misma edad: %d años.\n,n1); Ejemplo Leer un número del fichero valores.txt encuentra en c:\temp y decir si es positivo. #include <stdio.h> int x; FILE *f; f=fopen( c:\\temp\\valores.txt, r ); fscanf(f, %d, &x); if (x>0) printf( El número %d es positivo,x); fclose(f); que se 8
Selección doble: if- if (condición) instrucción_1 instrucción_2 Instrucción_1, instrucción_2: pueden ser una instrucción simple, un bloque de instrucciones (entre llaves), o instrucciones compuestas. Si la condición es cierta se ejecutará instrucción_1, si es falsa se ejecutará instrucción_2. Sólo se ejecutará una sentencia, no ambas. Diagrama de flujo de la instrucción if.. if (condición) instrucción_cierto; instrucción_falso; Resto de Instrucciones; 9
Ejemplo Cierto printf( Positivo\n ); X>=0 Falso printf( Negativo\n ); if (x>=0) printf( Positivo ); printf( Negativo ); printf( Adiós\n ); printf( Adiós\n ); Ejemplo #include <stdio.h> int x; printf( Dame un número: ); scanf( %d, &x); if (x>=0) printf( El número %d es positivo, x); /* Bloque cierto*/ printf( El número %d es negativo, x); /* Bloque falso*/ Cuando el bloque sólo contiene una única instrucción, pueden omitirse las llaves 10
Ejemplo #include <stdio.h> int x; printf( Dame un número ); scanf( %d,&x); if (x>=0) printf( El número %d es positivo,x); /* Bloque verdadero*/ if (x<0) printf( El número %d es negativo,x); /* Bloque verdadero*/ Condiciones complementarias 3. Instrucciones if anidadas if (n >0) printf( El número %d es mayor que 0\n, n); Un if con su, es if (n == 0) una única instrucción, por eso no se ponen printf( Es 0\n ); llaves printf( El número %d es menor que 0\n,n); 11
Ejemplo int edad; printf( Dime tu edad: ); scanf( %d,&edad); if (edad>=18) if (edad<=65) printf( Trabajador.\n ); El cuerpo del primer if contiene una única instrucción, por lo que no hacen falta llaves. Un if con su correspondiente es una instrucción. El cuerpo del segundo if contiene más de una instrucción, por lo que hacen falta llaves. printf( Solicitar los datos del contrato.\n ); printf( Jubilado.\n ); Ejercicio Pedir al usuario un número A. Si el número A es positivo: Pedir un número B. Si es positivo: Calcular la suma, resta, producto, división y resto de ambos. Mostrar los resultados por pantalla. 12
#include <stdio.h> int A, B; printf( Introduce un valor: ); scanf( %d, &A); if (A>0) El cuerpo del if contiene más de una instrucción, printf( Introduce otro valor: ); por lo que hacen falta scanf( %d, &B); llaves. if (B>0) printf( %d + %d = %d\n, A, B, A+B); printf( %d - %d = %d\n, A, B, A-B); printf( %d * %d = %d\n, A, B, A*B); printf( %d / %d = %d\n, A, B, A/B); printf( %d % %d = %d\n, A, B, A%B); Diagrama de flujo Condición_1 Cierto Falso Sentencia_Cierto_1 Condición_2 Cierto Falso Sentencia_Cierto_2 Sentencia_Falso_2 if (condición_1) sentencia_cierto_1 if (condición_2) sentencia_cierto_2 sentencia_falso_2 Resto de Instrucciones 13
Si no hay llaves, un siempre va con el último if escrito. if (edad>=0) if (edad>=18) printf( Mayor de edad\n ); printf( Menor de edad\n ); Si se quiere variar esta situación, poner llaves. if (edad>=0) if (edad>=18) printf( Mayor de edad\n ); printf( Edad incorrecta\n\n ); 14
Ejercicio Cuál es la salida por pantalla de estos programas? int a=1; if (a==0) printf( Es cero\n ); printf( No es cero\n ); printf( a=%d\n,a); int a=1; if (a=0) printf( Es cero\n ); printf( No es cero\n ); printf( a=%d\n,a); No es cero a=1 No es cero a=0 Ejercicio Resolver una ecuación de primer grado ax+b=0 Análisis de las soluciones: Si a!=0 solución x=-b/a Si a==0 b!=0 solución imposible. b==0 solución indeterminada 15
#include <stdio.h> float a, b; printf( Dame las incógnitas de la ecuación ax+b=0: ); scanf( %f%f, &a, &b); if (a!=0) printf( El resultado es: %f,-b/a); if (b!=0) printf( La solución es imposible ); printf( La solución es indeterminada ); #include <stdio.h> float a,b; printf( Dame las incógnitas de la ecuación ax+b=0: ); scanf( %f%f,&a,&b); if (a!=0) printf( El resultado es: %f,-b/a); if (b!=0) printf( La solución es imposible ); printf( La solución es indeterminada ); Versión que no utiliza identación 16
Ejemplo #include <stdio.h> float a,b; Para evitar la anidación, se desglosan las condiciones explícitamente. Resultado más complejo de escribir y más lento de ejecutar printf( Déme las incógnitas a y b de la ecuación ax+b=0: ); scanf( %f%f,&a,&b); 1 if (a!=0) printf( El resultado es: %f,-b/a); Realiza 5 2 if ((a==0) && (b!=0)) 3 comparaciones printf( La solución es imposible ); frente las 2 del 4 if ((a==0) && (b==0)) 5 programa anterior. printf( La solución es indeterminada ); Ejercicio Calcular el mayor de tres números enteros introducidos por teclado. 17
#include <stdio.h> int a, b, c; printf( Dime tres números: ); scanf( %d%d%d, &a, &b, &c); Versión sin anidación: 18 comparaciones if (a==b && b==c) printf( Iguales\n ); if (a==b && b<c) printf( El mayor es %d\n,c); if (a==b && b>c) printf( El mayor es %d\n,b); if (a>b && a>=c) printf( El mayor es %d\n,a); if (a>b && a<c) printf( El mayor es %d\n,c); if (a<b && b>=c) printf( El mayor es %d\n,b); if (a<b && b<c) printf( El mayor es %d\n,c); system( PAUSE ); #include <stdio.h> int a, b, c; printf( Dime tres números: ); scanf( %d%d%d, &a, &b, &c); if (a==b) if (b==c) printf( Iguales\n ); if (b<c) printf( El mayor es %d\n,c); printf( El mayor es %d\n,b); if (a>b) if (a>=c) printf( El mayor es %d\n,a); printf( El mayor es %d\n,c); if (b>=c) printf( El mayor es %d\n,b); printf( El mayor es %d\n,c); system( PAUSE ); Versión con anidación: 7 comparaciones 18
#include <stdio.h> int a, b, c, mayor; printf( Dime tres números: ); scanf( %d%d%d, &a, &b, &c); Otra versión con anidación: 2 comparaciones if (a>=b) mayor = a; mayor = b; If (c>mayor) mayor = c; printf( El mayor es %d\n,mayor); system( PAUSE ); Ejercicio Se desea diseñar un programa en C que lea desde teclado una calificación alfabética: A, B, C, D, E y la convierta en la numérica: 10, 8, 6, 5, 0 19
#include <stdio.h> char nota; printf( Déme una calificación: ); scanf( %c,¬a); if ((nota< A ) (nota> E )) printf( Calificación desconocida ); if (nota== A ) printf( La nota es 10 ); if (nota== B ) printf( La nota es 8 ); if (nota== C ) printf( La nota es 6 ); if (nota== D ) printf( La nota es 5 ); if (nota== E ) printf( La nota es 0 ); Ejercicio La fecha del domingo de Pascua corresponde al primer domingo después de la primera luna llena que sigue al equinoccio de primavera. Dado un año, los cálculos que permiten conocer esta fecha son: A = año %19 B = año % 4 C = año % 7 D = (19 * A + 24) % 30 E = (2 * B + 4 * C + 6 * D + 5) % 7 N = (22 + D + E) Donde N indica el número del día del mes de marzo (o abril si N es superior a 31) correspondiente al domingo de Pascua. Escribir un programa que lea un año y muestre el día y el mes en el que se celebró o se celebrará el domingo de Pascua ese año. 20
Por ejemplo: si introducimos el año 2002, los cálculos son los siguientes: A = 2002 % 19 = 7 B = 2002 % 4 = 2 C = 2002 % 7 = 0 D = (19 * 7 + 24) % 30 = 157 % 30 = 7 E = (2 * 2 + 4 * 0 + 6 * 7 + 5) % 7 = 51 % 7 = 2 N = (22 + 7 + 2) = 31 Es decir, el año 2002 el domingo de Pascua fue el 31 de marzo. #include <stdio.h> int anyo, a, b, c, d, e, n; printf ("Introduce un año:"); scanf ("%d", &anyo); a = anyo % 19; b = anyo % 4; c = anyo % 7; d = (19 * a + 24) % 30; e = (2 * b + 4 * c + 6 * d + 5) % 7; n = 22 + d + e; 21
if (n<=31) printf ("El Domingo de Pascua del año %d es el %d de marzo\n", anyo, n); printf ("El Domingo de Pascua del año %d es el %d de abril\n", anyo, n-31); system( PAUSE ); Ejercicio Calcular el máximo de 4 números introducidos por teclado. Nota: pensar un método diferente al problema del máximo de 3 números enteros. Entrada: Salida: 4 valores el valor máximo de los cuatro 22
Algoritmo Entrada P R O C E S O Salida Pedir los valores al usuario (valor1, valor 2, valor3, valor4) Tomar el primer valor como el máximo actual (máximo=valor1) Si el segundo valor es mayor que el máximo actual El nuevo máximo es el segundo valor (máximo=valor2) Si el tercer valor es mayor que el máximo actual El nuevo máximo es el tercer valor (máximo=valor3) Si el cuarto valor es mayor que el máximo actual El nuevo máximo es el cuarto valor (máximo=valor4) Mostrar por pantalla el valor máximo #include <stdio.h> void main () float a, b, c, d, maximo; /* Lectura de datos */ printf ("Introduzca los 4 números: \n"); scanf ("%f%f%f%f", &a, &b, &c, &d); /* Calculo */ maximo = a; if (b > maximo) maximo = b; if (c > maximo) maximo = c; if (d > maximo) maximo = d; /* Escritura de resultados */ printf ("El número máximo es: %f\n", maximo); 23
4. Detección de errores en la apertura de un fichero Cómo saber si el fichero se ha abierto correctamente? Si el fichero no se puede abrir, fopen retorna NULL. FILE *fichero; if ((fichero = fopen ( c:\\temp\\prueba.txt, r ))==NULL) printf( Fichero no existe\n ); fichero = fopen ( c:\\temp\\prueba.txt, r ); If (fichero==null) printf( Fichero no existe\n ); Ejercicio Abrir el fichero pepito.txt para lectura. Leer un valor entero y cerrarlo. Detectar si se ha abierto correctamente el fichero. int x; FILE *f; if ((f=fopen( pepito.txt, r ))==NULL) printf( No se puede abrir el fichero\n ); fscanf(f, %d, &x); fclose(f); 24
Ejercicio Leer la edad de 2 personas de un fichero edad.txt. Mostrarlas ordenadas de menor a mayor en el fichero salida.txt. void main () FILE *e, *s; int edad1, edad2; if ((e=fopen( edad.txt, r ))==NULL) printf( No se puede abrir el fichero edad.txt.\n ); if ((s=fopen( salida.txt, w ))==NULL) printf( No se puede abrir el fichero salida.txt.\n ); fscanf (e, %d%d, &edad1, &edad2); if (edad1>=edad2) fprintf (s, %d - %d\n, edad2, edad1); fprintf (s, %d - %d\n, edad1, edad1); fclose(s); fclose(e); 25
5. Selección múltiple: switch Permite seleccionar entre múltiples caminos sin necesidad de anidar y evaluando una única expresión switch (expresión) case valor1: instrucciones_1; break; case valor2: instrucciones_2; break;... default: instrucciones_n; break; Ejemplo int opc; printf( 1. Ingreso.\n ); printf( 2. Reintegro.\n ); printf( 3. Consulta de saldo.\n ); scanf( %d,&opc); switch (opc) case 1: printf( Ha elegido ingreso.\n ); break; case 2: printf( Ha elegido reintegro.\n ); break; case 3: printf( Ha elegido consulta.\n ); break; default: printf( Opción incorrecta.\n ); Aunque haya más de una instrucción dentro de cada case, no hay que poner llaves. 26
Propiedades Sólo se puede seleccionar en base a la evaluación de una única expresión. La evaluación de la expresión de switch siempre debe generar un único valor (entero o char). Los valores de cada case debe ser constantes. No se puede utilizar nombres de variables. La ejecución de un case no para hasta que encuentra un break (o finaliza), sobrepasando incluso otros case. Ejemplo #include <stdio.h> char nota; printf( Déme una calificación: ); La expresión es de scanf( %c, ¬a); tipo carácter switch (nota) case A : printf( La nota es 10 ); break; case B : printf( La nota es 8 ); break; case C : printf( La nota es 6 ); break; case D : printf( La nota es 5 ); break; case E : printf( La nota es 0 ); break; default : printf( Nota desconocida ); 27
Ejemplo char c; printf( Opción: ); scanf( %c,&c); switch (c) case 1 : break; case 2 : break; case 3 : break; default: printf( Elegida opción 1.\n ); printf( Elegida opción 2.\n ); printf( Elegida opción 3.\n ); printf( Opción incorrecta.\n ); La expresión es de tipo carácter Ejemplo int c; printf( Opción: ); scanf( %d,&c); switch (c) case 1: break; case 2: break; case 3: break; default: printf( Elegida opción 1.\n ); printf( Elegida opción 2.\n ); printf( Elegida opción 3.\n ); printf( Opción incorrecta.\n ); La expresión es de tipo entero 28
Ejemplo, NO se puede: #include <stdio.h> float nota; printf( Déme una calificación: ); scanf( %f,¬a); switch (nota) case (nota<5.0): printf( La nota es 4 ); break; case 5.0: printf( La nota es 5 ); break; case 6.0: printf( La nota es 6 ); break; case 7.0: printf( La nota es 7 ); break; case 8.0: printf( La nota es 8 ); break; case 9.0: printf( La nota es 9 ); break; default : printf( Nota desconocida ); La expresión debe ser int o char El valor de case debe ser constante, no puede ser una expresión, no puede contener variables Ejemplo Qué muestra por pantalla este programa si se elige cada una de las opciones? int c; printf( Opción: ); scanf( %d,&c); switch (c) case 1: printf( Elegida opción 1.\n ); case 2: printf( Elegida opción 2.\n ); case 3: printf( Elegida opción 3.\n ); default: printf( Opción incorrecta.\n ); Opción 1: Elegida opción 1. Elegida opción 2. Elegida opción 3. Opción incorrecta. Opción 2: Elegida opción 2. Elegida opción 3. Opción incorrecta. Opción 3: Elegida opción 3. Opción incorrecta. Otra opción: Opción incorrecta. 29
Ejercicio poner otro Mostrar al usuario un menú por pantalla con las opciones: 1. Suma 2. Resta 3. Producto 4. División 5. Salir Solicitar los valores al usuario y realizar la operación elegida. int opc, a, b; printf( 1. Suma\n ); printf( 2. Resta\n ); printf( 3. Multiplicación\n ); printf( 4. División\n ); scanf( %d,&opc); scanf( %d%d, &a,&b); switch(opc) case 1: printf( %d + %d = %d\n, a, b, a+b); break; case 2: printf( %d - %d = %d\n, a, b, a-b); break; case 3: printf( %d * %d = %d\n, a, b, a*b); break; case 4: if (b!=0) printf( %d / %d = %d\n, a, b, a/b); break; default: printf( Opción incorrecta\n ); 30
Ejercicio Convertir un valor numérico en una nota: suspendido, aprobado, notable, sobresaliente, matricula, etc... Valores: [0-5[ corresponde a Suspendido [5-7[ corresponde a Aprobado [7-9[ corresponde a Notable [9-10[ corresponde a Sobresaliente 10 corresponde a Matricula. Hacerlo con if (anidados y no anidados) y con switch. int nota; printf( Déme una calificación ); scanf( %d,¬a); if ((nota<0) (nota>10)) printf( Calificación desconocida ); if ((nota>0) && (nota<5)) printf( Nota %d = Suspenso,nota); if ((nota>=5) && (nota<7)) printf( Nota %d = Aprobado,nota); if ((nota>=7) && (nota<9)) printf( Nota %d = Notable,nota); if ((nota>=9) && (nota<10)) printf( Nota %d = Sobresaliente,nota); if (nota==10) printf( Nota %d = Matricula,nota); Versión con if 31
int nota; printf( Déme una calificación ); scanf( %d,¬a); Versión con if anidados if ((nota<0) (nota>10)) printf( Calificación desconocida ); if (nota<5) printf( Nota %d = Suspenso,nota); if (nota<7) printf( Nota %d = Aprobado,nota); if (nota<9) printf( Nota %d = Notable,nota); if (nota<10) printf( Nota %d = Sobresaliente,nota); printf( Nota %d = Matricula,nota); int nota; printf( Déme una calificación ); scanf( %d,¬a); switch (nota) Versión con case 0: switch case 1: case 2: case 3: case 4: printf( Nota %d = Suspendido,nota); break; case 5: case 6: printf( Nota %d = Aprobado,nota); break; case 7: case 8: printf( Nota %d = Notable,nota); break; case 9: printf( Nota %d = Sobresaliente,nota); break; case 10: printf( Nota %d = Matricula,nota); break; default : printf( Nota desconocida ); 32
Inconvenientes de switch No se puede emplear cuando la elección está basada en una comparación de variables o expresiones de tipo float. No se puede usar cuando la variable está comprendida en un cierto rango y no es un valor concreto. Se deben usar constantes como etiquetas, no variables. En general, switch es más eficiente que if. Ejemplo if (n < 100 && n > 2)... switch (n) case 3: case 4:... case 99:... La versión con if es más corta y más eficiente. Con switch hay que escribir todos los posibles valores. 33
Ejercicio Escribir un programa que construya una calculadora básica. Debe mostrarse un menú con las siguientes opciones: suma, resta, multiplicación, división, raíz cuadrada y potencia. Se debe de elegir una operación. Para la opción elegida se piden y validan los datos de la opción correspondiente y se realiza la operación correspondiente. Utilizar: Función sqrt(a): obtiene la raíz cuadrada de a. Función pow(a, b): obtiene a elevado a b. 34
Algoritmo Mostrar el menú. Pedir al usuario la opción del menú. Realizar la operación según la opción: Si la operación es sumar: Pedir dos valores al usuario Sumarlos Si la operación es restar: Pedir dos valores al usuario Restarlos Si la operación es multiplicar: Pedir dos valores al usuario Multiplicarlos Si la operación es dividir: Pedir dos valores al usuario Si divisor 0 Dividirlos Si la operación es raíz cuadrada: Pedir un valor al usuario Si valor >0 Calcular raíz Si la operación es potencia: Pedir dos valores al usuario Calcular a b #include <stdio.h> #include <math.h> int opcion; float a, b; printf("menú\n"); printf("1. Sumar.\n"); printf("2. Restar.\n"); printf("3. Multiplicar.\n"); printf("4. Dividir.\n"); printf("5. Raíz cuadrada.\n"); printf("6. Potencia.\n"); printf("opción elegida: "); scanf("%d",&opcion); Menú 35
switch(opcion) case 1: /* Sumar */ printf("introduce los valores a sumar (a+b): "); scanf("%f%f", &a, &b); printf("%f + %f = %f\n", a, b, a+b); break; case 2: /* Restar */ printf("introduce los valores a restar (a-b): "); scanf("%f%f", &a, &b); printf("%f - %f = %f\n", a, b, a-b); break; case 3: /* Multiplicar */ printf("introduce los valores a multiplicar (a*b): "); scanf("%f%f", &a, &b); printf("%f * %f = %f\n", a, b, a*b); break; case 4: /* Dividir */ printf("introduce los valores a dividir (a/b): "); scanf("%f%f", &a, &b); if (b==0) printf("divisor 0\n"); printf("%f / %f = %f\n", a, b, a/b); break; case 5: /* Raíz cuadrada */ printf("introduce el valor para calcular la raíz: "); scanf("%f", &a); if (a<0) printf("no se puede calcular la raíz cuadrada.\n"); printf("raíz de %f = %f\n", a, sqrt(a)); break; case 6: /* Potencia */ printf("introduce los valores para calcular la potencia (a^b): "); scanf("%f%f", &a, &b); printf("%f^%f = %f\n", a, b, pow(a,b)); break; default: printf("opción incorrecta.\n"); 36