Estructuras de Controlc++whiledo-whileciclosloops

Ciclo While

Aprende a usar while y do-while para repetir cuando no sabes cuántas veces

OOI Oaxaca9 de febrero de 20268 min read

¿Cuándo usar while?

El ciclo for es perfecto cuando sabes cuántas veces repetir. Pero, ¿qué pasa cuando no lo sabes? Por ejemplo:

  • "Sigue pidiendo una contraseña mientras sea incorrecta."
  • "Divide el número entre 2 mientras sea par."
  • "Lee datos mientras haya datos disponibles."

Para estas situaciones usamos el ciclo while.

Analogía: Imagina que estás llenando un vaso con agua. No sabes cuántos segundos tardará, pero sigues mientras el vaso no esté lleno.

El ciclo while

while (condición) {
    // Este código se repite MIENTRAS la condición sea verdadera
}

Flujo:

  1. Evalúa la condición.
  2. Si es true, ejecuta el bloque.
  3. Vuelve al paso 1.
  4. Si es false, el ciclo termina.
int i = 1;
while (i <= 5) {
    cout << i << " ";
    i++;     // ¡No olvides actualizar la variable!
}
// Salida: 1 2 3 4 5

Paso a paso:

Iteracióni¿i <= 5?Acción
11Imprime 1, i → 2
22Imprime 2, i → 3
33Imprime 3, i → 4
44Imprime 4, i → 5
55Imprime 5, i → 6
66NoFIN
⚠️

¡Cuidado con los ciclos infinitos! Si la condición nunca se vuelve falsa, el programa se ejecuta para siempre. Siempre asegúrate de que algo dentro del ciclo eventualmente haga la condición falsa.

// ❌ CICLO INFINITO - la condición nunca cambia
int x = 1;
while (x > 0) {
    cout << x << endl;
    // Olvidamos cambiar x
}

while vs for

Cualquier for se puede reescribir como while y viceversa:

// Con for
for (int i = 0; i < n; i++) {
    cout << i << endl;
}

// Equivalente con while
int i = 0;
while (i < n) {
    cout << i << endl;
    i++;
}

¿Cuándo usar cuál?

  • for: Cuando sabes cuántas veces repetir (o tienes un rango claro).
  • while: Cuando la repetición depende de una condición que puede cambiar de formas más complejas.

El ciclo do-while

La diferencia con while es que do-while siempre ejecuta el bloque al menos una vez, porque la condición se evalúa después:

do {
    // Se ejecuta al menos una vez
} while (condición);  // Nota el punto y coma al final

Analogía: "Prueba el platillo, y si no te gusta, prueba otro." (Primero pruebas, luego decides.)

int opcion;
do {
    cout << "1. Jugar" << endl;
    cout << "2. Opciones" << endl;
    cout << "3. Salir" << endl;
    cout << "Elige: ";
    cin >> opcion;

    if (opcion < 1 || opcion > 3) {
        cout << "Opción no válida, intenta de nuevo." << endl;
    }
} while (opcion != 3);

cout << "¡Hasta luego!" << endl;

Este menú se muestra al menos una vez, y se repite hasta que el usuario elija 3.

Usos comunes del while

1. Extraer dígitos de un número

int n = 12345;

while (n > 0) {
    int digito = n % 10;    // Último dígito
    cout << digito << " ";
    n /= 10;                // Quitar el último dígito
}
// Salida: 5 4 3 2 1 (los dígitos en orden inverso)

Paso a paso:

nn % 10 (dígito)n / 10 (nuevo n)
1234551234
12344123
123312
1221
110
0FIN

2. Suma de dígitos

int n;
cin >> n;

int suma = 0;
while (n > 0) {
    suma += n % 10;
    n /= 10;
}
cout << "Suma de dígitos: " << suma << endl;

Entrada: 1234 Salida: Suma de dígitos: 10 (porque 1+2+3+4 = 10)

3. Contar dígitos

int n;
cin >> n;

int digitos = 0;
int temp = n;

if (temp == 0) digitos = 1;  // Caso especial: el 0 tiene 1 dígito

while (temp > 0) {
    digitos++;
    temp /= 10;
}

cout << n << " tiene " << digitos << " dígitos" << endl;

