Condicionales y operadores lógicos

Las sentencias condicionales permiten ejecutar unas instrucciones u otras según si una condición se cumple o no. Aquí presentamos IF y SWITCH, y por el camino nos llevamos los operadores lógicos.

Los condicionales son una herramienta fundamental en la programación estructurada, y en C contamos con dos tipos principales: el if (junto con else y else if) y el switch. Estos nos permiten controlar el flujo de ejecución de nuestro programa en función de ciertas condiciones, haciendo que se ejecuten diferentes bloques de código según los valores que manejemos.

Empezamos con el if, que es una instrucción que evalúa una condición y ejecuta un bloque de código solo si esa condición es verdadera. Por ejemplo, si tenemos una variable x con un valor determinado, podemos decidir que si x es igual a 20, se ejecute un código específico. La sintaxis básica es escribir if seguido de la condición entre paréntesis, y luego el bloque de instrucciones entre llaves. Si la condición no se cumple, podemos usar else para ejecutar otro bloque alternativo. Esto nos permite crear regiones de código mutuamente excluyentes, donde solo se ejecuta uno u otro bloque según el valor de la variable.

Las condiciones dentro del if se expresan usando operadores lógicos como == para igualdad, >, <, >=, <= para comparaciones, y también podemos combinar varias condiciones con operadores booleanos. Por ejemplo, el operador && (and lógico) nos permite exigir que dos condiciones sean verdaderas simultáneamente, como que x sea mayor que 20 y menor que 30. Por otro lado, el operador || (or lógico) hace que la condición sea verdadera si al menos una de las subcondiciones lo es. Además, podemos agrupar condiciones con paréntesis para controlar el orden de evaluación y construir expresiones complejas.

Veamos un ejemplo sencillo que ilustra el uso de if y else:

int x = 20;
if (x == 20) {
    printf("x vale 20\n");
} else {
    printf("x no vale 20\n");
}
printf("Esto se ejecuta siempre\n");

Aquí, si x es 20, se imprime x vale 20, y si no, x no vale 20. La última línea se ejecuta siempre, independientemente del valor de x. Notemos que para imprimir un salto de línea usamos \n dentro del printf.

Cuando queremos evaluar múltiples condiciones, podemos anidar if dentro de else, pero esto puede volverse poco legible y engorroso. Por suerte, C nos ofrece la instrucción else if, que nos permite encadenar varias condiciones de forma más clara y ordenada. Por ejemplo:

if (x == 20) {
    printf("x vale 20\n");
} else if (x == 30) {
    printf("x vale 30\n");
} else if (x == 40) {
    printf("x vale 40\n");
} else {
    printf("no sé lo que vale x\n");
}

Este código evalúa varias posibilidades para x y ejecuta el bloque correspondiente. Si ninguna condición se cumple, se ejecuta el bloque del else final.

Sin embargo, cuando tenemos muchas condiciones que dependen del valor exacto de una variable, como en el caso de identificar días de la semana según un número, usar múltiples else if puede ser poco práctico. Aquí es donde el switch resulta muy útil. El switch evalúa una expresión una sola vez y compara su valor con diferentes casos (case). Cada case especifica un valor y el código que se ejecuta si la variable coincide con ese valor. Además, podemos usar default para manejar cualquier valor que no coincida con los casos definidos.

La estructura básica de un switch es:

switch (numeroDeDia) {
    case 1:
        printf("lunes\n");
        break;
    case 2:
        printf("martes\n");
        break;
    case 3:
        printf("miércoles\n");
        break;
    // ... otros casos ...
    default:
        printf("no es un día de la semana válido\n");
        break;
}

Es fundamental incluir la instrucción break al final de cada caso para evitar que la ejecución continúe en los casos siguientes, un comportamiento conocido como fall through. Si omitimos el break, el programa ejecutará todos los bloques de código que siguen al caso coincidente, lo que generalmente no es deseado.

