</>waridocu

C++

Control de flujo: if, for, while y switch

Cómo hacer que un programa tome decisiones y repita trabajo con if/else, bucles y switch.

cppcontrol-de-flujoifforwhileswitch

De dónde venimos

En Variables, tipos de datos y operadores apareció una línea curiosa:

Recordando: la comparación de la página anteriorcpp
std::cout << "¿Aprobado? " << (promedio >= 4.0) << "\n";

Esa comparación produce un bool, pero el programa lo único que hacía era imprimirlo. Un bool sirve para mucho más: es el material con el que se construyen las decisiones. Esta página usa exactamente esos operadores de comparación (==, <, >=) y lógicos (&&, ||, !) que ya conoces, y les da el uso para el que existen: cambiar qué líneas se ejecutan y cuántas veces.

Los ejemplos siguen usando std::cin y std::cout tal como se explicaron en la página de la Standard Library, así que no hay nada nuevo en la entrada/salida: lo nuevo es solo la estructura alrededor.

Bloques y ámbito

Antes de las estructuras en sí, un detalle que las atraviesa todas: las llaves { } delimitan un bloque, y una variable declarada dentro de un bloque solo existe dentro de ese bloque. A eso se le llama ámbito (scope).

Ejemplo: una variable no sobrevive a su bloquecpp
{
    int temporal = 5;
    // aquí temporal existe
}
// aquí temporal ya NO existe: usarla es error de compilación

Esto no es un tecnicismo: es la base del modelo de recursos de C++. Cuando una variable sale de su ámbito, C++ libera automáticamente lo que ocupaba. Ese comportamiento tiene nombre (RAII) y es tema de una sección más avanzada, pero conviene que la idea te suene desde ya.

Tomar decisiones con if

if ejecuta un bloque solo si una condición es verdadera. else if encadena condiciones alternativas y else cubre todo lo demás.

Ejemplo: clasificar una nota con if / else if / elsecpp
#include <iostream>

int main() {
    double nota = 0.0;
    std::cout << "Ingresa tu nota (1.0 a 7.0): ";
    std::cin >> nota;

    if (nota < 1.0 || nota > 7.0) {
        std::cout << "Nota fuera de rango.\n";
    } else if (nota >= 6.0) {
        std::cout << "Excelente.\n";
    } else if (nota >= 4.0) {
        std::cout << "Aprobado.\n";
    } else {
        std::cout << "Reprobado.\n";
    }

    return 0;
}
bashbash
g++ -std=c++17 -Wall -o notas notas.cpp
./notas
texttext
Ingresa tu nota (1.0 a 7.0): 6.5
Excelente.

El orden de las ramas importa: se evalúan de arriba a abajo y la primera que sea verdadera gana; el resto ni se mira. Por eso >= 6.0 va antes que >= 4.0: al revés, un 6.5 entraría por “Aprobado” y nunca llegaría a “Excelente”.

Advertencia

Las llaves son opcionales cuando el cuerpo del if es una sola línea, pero omitirlas es una fuente conocida de bugs: si más adelante alguien agrega una segunda línea creyendo que está dentro del if, esa línea se ejecutará siempre. Este error tiene incluso un nombre propio en la historia del software (el bug goto fail de Apple en 2014, que rompió la validación de certificados SSL). Pon siempre las llaves, aunque sobren.

if con condiciones combinadas

&& exige que ambas condiciones se cumplan, || que se cumpla al menos una:

Ejemplo: combinar condicionescpp
if (edad >= 18 && tieneCarnet) {
    std::cout << "Puede conducir\n";
}

C++ evalúa estos operadores en cortocircuito: si el lado izquierdo de && ya es falso, el derecho ni se evalúa. Esto no es solo una optimización, es una garantía del lenguaje que se usa a propósito para escribir comprobaciones seguras, como verificar que un puntero no sea nulo antes de usarlo — algo que verás en Punteros.

El bucle for

for repite un bloque un número conocido de veces. Sus tres partes, separadas por ;, son: inicialización, condición de continuación e incremento.

Ejemplo: imprimir los números pares del 1 al 10cpp
#include <iostream>

