Curso C++

Condicionales

En el desarrollo de software, rara vez un programa ejecuta una secuencia de tareas de forma lineal y sin desvíos. La verdadera potencia de una aplicación reside en su capacidad para reaccionar a diferentes escenarios, entradas del usuario o estados internos. Vos, como desarrollador, necesitás una forma de instruir a tu programa para que tome decisiones. En C++, esta capacidad de bifurcar el flujo de ejecución se logra a través de la lógica condicional.

Este artículo es una guía técnica y directa para que domines las estructuras de control if, else y switch. Vamos a desglosar desde los fundamentos de la lógica booleana hasta cómo y cuándo aplicar cada estructura para escribir un código que no solo sea funcional, sino también limpio, legible y mantenible.

Lógica Booleana y Operadores

Antes de que puedas controlar el flujo de tu programa, tenés que entender cómo C++ evalúa el mundo: en términos de verdadero y falso.

El lenguaje te provee del tipo de dato bool, que solo puede tener dos valores: true o false. Pero la lógica booleana va más allá. Cuando C++ necesita evaluar una condición, cualquier valor numérico igual a 0 es interpretado como false, y cualquier valor distinto de cero es considerado true.

Para construir estas condiciones, utilizás los operadores relacionales y lógicos.

  • Operadores Relacionales: Te permiten comparar dos valores.
    • == (igual a)
    • != (distinto de)
    • < (menor que)
    • > (mayor que)
    • <= (menor o igual que)
    • >= (mayor o igual que)
  • Operadores Lógicos: Te permiten combinar o invertir expresiones booleanas.
    • && (AND lógico)
    • || (OR lógico)
    • ! (NOT lógico)

[!NOTE] Un punto clave en los operadores && y || es la evaluación de cortocircuito (short-circuit evaluation). Si el resultado de una expresión se puede determinar evaluando solo el primer operando, el segundo no se evalúa. Por ejemplo, si en condicion1 && condicion2, condicion1 es false, C++ sabe que el resultado total es false y nunca ejecuta condicion2. Esto no solo es una optimización de rendimiento, sino que te permite escribir código más seguro, como verificar si un puntero es nulo antes de intentar acceder a su contenido.

#include <iostream>

void verificarAcceso(int edadUsuario, bool tieneCredencial) {
    // Uso de operadores lógicos y relacionales
    if (edadUsuario >= 18 && tieneCredencial) {
        std::cout << "Acceso concedido." << std::endl;
    } else {
        std::cout << "Acceso denegado." << std::endl;
    }
}

Estructuras Condicionales: El if, else if y else

La herramienta fundamental para la toma de decisiones es la sentencia if. Su sintaxis es directa: si la condición entre paréntesis es true, el bloque de código que le sigue se ejecuta.

#include <iostream>

void controlarTemperatura(int temperaturaActual) {
    if (temperaturaActual > 25) {
        std::cout << "Temperatura alta. Activando sistema de refrigeración." << std::endl;
    }
}

Para manejar el caso contrario, introducís la sentencia else. Esta te da una bifurcación clara: si la condición del if no se cumple, el bloque del else se ejecuta.

Y si necesitás evaluar múltiples condiciones en una secuencia, la estructura else if te permite encadenar varias pruebas de forma excluyente.

#include <iostream>

void asignarCategoria(int puntaje) {
    if (puntaje > 90) {
        std::cout << "Categoría: Avanzado" << std::endl;
    } else if (puntaje > 70) {
        std::cout << "Categoría: Intermedio" << std::endl;
    } else {
        std::cout << "Categoría: Principiante" << std::endl;
    }
}

También podés anidar sentencias if para crear lógicas más complejas, donde una decisión depende de otra.

[!WARNING] Tené cuidado con el anidamiento excesivo. Si te encontrás con tres o más niveles de if anidados, tu código probablemente se está voliendo difícil de leer y mantener, una condición conocida como “código espagueti” o “arrow anti-pattern”. En esos casos, considerá refactorizar tu lógica, quizás extrayendo partes a funciones separadas o usando una estructura diferente como switch.

Selección Múltiple: La Sentencia switch

Cuando tenés que comparar una única variable contra una lista de valores constantes y enteros, una larga cadena de if-else if puede volverse verbosa. Para estos escenarios, C++ te ofrece la sentencia switch, una alternativa más limpia y estructurada.

El switch evalúa una expresión entera y salta al case cuyo valor coincida.

Un detalle crucial de esta estructura es la sentencia break. Si la omitís al final de un bloque case, la ejecución continuará en el siguiente case de forma secuencial, un comportamiento llamado “fall-through”. A veces es útil, pero la mayoría de las veces es una fuente común de errores.

#include <iostream>

void interpretarComando(int comando) {
    switch (comando) {
        case 1:
            std::cout << "Ejecutando Tarea A..." << std::endl;
            break; // Sin este break, se ejecutaría también el caso 2.
        case 2:
            std::cout << "Ejecutando Tarea B..." << std::endl;
            break;
        case 3:
            std::cout << "Ejecutando Tarea C (con fall-through)..." << std::endl;
            // No hay break, por lo que la ejecución sigue al siguiente case.
        case 4:
            std::cout << "Esta tarea se ejecuta para los comandos 3 y 4." << std::endl;
            break;
        default:
            std::cout << "Comando no reconocido." << std::endl;
            break;
    }
}

Finalmente, la cláusula default actúa como una red de seguridad. Si el valor de la variable no coincide con ningún case, el bloque default se ejecuta. Es una buena práctica incluirla siempre para manejar situaciones inesperadas.

Conclusión: Escribiendo Código Limpio y Decisivo

Dominar el if-else y el switch es fundamental. La elección entre uno y otro no siempre es obvia, pero una buena regla general es:

  • Usá if-else if para condiciones complejas, rangos de valores o cuando evaluás variables de diferentes tipos.
  • Preferí switch cuando compares una única variable entera contra una lista de constantes discretas. El switch comunica tu intención de forma más clara en ese contexto.

Más allá de la sintaxis, el objetivo es siempre escribir código que sea fácil de entender para otros desarrolladores y para tu “yo” del futuro. Un control de flujo claro y bien estructurado es uno de los pilares para lograr un software robusto y mantenible.