Aunque en algunos lenguajes modernos el switch termina automáticamente después de cada caso, en C debemos controlar esto explícitamente con break. Sin embargo, en ciertas situaciones podemos aprovechar esta característica para agrupar casos que deben ejecutar el mismo código. Por ejemplo, para determinar si un día es laborable o fin de semana, podemos escribir:

switch (numeroDeDia) {
    case 1:
    case 2:
    case 3:
    case 4:
    case 5:
        printf("laborable\n");
        break;
    case 6:
    case 7:
        printf("fin de semana\n");
        break;
    default:
        printf("día no válido\n");
        break;
}

Aquí, los casos del 1 al 5 comparten el mismo bloque de código, y los casos 6 y 7 otro, gracias a la ausencia de break entre ellos.

En definitiva, el uso adecuado de if, else if, else y switch nos permite controlar el flujo de nuestros programas de manera clara y eficiente, adaptándonos a la complejidad de las condiciones que necesitemos evaluar. Como ejercicio, podemos practicar creando una función que, dado un número, nos diga a qué mes del año corresponde, usando cualquiera de estas estructuras condicionales.

Lista de reproducción
  1. 1
    Instalar CodeBlocks
    15 minutos
  2. 2
    Funciones y hola mundo
    17 minutos
  3. 3
    Variables y tipos de datos
    17 minutos
  4. 4
    Condicionales y operadores lógicos
    16 minutos
  5. 5
    Bucles
    11 minutos
  6. 6
    Punteros
    12 minutos
  7. 7
    Arrays
    14 minutos
  8. 8
    Estructuras
    12 minutos
  9. 9
    Otras construcciones de C
    9 minutos
  10. 10
    Memoria dinámica
    8 minutos
  11. 11
    El preprocesador (parte 1)
    10 minutos
  12. 12
    El preprocesador (parte 2)
    9 minutos
  13. 13
    Archivos de cabecera y múltiples .c (parte 1)
    8 minutos
  14. 14
    Archivos de cabecera y múltiples .c (parte 2)
    9 minutos
  15. 15
    C desde la línea de comandos (parte 1)
    8 minutos
  16. 16
    C desde la línea de comandos (parte 2)
    9 minutos
  17. 17
    Break y continue
    10 minutos
  18. 18
    Goto
    13 minutos
  19. 19
    Manipulación de bits
    15 minutos
  20. 20
    Máscaras de bit
    19 minutos
  21. 21
    Archivos (1): fopen y fclose
    13 minutos
  22. 22
    Archivos (2): leer con fgetc
    9 minutos
  23. 23
    Archivos (3): fseek y ftell
    11 minutos
  24. 24
    Archivos (4): leer con fgets
    9 minutos
  25. 25
    Archivos (5): fputc y fputs
    7 minutos
  26. 26
    Archivos (6): volcar en archivos con fwrite
    10 minutos
  27. 27
    Archivos (7): fread, fwrite y los arrays
    10 minutos
  28. 28
    Archivos (8): entrada estándar y salida estándar
    9 minutos
  29. 29
    Archivos (9): buffers
    14 minutos
  30. 30
    Archivos (y 10): otras funciones útiles con archivos
    5 minutos
  31. 31
    printf (1)
    18 minutos
  32. 32
    printf (parte 2)
    12 minutos
  33. 33
    scanf (parte 1)
    17 minutos
  34. 34
    scanf (parte 2)
    17 minutos
  35. 35
    fprintf, sprintf y snprintf
    8 minutos
  36. 36
    Tipos de datos opacos
    13 minutos
  37. 37
    Bibliotecas estáticas
    13 minutos
  38. 38
    Bibliotecas dinámicas
    15 minutos
  39. 39
    Más flags: i mayúscula (include), wall, werror, pedantic...
    12 minutos
  40. 40
    pkg-config
    12 minutos
  41. 41
    Make
    17 minutos
  42. 42
    GDB
    21 minutos
  43. 43
    Variables globales
    6 minutos
  44. 44
    extern
    9 minutos
  45. 45
    Funciones variádicas
    12 minutos
  46. 46
    El optimizador de GCC y la opción -O
    12 minutos
  47. 47
    Volatile
    6 minutos