C Language
Declaraciones de selección
Buscar..
if () Declaraciones
Una de las formas más simples de controlar el flujo del programa es mediante el uso de sentencias de selección if
. Esta sentencia puede decidir si un bloque de código se ejecutará o no se ejecutará.
La sintaxis de if
declaración de selección en C podría ser la siguiente:
if(cond)
{
statement(s); /*to be executed, on condition being true*/
}
Por ejemplo,
if (a > 1) {
puts("a is larger than 1");
}
Donde a > 1
es una condición que debe evaluarse como true
para ejecutar las sentencias dentro del bloque if
. En este ejemplo, "a es mayor que 1" solo se imprime si a > 1
es verdadero.
if
declaraciones de selección pueden omitir las llaves de ajuste {
y }
si solo hay una declaración dentro del bloque. El ejemplo anterior se puede reescribir a
if (a > 1)
puts("a is larger than 1");
Sin embargo, para ejecutar varias instrucciones dentro del bloque, las llaves deben usarse.
La condición para if
puede incluir múltiples expresiones. if
solo realizará la acción si el resultado final de la expresión es verdadero.
Por ejemplo
if ((a > 1) && (b > 1)) {
puts("a is larger than 1");
a++;
}
solamente se ejecutará la printf
y a++
si tanto a
y b
son mayores que 1
.
if () ... else sentencias y sintaxis
Mientras que if
realiza una acción solo cuando su condición se evalúa como true
, if
/ else
permite especificar las diferentes acciones cuando la condición sea true
y cuando la condición sea false
.
Ejemplo:
if (a > 1)
puts("a is larger than 1");
else
puts("a is not larger than 1");
Al igual que el if
declaración, cuando el bloque dentro de if
o else
está formado por una sola declaración, a continuación, los tirantes se puede omitir (pero el hacerlo no se recomienda ya que puede introducir fácilmente los problemas involuntariamente). Sin embargo, si hay más de una declaración dentro del bloque if
o else
, entonces las llaves deben usarse en ese bloque en particular.
if (a > 1)
{
puts("a is larger than 1");
a--;
}
else
{
puts("a is not larger than 1");
a++;
}
Switch () Declaraciones
switch
instrucciones de switch
son útiles cuando quiere que su programa haga muchas cosas diferentes de acuerdo con el valor de una variable de prueba en particular.
Un ejemplo de uso de la instrucción switch
es como esto:
int a = 1;
switch (a) {
case 1:
puts("a is 1");
break;
case 2:
puts("a is 2");
break;
default:
puts("a is neither 1 nor 2");
break;
}
Este ejemplo es equivalente a
int a = 1;
if (a == 1) {
puts("a is 1");
} else if (a == 2) {
puts("a is 2");
} else {
puts("a is neither 1 nor 2");
}
Si el valor de a
es 1 cuando se usa la instrucción de switch
, a is 1
se imprimirá. Si el valor de a
es 2, entonces, a is 2
será impreso. De lo contrario, a is neither 1 nor 2
se imprimirá a is neither 1 nor 2
.
case n:
se utiliza para describir dónde saltará el flujo de ejecución cuando el valor pasado a la instrucción de switch
es n . n debe ser una constante de tiempo de compilación y la misma n puede existir como máximo una vez en una instrucción switch
.
default:
se utiliza para describir que cuando el valor no coincide con ninguna de las opciones para el case n:
Es una buena práctica incluir un caso default
en cada instrucción de cambio para detectar un comportamiento inesperado.
Un break;
Se requiere una declaración para saltar fuera del bloque de switch
.
Nota: Si accidentalmente olvida agregar una break
después del final de un case
, el compilador asumirá que tiene la intención de "fracasar" y todas las declaraciones de casos subsiguientes, si las hubiera, se ejecutarán (a menos que se encuentre una declaración de ruptura en cualquiera de los casos subsiguientes), independientemente de si las declaraciones de caso subsiguientes coinciden o no. Esta propiedad en particular se utiliza para implementar el dispositivo de Duff . Este comportamiento a menudo se considera un defecto en la especificación del lenguaje C.
A continuación se muestra un ejemplo que muestra los efectos de la ausencia de break;
:
int a = 1;
switch (a) {
case 1:
case 2:
puts("a is 1 or 2");
case 3:
puts("a is 1, 2 or 3");
break;
default:
puts("a is neither 1, 2 nor 3");
break;
}
Cuando el valor de a
es 1 o 2, a is 1 or 2
y a is 1, 2 or 3
se imprimirán. Cuando a
es 3, solo se imprimirá a a is 1, 2 or 3
. De lo contrario, a is neither 1, 2 nor 3
se imprimirán.
Tenga en cuenta que el caso default
no es necesario, especialmente cuando el conjunto de valores que obtiene en el switch
finaliza y se conoce en el momento de la compilación.
El mejor ejemplo es usar un switch
en una enum
.
enum msg_type { ACK, PING, ERROR };
void f(enum msg_type t)
{
switch (t) {
case ACK:
// do nothing
break;
case PING:
// do something
break;
case ERROR:
// do something else
break;
}
}
Hay múltiples ventajas de hacer esto:
- la mayoría de los compiladores informarán una advertencia si no maneja un valor (esto no se informaría si hubiera un caso
default
) - por el mismo motivo, si agrega un nuevo valor a la
enum
, se le notificará de todos los lugares donde se olvidó de manejar el nuevo valor (con un casodefault
, deberá explorar manualmente su código en busca de dichos casos) - El lector no necesita averiguar "qué está oculto por el
default:
", si existen otros valores deenum
o si es una protección para "por si acaso". Y si hay otros valores deenum
, ¿el codificador usó intencionalmente el casodefault
para ellos o hay un error que se introdujo cuando agregó el valor? - el manejo de cada valor de
enum
hace que el código sea autoexplicativo ya que no puede esconderse detrás de un comodín, debe manejar explícitamente cada uno de ellos.
Sin embargo, no puedes evitar que alguien escriba código malvado como:
enum msg_type t = (enum msg_type)666; // I'm evil
Por lo tanto, puede agregar un control adicional antes de que su interruptor lo detecte, si realmente lo necesita.
void f(enum msg_type t)
{
if (!is_msg_type_valid(t)) {
// Handle this unlikely error
}
switch(t) {
// Same code than before
}
}
if () ... else Ladder Chaining dos o más if () ... else sentencias
Mientras que la instrucción if ()... else
permite definir solo un comportamiento (predeterminado) que ocurre cuando no se cumple la condición dentro de if ()
, encadenando dos o más if () ... else
declaraciones if () ... else
permiten definir un par más comportamientos antes de ir a la última else
rama que actúa como un "defecto", en su caso.
Ejemplo:
int a = ... /* initialise to some value. */
if (a >= 1)
{
printf("a is greater than or equals 1.\n");
}
else if (a == 0) //we already know that a is smaller than 1
{
printf("a equals 0.\n");
}
else /* a is smaller than 1 and not equals 0, hence: */
{
printf("a is negative.\n");
}
Anidado si () ... else VS if () .. else Ladder
Las instrucciones anidadas if()...else
tardan más tiempo de ejecución (son más lentas) en comparación con una escalera if()...else
porque las instrucciones anidadas if()...else
comprueban todas las declaraciones condicionales internas una vez que son externas la sentencia condicional if()
se cumple, mientras que la escalera if()..else
detendrá la prueba de condición una vez que cualquiera de las sentencias condicionales if()
o else if()
sean verdaderas.
Una escalera if()...else
:
#include <stdio.h>
int main(int argc, char *argv[])
{
int a, b, c;
printf("\nEnter Three numbers = ");
scanf("%d%d%d", &a, &b, &c);
if ((a < b) && (a < c))
{
printf("\na = %d is the smallest.", a);
}
else if ((b < a) && (b < c))
{
printf("\nb = %d is the smallest.", b);
}
else if ((c < a) && (c < b))
{
printf("\nc = %d is the smallest.", c);
}
else
{
printf("\nImprove your coding logic");
}
return 0;
}
En el caso general, se considera que es mejor que el equivalente anidado if()...else
:
#include <stdio.h>
int main(int argc, char *argv[])
{
int a, b, c;
printf("\nEnter Three numbers = ");
scanf("%d%d%d", &a, &b, &c);
if (a < b)
{
if (a < c)
{
printf("\na = %d is the smallest.", a);
}
else
{
printf("\nc = %d is the smallest.", c);
}
}
else
{
if(b < c)
{
printf("\nb = %d is the smallest.", b);
}
else
{
printf("\nc = %d is the smallest.", c);
}
}
return 0;
}