Asignatura: Fundamentos de Informática | ![]() |
![]() |
Especialidad: Electrónica - UPV/EHU | ||
Curso académico: 2013-2014 | ||
Profesor: Ismael Etxeberria Agiriano |
La resolución más directa es ir probando cada uno de los valores posibles uno a uno discriminando cada vez un día de la semana.
El diagrama de flujo sería:
La codificación correspondiente a la variante 1 podría ser:
/* 06-001-1.c (versión laboratorio) * Leer un número del 0 al 6 y escribir el nombre del día de la semana * correspondiente, "lunes", "martes", ..., "domingo". * * Si el número leído no está en el intervalo previsto escribirá "error". * * Variante 1. Utilizando if-else. */ #include <stdio.h> #include <stdlib.h> int main (void) { int diaSem; printf ("Introduce el número del día de la semana: "); scanf ("%d", &diaSem); if (diaSem == 0) printf ("lunes\n"); else if (diaSem == 1) printf ("martes\n"); else if (diaSem == 2) printf ("miércoles\n"); else if (diaSem == 3) printf ("jueves\n"); else if (diaSem == 4) printf ("viernes\n"); else if (diaSem == 5) printf ("sábado\n"); else if (diaSem == 6) printf ("domingo\n"); else printf ("error\n"); system ("pause"); return 0; }
Una variante de la resolución anterior consiste en utilizar una estructura
switch
.
Se observa que la diferencia principal es que sólo hay una condición,
que es el valor de la variable diaSem.
Si ejecutamos el programa paso a paso con el depurador veremos que nos
posicionamos sobre la instrucción switch
y en el paso siguiente
vamos directamente al caso en cuestión, mientras en la variante anterior
vamos evaluando una a una las condiciones hasta dar con la adecuada.
Este diagrama de flujo no es fácil de dibujar y no facilita la comprensión por lo que no se recomienda su utilización en este curso.
Se ilustra en este ejemplo para describir el funcionamiento.
El diagrama de flujo sería:
La codificación correspondiente a la variante 2 podría ser:
/* 06-001-2.c (versión laboratorio) * Leer un número del 0 al 6 y escribir el nombre del día de la semana * correspondiente, "lunes", "martes", ..., "domingo". * * Si el número leído no está en el intervalo previsto escribirá "error". * * Variante 2. Utilizando switch. */ #include <stdio.h> #include <stdlib.h> int main (void) { int diaSem; printf ("Introduce el número del día de la semana: "); scanf ("%d", &diaSem); switch (diaSem) { case 0: printf ("lunes\n"); break; case 1: printf ("martes\n"); break; case 2: printf ("miércoles\n"); break; case 3: printf ("jueves\n"); break; case 4: printf ("viernes\n"); break; case 5: printf ("sábado\n"); break; case 6: printf ("domingo\n"); break; default: printf ("error\n"); break; } system ("pause"); return 0; }
Sean los tres números n1, n2 y n3, un posible algoritmo consiste en determinar si n1 es el mayor, comparándolo con n2 y n3. En caso afirmativo, escribimos que n1 es el mayor y comparamos los dos que quedan, n2 y n3. En caso negativo sólo los dos restantes n2 y n3 pueden ser el mayor y así sucesivamente.
El diagrama de flujo aclara esta multiplicación de casos:
El siguiente diagrama de flujo simplificado muestra los bloques de la primera condicional
La codificación correspondiente a la variante 1 podría ser:
/* 06-002-1.c (versión laboratorio) * Leer tres números enteros y decir cuál es el mayor, el mediano y el menor * * Variante 1. Escribiendo resultados sobre la marcha. */ #include <stdlib.h> #include <stdio.h> int main (void) { int n1, n2, n3; printf ("Introduce tres números: "); scanf ("%d%d%d", &n1, &n2, &n3); if (n1 >= n2 && n1 >= n3) { printf ("Mayor: %d\n", n1); if (n2 >= n3) printf ("Mediano: %d\nMenor: %d\n", n2, n3); else printf ("Mediano: %d\nMenor: %d\n", n3, n2); } else { if (n2 >= n3) { printf ("Mayor: %d\n", n2); if (n1 >= n3) printf ("Mediano: %d\nMenor: %d\n", n1, n3); else printf ("Mediano: %d\nMenor: %d\n", n3, n1); } else { printf ("Mayor: %d\n", n3); if (n1 >= n2) printf ("Mediano: %d\nMenor: %d\n", n1, n2); else printf ("Mediano: %d\nMenor: %d\n", n2, n1); } } system ("pause"); return 0; }
Una variante de la solución propuesta consiste en calcular primero cuáles
son el mayor, el mediano y el menor y finalmente sólo escribirlos una vez.
Para ello necesitaremos tres variables suplementarias,
ma
,
me
y
mi
.
Se observará que disminuye el número de instrucciones de escritura, de nueve a una. En la misma medida se introducen nueve asignaciones.
Esta variante responde más a la estructura típica:
La codificación correspondiente a la variante 2 podría ser:
/* 06-002-2.c (versión laboratorio) * Leer tres números enteros y decir cuál es el mayor, el mediano y el menor * * Variante 2. Utilizando variables suplementarias ma, me y mi, asignándoles * los valores sobre la marcha. */ #include <stdlib.h> #include <stdio.h> int main (void) { int n1, n2, n3; int ma, me, mi; printf ("Introduce tres números: "); scanf ("%d%d%d", &n1, &n2, &n3); if (n1 >= n2 && n1 >= n3) { ma = n1; if (n2 >= n3) { me = n2; mi = n3; } else { me = n3; mi = n2; } } else { if (n2 >= n3) { ma = n2; if (n1 >= n3) { me = n1; mi = n3; } else { me = n3; mi = n1; } } else { ma = n3; if (n1 >= n2) { me = n1; mi = n2; } else { me = n2; mi = n1; } } } printf ("Mayor: %d\nMediano: %d\nMenor: %d\n", ma, me, mi); system ("pause"); return 0; }
Podemos optar por determinar cada uno de los seis casos y luego asignar los valores correspondientes.
Se observará en el diagrama de flujo que hay menos mezcla de colores, por lo que la complejidad es menor.
La codificación correspondiente a la variante 3 podría ser:
/* 06-002-3.c (versión laboratorio) * Leer tres números enteros y decir cuál es el mayor, el mediano y el menor * * Variante 3. Utilizando variables suplementarias ma, me y mi, asignándoles * los valores según el caso. */ #include <stdlib.h> #include <stdio.h> int main (void) { int n1, n2, n3; int ma, me, mi; printf ("Introduce tres números: "); scanf ("%d%d%d", &n1, &n2, &n3); if (n1 >= n2 && n1 >= n3) if (n2 >= n3) { ma = n1; me = n2; mi = n3; } else { ma = n1; me = n3; mi = n2; } else if (n2 >= n3) if (n1 >= n3) { ma = n2; me = n1; mi = n3; } else { ma = n2; me = n3; mi = n1; } else if (n1 >= n2) { ma = n3; me = n1; mi = n2; } else { ma = n3; me = n2; mi = n1; } printf ("Mayor: %d\nMediano: %d\nMenor: %d\n", ma, me, mi); system ("pause"); return 0; }
Esta nueva variante propuesta contempla la utilización del operador condicional c?e1:e2.
Partiendo de la variante 3 es relativamente sencillo entender esta solución. La complejidad algoritmica es muy reducida pero se aumenta la complejidad de las expresiones condicionales.
Así, se calcula el valor del mayor (ma), mediano (m3) y menor (mi), cada una de golpe y teniendo en cuenta información de comparaciones previas.
Veamos cómo se calculan, recordando que el operador c?e1:e2 evalúa la condición c y si es cierta toda la expresión tomará el valor de la evaluación de e1 y si no, la de e2.
Veamos mediante una representación de diagramas de flujo la expresión para
calcular el número mediano me
:
Es de remarcar que hemos utilizado paréntesis para clarificar cuáles son las subexpresiones condicionales, aunque en realidad no serían necesarias ya que se ejecutarían en el orden apropiado.
Se puede simplificar esta expresión agrupando los elementos que resultan que
me
es n1
y n2
.
No vamos a proporcionar el diagrama de flujo correspondiente pero el código
proporcionado contempla este agrupamiento.
La codificación correspondiente a la variante 4 podría ser:
/* 06-002-4.c (versión laboratorio) * Leer tres números enteros y decir cuál es el mayor, el mediano y el menor * * Variante 4. Utilizando operador condicional c?e1:e2. */ #include <stdlib.h> #include <stdio.h> int main (void) { int n1, n2, n3; int ma, me, mi; printf ("Introduce tres números: "); scanf ("%d%d%d", &n1, &n2, &n3); ma = (n1 >= n2 && n1 >= n3)? n1 : (n2 >= n3)? n2 : n3; mi = (n1 <= n2 && n1 <= n3)? n1 : (n2 <= n3)? n2 : n3; me = (n1 == n2 || n1 == n3 || ma > n1 && n1 > mi)? n1 : (n2 == n3 || ma > n2 && n2 > mi)? n2 : n3; printf ("Mayor: %d\nMediano: %d\nMenor: %d\n", ma, me, mi); system ("pause"); return 0; }
En esta cuarta variante se ha visto algo muy típico en el lenguaje C: se puede simplificar mucho el número de instrucciones a base de utilizar expresiones complejas.
Lo que nos tenemos que preguntar siempre es: ¿Es el programa resultante más fácil de escribir? ¿Es más fácil de entender? ¿Es más fácil equivocarse? ¿Es más fácil de mantener por uno mismo y por otros?
Con esta última variante se pretende mostrar una nueva solución al problema, similar a la variante 06-002-3 pero con una estructura condicional más sencilla.
Comparando esta nueva solución con las anteriores veremos que es más simple, que utiliza un algoritmo más directo.
La codificación correspondiente a la variante 5 podría ser:
/* 06-002-5.c (versión laboratorio) * Leer tres números enteros y decir cuál es el mayor, el mediano y el menor * * Variante 5. Solución más sencilla. */ #include <stdlib.h> #include <stdio.h> int main (void) { int n1, n2, n3; int ma, me, mi; printf ("Introduce tres números: "); scanf ("%d%d%d", &n1, &n2, &n3); if (n1 > n2) if (n1 > n3) if (n2 > n3) { ma = n1; me = n2; mi = n3; } else { ma = n1; me = n3; mi = n2; } else { ma = n3; me = n1; mi = n2; } else if (n2 > n3) if (n1 > n3) { ma = n2; me = n1; mi = n3; } else { ma = n2; me = n3; mi = n1; } else { ma = n3; me = n2; mi = n1; } printf ("Mayor: %d; Mediano: %d; Menor: %d\n", ma, me, mi); system ("pause"); return 0; }