Curso C++

El Ciclo for

¿Por Qué Necesitamos un Ciclo?

Imaginá que tenés que registrar la temperatura de 5 días seguidos. Si no conocieras los ciclos, probablemente escribirías esto:

#include <iostream>

int main() {
    int tempDia1, tempDia2, tempDia3, tempDia4, tempDia5;

    std::cout << "Ingresá la temperatura del día 1: ";
    std::cin >> tempDia1;
    std::cout << "Ingresá la temperatura del día 2: ";
    std::cin >> tempDia2;
    std::cout << "Ingresá la temperatura del día 3: ";
    std::cin >> tempDia3;
    std::cout << "Ingresá la temperatura del día 4: ";
    std::cin >> tempDia4;
    std::cout << "Ingresá la temperatura del día 5: ";
    std::cin >> tempDia5;

    return 0;
}

¿Qué pasa si en vez de 5 días fueran 500? ¿O 5000? ¿Vas a crear 500 variables distintas? Copiar y pegar el mismo código con cambios mínimos es propenso a errores, podés olvidarte de renombrar una variable, saltarte un día, etc. En programación, esto se conoce como violar el principio DRY (Don’t Repeat Yourself).

Para estos casos existe el ciclo for, una estructura de control que ejecuta un bloque de código un número determinado de veces de forma controlada y predecible. A nivel de máquina, la CPU ejecuta un salto condicional hacia atrás en el flujo de instrucciones, evitando tener que duplicar el código físicamente.

El contador del bucle se almacena en un registro de la CPU o en la pila (stack) como una variable local de tipo entero. El compilador traduce todo el bloque a instrucciones de máquina eficientes con un solo salto condicional.

Configuración del Ciclo For

El for en C++ tiene una sintaxis que separa tres responsabilidades distintas con punto y coma (;):

for ( inicialización ; condición ; actualización )
    instrucción;

Cada uno de estos tres parámetros tiene un momento exacto de ejecución y un trabajo específico.

Inicialización

La inicialización se ejecuta una sola vez antes que cualquier otra cosa dentro del for. Es el punto de partida del ciclo.

for (int dia = 1; dia <= 5; dia++) {
    std::cout << "Día " << dia << std::endl;
}

En este ejemplo, int dia = 1 es la inicialización. Se ejecuta apenas el programa llega al for, se crea la variable dia con valor 1, y después el control pasa a la condición.

La variable contador puede llamarse de cualquier forma (i, j, contador, dia, vuelta), pero lo importante es que su declaración ocurre en este primer espacio. C++ permite tanto declarar la variable directamente aquí como usar una ya declarada antes.

Condición

La condición se evalúa antes de cada iteración, incluyendo la primera. Si el resultado es true (distinto de cero), el cuerpo del ciclo se ejecuta. Si es false (cero), el termina y el programa continúa con la instrucción siguiente al for.

for (int dia = 1; dia <= 5; dia++) {
    std::cout << "Procesando día " << dia << std::endl;
}

Acá dia <= 5 es la condición. Mientras dia sea menor o igual a 5, el ciclo sigue ejecutándose. Cuando dia llegue a 6, la condición se evalúa como false y el ciclo termina.

Si la condición es false desde el principio, el cuerpo del for nunca se ejecuta. Por ejemplo, for (int i = 10; i < 5; i++) daría 0 vueltas. El ciclo puede dar cero iteraciones sin ser un error.

La condición usa los operadores relacionales que ya conocés (<, <=, >, >=, ==, !=). Estos operadores devuelven un valor de tipo bool: true (1) si la relación se cumple, false (0) si no.

Actualización

La actualización se ejecuta al final de cada iteración, justo después del cuerpo del ciclo y antes de volver a evaluar la condición. Su propósito es avanzar el contador.

for (int dia = 1; dia <= 5; dia++) {
    std::cout << "Día " << dia << std::endl;
}

dia++ es la actualización. En cada vuelta, después de ejecutar el cuerpo, se incrementa dia en 1. Sin esta línea, el contador nunca avanzaría y el ciclo sería infinito (si la condición nunca se vuelve false).

El operador ++ suma 1 a la variable, y -- resta 1. Ambos tienen dos variantes:

  • Prefijo (++i): incrementa y devuelve el valor ya incrementado.
  • Postfijo (i++): devuelve el valor original y luego incrementa.

En un for, el efecto es el mismo porque el valor retornado no se usa, pero es importante saber que existen.

// Avance de 2 en 2
for (int i = 0; i < 10; i = i + 2) {
    std::cout << i << " ";
}
// Salida: 0 2 4 6 8

// Decremento (cuenta regresiva)
for (int i = 10; i > 0; i--) {
    std::cout << i << " ";
}
// Salida: 10 9 8 7 6 5 4 3 2 1

Ámbito (Scope)

Si declarás la variable contador dentro del for (en la inicialización), su ámbito (scope) se limita al bloque del ciclo. Esto significa que la variable “vive” solo dentro de las llaves del for y no puede usarse después.

for (int dia = 1; dia <= 5; dia++) {
    // acá 'dia' existe y se puede usar
}
// acá 'dia' ya no existe
// std::cout << dia; // ERROR: 'dia' was not declared in this scope

Si intentás usar la variable dia después de cerrar el for, el compilador te va a marcar un error. La variable ya no existe porque salió de su ámbito natural.

Si necesitás el valor del contador después del bucle, tenés que declarar la variable fuera del for:

int dia;
for (dia = 1; dia <= 5; dia++) {
    std::cout << "Procesando día " << dia << std::endl;
}
std::cout << "Valor final del contador: " << dia << std::endl;

Este comportamiento sigue el estándar C++. En MSVC, la opción /Zc:forScope (activada por defecto) fuerza esta conducta estándar.

El Flujo de Ejecución

Entender el orden exacto en que se ejecuta cada parte del for es fundamental. Hay una secuencia estricta que la CPU sigue al pie de la letra.

Tomemos este código:

for (int vuelta = 1; vuelta <= 3; vuelta++) {
    std::cout << "Vuelta número " << vuelta << std::endl;
}
std::cout << "Ciclo terminado." << std::endl;

La secuencia de ejecución es:

  1. Inicialización: int vuelta = 1; → se ejecuta una sola vez. vuelta vale 1.
  2. Condición: vuelta <= 3 → 1 <= 3 es true. Se ejecuta el cuerpo.
  3. Cuerpo: Imprime "Vuelta número 1".
  4. Actualización: vuelta++vuelta ahora vale 2.
  5. Condición: vuelta <= 3 → 2 <= 3 es true. Se ejecuta el cuerpo.
  6. Cuerpo: Imprime "Vuelta número 2".
  7. Actualización: vuelta++vuelta ahora vale 3.
  8. Condición: vuelta <= 3 → 3 <= 3 es true. Se ejecuta el cuerpo.
  9. Cuerpo: Imprime "Vuelta número 3".
  10. Actualización: vuelta++vuelta ahora vale 4.
  11. Condición: vuelta <= 3 → 4 <= 3 es false. El bucle termina.
  12. El programa continúa con la línea siguiente: imprime "Ciclo terminado.".

Corte de la Condicón: cuando la condición se evalúa como false, el control salta inmediatamente a la primera instrucción después del bloque for. No se ejecuta el cuerpo, no se ejecuta la actualización. El ciclo muere ahí.

Uso del Ciclo For

El for es la estructura base para iterar. Pero su verdadero poder aparece cuando lo combinás con la lógica condicional (if/else) que ya dominás. Acá van los patrones fundamentales.

Acumulador

El acumulador consiste en declarar una variable fuera del for e ir sumándole valores en cada iteración. Como la variable está fuera del ciclo, conserva su valor entre vueltas y podés leer el total después.

#include <iostream>

int main() {
    int suma = 0;
    int puntaje;

    for (int ronda = 1; ronda <= 3; ronda++) {
        std::cout << "Ingresá el puntaje de la ronda " << ronda << ": ";
        std::cin >> puntaje;
        suma += puntaje;  // acumulamos
    }

    std::cout << "Puntaje total: " << suma << std::endl;
    return 0;
}

Si declarás el acumulador dentro del for (ej. int suma = 0; adentro del bloque), en cada vuelta se reiniciaría a cero. Error clásico de principiantes: la variable se crea y destruye en cada iteración.

Filtrado dentro del Ciclo

Podés colocar una sentencia if dentro del cuerpo del for para ejecutar código condicionalmente en iteraciones específicas. Esto te permite filtrar datos o contar ocurrencias particulares.

#include <iostream>

int main() {
    int temperatura;
    int diasCalurosos = 0;

    for (int dia = 1; dia <= 10; dia++) {
        std::cout << "Ingresá la temperatura del día " << dia << ": ";
        std::cin >> temperatura;

        if (temperatura > 25) {
            std::cout << "  -> ¡Día caluroso!" << std::endl;
            diasCalurosos++;
        }
    }

    std::cout << "Días calurosos (>25°C): " << diasCalurosos << std::endl;
    return 0;
}

En este ejemplo, el for itera 10 veces (una por día). Dentro de cada vuelta, un if decide si la temperatura supera los 25°C. Si es así, imprime un mensaje y cuenta el día. Si no, simplemente avanza al siguiente.

Acá combinamos dos patrones: el acumulador (diasCalurosos) y el filtrado con if. Notá cómo el acumulador crece solo cuando se cumple la condición.

Ejemplo Integrador

Hagamos un programa completo que resuelve el problema del inicio: registrar temperaturas, acumular el total, y contar los días que superaron una meta, todo con las herramientas que aprendiste.

#include <iostream>

int main() {
    int temperatura;
    int sumaTemperaturas = 0;
    int diasMetaSuperada = 0;
    const int META = 25;  // temperatura objetivo

    std::cout << "=== Registro de Temperaturas Semanal ===" << std::endl;

    for (int dia = 1; dia <= 5; dia++) {
        std::cout << "Día " << dia << " - Ingresá la temperatura: ";
        std::cin >> temperatura;

        sumaTemperaturas += temperatura;

        if (temperatura > META) {
            std::cout << "  >> ¡Meta superada!" << std::endl;
            diasMetaSuperada++;
        }
    }

    std::cout << "\n--- Resumen Semanal ---" << std::endl;
    std::cout << "Promedio de temperatura: " << (sumaTemperaturas / 5) << "°C" << std::endl;
    std::cout << "Días que superaron la meta: " << diasMetaSuperada << std::endl;

    return 0;
}

¿Te imaginás escribir esto sin un for? Tendrías 5 bloques de código casi idénticos, 5 variables distintas para las temperaturas, y cualquier cambio requeriría modificar los 5 bloques.