switch
.
if-else
) y repetititivas (
for
,
while
). Las sentencias alternativas permiten especificar la reacción del programa en distintas circunstancias; si la lógica del algoritmo empleado se ajusta a un comportamiento más o menos dicotómico, es posible construir un árbol de sentencias
if()
anidadas que generen el comportamiento necesario. Sin embargo, es frecuente hallar grupos de situaciones (y por tanto de respuestas de programa) que se reducen a una lista de posibilidades mutuamente excluyentes. Ciertamente, se puede implementar un algoritmo de este tipo mediante múltiples sentencias
if()-else
anidadas, pero esta solución resulta farragosa y poco eficiente, porque el código tiene que ir comprobando una por una todas las posibilidades (todas las condiciones
if()
) hasta encontrar la correcta.
switch
es un selector multivía, que admite como argumento el valor de una expresión ordinal, y desencadena la ejecución del código correspondiente, identificado mediante uno o más valores constantes del mismo tipo ordinal que la expresión. La sintaxis de esta sentencia es como sigue:
switch( expresión_ordinal ) { case constante_1 : Bloque_1; break; case constante_2 : Bloque_2; break; case constante_3 : case constante_4 : case constante_5 : Bloque_3; break; ... default : Bloque_4; break; }
expresión_ordinal
se obtiene un entero (quizá el valor de una variable de tipo
enum
) o un carácter. Si este valor es igual a la constante que acompaña a alguna de las cláusulas
case
presentes en el cuerpo de la sentencia
switch
, entonces se ejecuta el bloque de código situado a la derecha de los dos puntos que acompañan a la cláusula
case
en cuestión. El bloque puede estar formado por una o más sentencias. Puede haber varias cláusulas
case
asociadas a un mismo bloque de código; en tal caso, el bloque ejecutado será el mismo para todos aquellos casos en que el valor de la expresión de control sea el de cualquiera de las cláusulas
case
asociadas a ese bloque. El programa siguiente es un ejemplo sencillo de uso de la sentencia
switch
:
#include<stdio.h> int main(int contador, char * argumento[]) { int i; switch(contador) { case 1: printf("\nNo me ha dado argumentos.\n"); break; case 2: printf("\nMe ha dado un argumento.\n"); break; case 3: case 4: case 5: printf("\nMe ha dado 2, 3 o 4 argumentos.\n"); break; default: printf("\nMe ha dado más de 4 argumentos.\n"); break; } printf("\n"); /* Ahora se muestran los argumentos dados, si los hay */ for(i=0;i<contador;i++) printf("Argumento[%d] = %s\n", i, argumento[i]); printf("\nTerminación normal del programa\n\n"); return 0; }
[cauldron:~/coti>]> ./a.out No me ha dado argumentos. Argumento[0] = ./a.out Terminación normal del programa [cauldron:~/coti>]> ./a.out 1 Me ha dado un argumento. Argumento[0] = ./a.out Argumento[1] = 1 Terminación normal del programa [cauldron:~/coti>]> ./a.out 1 2 3 Me ha dado 2, 3 o 4 argumentos. Argumento[0] = ./a.out Argumento[1] = 1 Argumento[2] = 2 Argumento[3] = 3 Terminación normal del programa [cauldron:~/coti>]> ./a.out 1 2 3 4 5 6 7 Me ha dado más de 4 argumentos. Argumento[0] = ./a.out Argumento[1] = 1 Argumento[2] = 2 Argumento[3] = 3 Argumento[4] = 4 Argumento[5] = 5 Argumento[6] = 6 Argumento[7] = 7 Terminación normal del programa [cauldron:~/coti>]>Comentarios .- La variable
contador
recibe automáticamente como valor el número de argumentos que acompañan al nombre del programa en la línea de órdenes. Si no se dan argumentos, esto es, si lo único que se escribe es el nombre del programa, entonces el valor de
contador
es 1. Si se dan argumentos, se incrementa
contador
en tantas unidades como palabras distintas aparezcan en la línea de órdenes. Hemos utilizado contador como expresión (trivial, al ser una variable) de control en este ejemplo de sentencia
switch
.
default
)
break
break
, sirve para hacer que el programa abandone la sentencia
switch
. Si no se encuentra un
break
, se ejecuta el siguiente bloque de código, y así hasta hallar un
break
o salir de la sentencia
switch
.
case
son puntos de entrada al conjunto de líneas de código que hay en el interior del
switch
. Las sentencias
break
son puntos de salida, y debemos organizar cuidadosamente ambas cosas para evitar errores que no podrá detectar el compilador.
default
.
switch
está especialmente indicada para construir menús: en efecto, se ofrece al usuario una colección de opciones, y este indica su preferencia pulsando una tecla o haciendo clic con el ratón en algún lugar. Esta elección del usuario es fácilmente transformable en números enteros, y una sentencia
switch
permite fácilmente asignar acciones a esos números. De hecho, la sentencia
switch
se va a utilizar para construir algunas esqueletos de programa, aun cuando prescindiremos de ella en cuanto dispongamos del interesante concepto de
puntero de función
.
switch
.
/* Este programa sirve para resolver ecuaciones cuadráticas. Es un ejemplo de utilización de la sentencia switch. */ #include <stdio.h> #include <stdlib.h> #include <math.h> enum tipos_de_raices {reales_y_distintas, complejas_conjugadas, raiz_real_doble}; enum tipos_de_raices tipo; float a, b, c, d; float r1, r2, preal, pimaginaria, rrd; int main(void) { printf ("Ecuaciones cuadráticas"); printf("\n\nEscriba los coeficientes a, b y c : "); scanf("%f %f %f", &a, &b, &c); d = b*b - 4.0*a*c; d > 0.0 ? tipo=reales_y_distintas : (d < 0.0 ? tipo=complejas_conjugadas : (tipo= raiz_real_doble)); switch(tipo) { case reales_y_distintas : { r1=(-b+sqrt(d))/(2.0*a); r2=(-b-sqrt(d))/(2.0*a); printf("\nRaíces reales y distintas; r1= %f y r2= %f", r1, r2); } break; case complejas_conjugadas : { preal=(-b)/(2.0*a); pimaginaria=sqrt(-d)/(2.0*a); printf( "\nRaíces complejas conjugadas, r1= %f+j%f y r2= %f-j%f", preal, pimaginaria, preal, pimaginaria); } break; case raiz_real_doble: { rrd=(-b)/(2.0*a); printf("\nRaíz real doble, rrd= %f", rrd); } break; default: { printf("\nError catastrófico - tipo de ecuación cuadrática desconocido!"); } break; } printf("\n\nTerminación normal del programa.\n"); return 0; }Comentarios .- El algoritmo empleado es el sobradamente conocido para la resolución de ecuaciones de segundo grado. Para hace más comprensible el programa se ha creado un tipo de datos enumerado,
enum tipos_de_raices
, para luego declarar una variable (
tipo
) de este tipo de datos. De este modo se puede hablar de manera comprensible de los distintos tipos de soluciones;
tipo
se utiliza como expresión de control en la sentencia
switch
del programa.
?:
anidados; lo mismo podría hacerse con sentencias
if()-else
, quizá algo más voluminosas aunque el resultado sería exactamente el mismo. A fin de cuentas, se trata de dar el valor correcto a
tipo
, en función del signo del discriminante.
switch
. Nada impide, desde luego, utilizar dos sentencias
switch
distintas, una para el cálculo y otra para la impresión; de hecho, el programa resultante resulta más claro./* Esta es una versión muy primitiva del programa núcleo, sin utilizar subprogramas. Este ejercicio muestra la aplicación de la sentencia switch, con especial antención a break y default. Esta versión del programa núcleo es apenas utilizable, es tan solo un ejemplo de aplicación de la sentencia switch. */ /* Basado en nucleosp.pas */ #include<stdio.h> void main(void) { int fin; /* control de iteración del programa */ char instruccion; /* dada por el usuario */ char menu[80]; /* que muestra el programa */ char opcionesvalidas[80]; /* que admite el programa */ /* Iniciaciones generales */ fin = 0; /* Acabamos de arrancar, no hay que salir */ strcpy(menu,"O)perar S)alir"); /* Esto es lo que mostrará el menú */ strcpy(opcionesvalidas,"OSQ"); /* Estas son las opciones admisibles */ do { do { printf("%s ", menu); scanf("%c%*c",&instruccion);/* Se descarta el \n del usuario */ instruccion=toupper(instruccion); } while (!strchr(opcionesvalidas,instruccion)); /* "dispatcher" */ switch(instruccion) { case 'S': { fin = 1; puts("Nos vamos!\n"); } break; case 'O': { puts("Estamos operando.\n"); } break; default : { puts("Instrucción incorrecta.\n"); } break; } } while (!fin); puts("\n\nThat's all folks!\n"); } /* COMENTARIOS Este programa admite "macros". En efecto, escriba varias veces la letra "o" y observará que se producen varias llamadas al bloque correspondiente a operar. Si hubiera más de una letra correspondiente a una operación, se desencadenarían sucesivamente todas las operaciones. Este programa es posiblemente el intérprete más pequeño posible. ¿Qué ocurre si las instrucciones se leen de un fichero (y no del teclado)? ¿Qué ocurre si en lugar de caracteres se leen cadenas completas (gets)? ¿Qué ocurre si se analizan esas cadenas, en busca de palabras reservadas (input, print,load, save, list, run...? ¿Cómo funciona command.com, o cualquier otro intérprete de líneas? ¿Se entiende el tratamiento de un fichero .BAT? */