4. Convertir decimal a binario

int n;
cin >> n;

string binario = "";
while (n > 0) {
    binario = (char)('0' + n % 2) + binario;  // Agregar al inicio
    n /= 2;
}

if (binario.empty()) binario = "0";
cout << binario << endl;

Entrada: 13 Salida: 1101 (porque 13 = 8+4+1 = 23+22+202^3 + 2^2 + 2^0)

5. Algoritmo de Euclides (GCD)

El máximo común divisor usando el algoritmo de Euclides:

int a, b;
cin >> a >> b;

while (b != 0) {
    int temp = b;
    b = a % b;
    a = temp;
}

cout << "GCD: " << a << endl;

Paso a paso con a=12, b=8:

aba % b
1284
840
40FIN

GCD(12, 8) = 4. ✓

6. Leer hasta EOF (fin de archivo)

int x;
while (cin >> x) {
    cout << x * 2 << '\n';
}

El ciclo continúa mientras haya datos para leer. Cuando el juez ya no envía más datos, cin >> x devuelve false y el ciclo termina.

7. Buscar algo específico

int n;
cin >> n;

// Encontrar la primera potencia de 2 mayor o igual a n
int potencia = 1;
while (potencia < n) {
    potencia *= 2;
}

cout << potencia << endl;

Entrada: 10 Salida: 16 (porque 1, 2, 4, 8, 16 ≥ 10)

Patrones avanzados

Simulación paso a paso

Muchos problemas de competencia te piden simular un proceso:

// Problema: Una bacteria se duplica cada hora.
// ¿Cuántas horas hasta que haya más de 1000 bacterias?

int bacterias = 1;
int horas = 0;

while (bacterias <= 1000) {
    bacterias *= 2;
    horas++;
}

cout << horas << " horas" << endl;
// Salida: 10 horas (2^10 = 1024 > 1000)

Secuencia de Collatz

Una secuencia famosa: empezando de cualquier número, si es par divídelo entre 2, si es impar multiplícalo por 3 y suma 1. Eventualmente llegas a 1.

int n;
cin >> n;

int pasos = 0;
while (n != 1) {
    cout << n << " -> ";
    if (n % 2 == 0) {
        n /= 2;
    } else {
        n = 3 * n + 1;
    }
    pasos++;
}
cout << 1 << endl;
cout << "Pasos: " << pasos << endl;

Entrada: 6 Salida: 6 -> 3 -> 10 -> 5 -> 16 -> 8 -> 4 -> 2 -> 1 (8 pasos)

while(t--): el patrón de múltiples casos

Muchos problemas en competencias tienen múltiples casos de prueba:

int t;
cin >> t;

while (t--) {
    // Resolver un caso
    int a, b;
    cin >> a >> b;
    cout << a + b << '\n';
}

¿Cómo funciona while(t--)?

  1. Evalúa t (si no es 0, es verdadero).
  2. Decrementa t.
  3. Si era verdadero, ejecuta el cuerpo.

Si t = 3, ejecuta el cuerpo 3 veces (con t tomando valores 2, 1, 0 internamente).

Ejercicio de práctica

Lee un número positivo y determina si es una potencia de 2. Un número es potencia de 2 si se puede obtener dividiendo repetidamente entre 2 hasta llegar a 1.

Entrada: 16Salida: Si (porque 16 → 8 → 4 → 2 → 1) Entrada: 12Salida: No (porque 12 → 6 → 3, y 3 no es divisible entre 2)

Ver solución
#include <iostream>
using namespace std;

int main() {
    int n;
    cin >> n;

    if (n <= 0) {
        cout << "No" << endl;
        return 0;
    }

    while (n > 1) {
        if (n % 2 != 0) {
            cout << "No" << endl;
            return 0;
        }
        n /= 2;
    }

    cout << "Si" << endl;

    return 0;
}

Alternativa elegante usando la propiedad de bits: una potencia de 2 en binario tiene exactamente un 1 (100...0). Entonces n & (n-1) es 0:

if (n > 0 && (n & (n - 1)) == 0) {
    cout << "Si" << endl;
} else {
    cout << "No" << endl;
}

Siguiente paso

Aprende sobre Funciones para organizar tu código en bloques reutilizables.