int main() {
    for (int i = 1; i <= 10; ++i) {
        if (i % 2 == 0) {          // el operador % de la página anterior
            std::cout << i << " ";
        }
    }
    std::cout << "\n";
    return 0;
}
texttext
2 4 6 8 10

La variable i se declara dentro del for, así que su ámbito es el bucle: fuera de él no existe. Eso es intencional y deseable — evita que un contador temporal contamine el resto de la función.

Nota

Este for “clásico” con contador es el que necesitas entender primero porque es el que verás en código C, en ejemplos antiguos y al recorrer arrays, pero no es lo más idiomático en C++ moderno. Para recorrer una colección completa, hoy se prefiere el for basado en rango (for (int n : numeros)), que no usa índices y elimina de raíz los errores de “me pasé por uno”. Lo verás en acción en la página de arrays.

El bucle while y do-while

while repite mientras la condición sea verdadera, y a diferencia de for no impone un contador: se usa cuando no sabes de antemano cuántas vueltas harás.

Ejemplo: pedir un número hasta que sea válidocpp
#include <iostream>

int main() {
    int edad = -1;

    while (edad < 0 || edad > 120) {
        std::cout << "Ingresa una edad válida (0-120): ";
        std::cin >> edad;
    }

    std::cout << "Edad registrada: " << edad << "\n";
    return 0;
}

do { ... } while (condicion); es la variante que ejecuta el cuerpo al menos una vez antes de comprobar la condición. Es útil justo para casos como el anterior, donde la primera pregunta siempre hay que hacerla, y evita tener que inicializar edad con un valor falso como -1.

Advertencia

El error clásico de while es el bucle infinito: si nada dentro del cuerpo cambia la variable de la condición, el programa se cuelga para siempre. Antes de escribir el cuerpo, pregúntate: “¿qué línea de aquí adentro hará que esta condición llegue a ser falsa?”. Si no hay respuesta, ya tienes el bug. (Si te pasa mientras pruebas, corta el programa con Ctrl+C.)

break y continue

  • break sale inmediatamente del bucle.
  • continue salta el resto del cuerpo y pasa a la siguiente vuelta.

Ambos funcionan en for, while y do-while. Úsalos con moderación: un bucle con cuatro break repartidos es difícil de seguir.

Elegir entre muchas opciones con switch

switch compara una expresión entera o de tipo carácter contra varios valores constantes. Es más legible que una cadena larga de else if cuando todas las comparaciones son de igualdad contra el mismo valor.

Ejemplo: menú simple con switchcpp
#include <iostream>

int main() {
    std::cout << "1) Saludar  2) Despedir  3) Salir\n";
    std::cout << "Opción: ";

    int opcion = 0;
    std::cin >> opcion;

    switch (opcion) {
        case 1:
            std::cout << "¡Hola!\n";
            break;
        case 2:
            std::cout << "¡Adiós!\n";
            break;
        case 3:
            std::cout << "Saliendo...\n";
            break;
        default:
            std::cout << "Opción no reconocida.\n";
            break;
    }

    return 0;
}
bashbash
g++ -std=c++17 -Wall -o menu menu.cpp
./menu
texttext
1) Saludar  2) Despedir  3) Salir
Opción: 2
¡Adiós!
Advertencia

Si olvidas el break al final de un case, la ejecución continúa hacia el siguiente case en lugar de salir del switch. Esto se llama fall-through y es la trampa número uno de switch. A veces se hace a propósito (para que varios case compartan el mismo código), y en ese caso conviene dejarlo escrito con un comentario // fall-through o, desde C++17, con el atributo [[fallthrough]];, para que quede claro que no es un olvido.

Nota

switch no funciona con std::string ni con double: solo acepta tipos enteros, char y enumeraciones. Para comparar cadenas de texto, necesitas if/else if con ==. Es una limitación heredada de C que sorprende a quien viene de Java o C#, donde el switch con strings sí es posible.

Siguiente paso

Ya puedes escribir programas que deciden y repiten, pero todo el código sigue viviendo dentro de un único main() que crece sin control. La forma de partirlo en piezas reutilizables con nombre son las funciones: continúa con Funciones.