Bucles en Java — ejercicios con vocales, notas hasta el -1 y primos en un rango (y el bucle que se me colgó a mí)

El primer bucle que escribí en Java se quedó colgado. No dio error ni excepción: la terminal empezó a llenarse de «Vuelta 0», «Vuelta 0», «Vuelta 0»… tan deprisa que no daba tiempo a leer, y el ventilador del portátil se puso a sonar como un secador. Tuve que pararlo con Ctrl + C. El fallo era una línea que no estaba: el i++ que hace avanzar el bucle. La condición i < 5 era verdadera al principio y seguía siéndolo para siempre, porque nada la cambiaba. Lo verás con su salida real (y un freno para que no llene la página) en «¿Qué falla aquí?».

Aquí tienes tres ejercicios de bucles en Java, de menos a más: contar las vocales de una frase (recorrer un texto con for y un switch dentro), pedir notas hasta que llegue un -1 (centinela, acumuladores, máximo y mínimo sin guardar las notas) y buscar los primos de un rango (bucles anidados con break). Como en la práctica de bucles, todo lo que se teclea viene del Scanner y no hay arrays. Al final tienes el cuestionario tipo examen y el chuletario.

Cómo usar este artículo

  1. Lee el enunciado y la salida esperada de cada ejercicio. La salida es real: si tu programa imprime lo mismo con los mismos datos, vas bien.
  2. Inténtalo sin mirar nada al menos 15 minutos. Si te atascas, abre la pista.
  3. Antes de las soluciones, haz «¿Qué falla aquí?»: tres fragmentos con un error cada uno. Predice qué imprimen antes de leer la explicación.
  4. Compara tu solución con la comentada. Haz una tabla de traza con dos o tres vueltas: es la forma más rápida de encontrar dónde se separan las dos.

Las salidas son de una única ejecución con Java 21 en un equipo en español: los decimales se teclean con coma (7,5) y lo que aparece detrás de cada pregunta es lo que se tecleó. En el entorno de Java de la web lo tecleado va en la pestaña Entrada, una línea por dato.

Todos los temas de Java de FP2, en orden y con su cuestionario, están en los ejercicios de Java resueltos.

Nivel básico

Ejercicio 1 — Contador de vocales

Escribe ContadorVocales: pide una palabra o frase y cuenta cuántas veces aparece cada vocal, el total y cuál es la más repetida (en caso de empate, la primera en el orden a, e, i, o, u). Da igual que estén en mayúscula, y las vocales con tilde cuentan como su vocal (á es una a). Si no hay ninguna, lo dice.

Salida esperada con programacion:

=== CONTADOR DE VOCALES ===
Palabra o frase: programacion
--- Resultado ---
a: 2  e: 0  i: 1  o: 2  u: 0
Total de vocales: 5
La más repetida: a (2 veces)

Con mayúsculas y tildes:

=== CONTADOR DE VOCALES ===
Palabra o frase: Programación en Java
--- Resultado ---
a: 4  e: 1  i: 1  o: 2  u: 0
Total de vocales: 8
La más repetida: a (4 veces)

Sin vocales:

=== CONTADOR DE VOCALES ===
Palabra o frase: FP2 xyz 2026
--- Resultado ---
a: 0  e: 0  i: 0  o: 0  u: 0
Total de vocales: 0
No hay vocales.

Pasa el texto a minúsculas una vez, antes del bucle. Recorre con for (int k = 0; k < texto.length(); k++) (la i te la vas a querer quedar para el contador de la vocal i) y dentro, un switch sobre texto.charAt(k) con flechas: case 'a', 'á' -> a++;. Para la más repetida, empieza suponiendo que es la a y compárala con las demás usando >. Comprueba a mano: en «programacion» hay dos o, dos a y una i.

Nivel intermedio

Ejercicio 2 — Notas con valor centinela

Escribe NotasCentinela: pide notas una a una (con decimales) hasta que se teclee -1, que no es una nota sino la señal de que se ha terminado. Las notas fuera de 0-10 se rechazan con un aviso y no cuentan. Al terminar, muestra cuántas notas hay y cuántas aprobadas, la media con dos decimales, la máxima y la mínima, sin guardar las notas (todavía no hemos visto los arrays). Si no se ha metido ninguna, avisa y no calcula la media.

Salida esperada con 6, 8, 11 (no vale), 4, 9 y 7,5:

=== NOTAS DE LA ASIGNATURA ===
Escribe las notas una a una (de 0 a 10). Escribe -1 para terminar.
Nota: 6
Nota: 8
Nota: 11
  No vale: va de 0 a 10.
Nota: 4
Nota: 9
Nota: 7,5
Nota: -1
--- Resumen ---
Notas: 5 (aprobadas: 4)
Media: 6,90
Máxima: 9.0  Mínima: 4.0

Si la primera es el -1:

=== NOTAS DE LA ASIGNATURA ===
Escribe las notas una a una (de 0 a 10). Escribe -1 para terminar.
Nota: -1
--- Resumen ---
No hay notas: no se puede calcular la media.

Un do-while (true) que pide la nota y sale con break cuando es -1; para las notas fuera de rango, aviso y continue. Necesitas un contador, otro de aprobadas y un acumulador suma, todos fuera del bucle y empezando en 0. La máxima y la mínima no pueden empezar en 0: dales el valor de la primera nota válida (la vuelta en la que el contador pasa a 1). La media es suma / cuantas, y solo si cuantas > 0.

Desafío final

Ejercicio 3 — Números primos en un rango

Escribe PrimosEnRango: pide un inicio y un final y muestra los primos que hay entre los dos (incluidos), en filas de cinco. Al final, el total de primos y cuántas divisiones se han hecho para encontrarlos. Si el inicio es mayor que el final, avisa y termina. El 0 y el 1 no son primos: si el inicio es menor que 2, se empieza en 2.

Salida esperada de 10 a 30:

=== NÚMEROS PRIMOS EN UN RANGO ===
Desde: 10
Hasta: 30
--- Primos encontrados ---
11 13 17 19 23
29
Total: 6 primos (38 divisiones)

De 1 a 100:

=== NÚMEROS PRIMOS EN UN RANGO ===
Desde: 1
Hasta: 100
--- Primos encontrados ---
2 3 5 7 11
13 17 19 23 29
31 37 41 43 47
53 59 61 67 71
73 79 83 89 97
Total: 25 primos (236 divisiones)

Con el rango al revés:

=== NÚMEROS PRIMOS EN UN RANGO ===
Desde: 30
Hasta: 10
Rango no válido: «desde» tiene que ser menor o igual que «hasta».

El bucle de fuera recorre cada candidato n del rango; el de dentro prueba divisores d desde 2. Para cada candidato, una bandera esPrimo = true que el bucle de dentro pone a false si encuentra un divisor (y entonces break: ya no hace falta seguir). No hace falta probar hasta n - 1: basta con que d * d <= n. Para las filas de cinco, acumula los primos en un String e imprímelo cada vez que el total sea múltiplo de 5; al terminar, imprime lo que haya quedado.

¿Qué falla aquí?

Antes de las soluciones, tres fragmentos con un error cada uno: los tres compilan sin avisos. Lee cada uno y predice qué imprime antes de mirar la salida.

Error 1

public class Vueltas {
    public static void main(String[] args) {
        int i = 0;
        int freno = 0;                            // freno de emergencia: NO forma parte del error
        while (i < 5) {
            System.out.println("Vuelta " + i);
            freno++;
            if (freno == 6) {
                System.out.println("(freno: 6 vueltas y sigue)");
                break;
            }
        }
    }
}

¿Cuántas vueltas da? Salida real:

Vuelta 0
Vuelta 0
Vuelta 0
Vuelta 0
Vuelta 0
Vuelta 0
(freno: 6 vueltas y sigue)

Sin el freno, no terminaría nunca: es mi bucle colgado. La condición es i < 5, pero dentro del cuerpo nadie cambia i: vale 0 en la primera vuelta, en la segunda y en la millonésima. El freno (freno == 6) no forma parte del error: lo he puesto para que la salida quepa en la página.

Un while cuya condición depende de una variable que el cuerpo no modifica. El for lo hace más difícil porque el avance está en la cabecera (i++), pero en un while es responsabilidad tuya. Antes de ejecutar, señala con el dedo qué línea del cuerpo cambia la condición.

Arreglo:

public class Vueltas {
    public static void main(String[] args) {
        int i = 0;
        while (i < 5) {
            System.out.println("Vuelta " + i);
            i++;                                  // la variable de la condición tiene que cambiar
        }
    }
}
Vuelta 0
Vuelta 1
Vuelta 2
Vuelta 3
Vuelta 4

Error 2

public class BuscarPareja {
    public static void main(String[] args) {
        // Quiero la PRIMERA pareja (a, b) de 1 a 6 con a * b == 12
        for (int a = 1; a <= 6; a++) {
            for (int b = 1; b <= 6; b++) {
                if (a * b == 12) {
                    System.out.println("Encontrada: " + a + " x " + b);
                    break;
                }
            }
        }
        System.out.println("Fin de la búsqueda");
    }
}

Se quiere la primera pareja a × b = 12. Salida real:

Encontrada: 2 x 6
Encontrada: 3 x 4
Encontrada: 4 x 3
Encontrada: 6 x 2
Fin de la búsqueda

El break solo sale del bucle en el que está, el de dentro (b). El de fuera no se entera y pasa a a = 3, encuentra 3 × 4, sale de esa fila, pasa a la 4… En total, cuatro parejas.

break solo sale del bucle de dentroDos tablas de 6 por 6 con los productos a por b. Con solo break, cada fila se recorre hasta su primer 12 y la búsqueda sigue en la fila siguiente: aparecen 2×6, 3×4, 4×3 y 6×2. Con la bandera en la condición del for de fuera, la búsqueda acaba en 2×6.Solo break: 4 parejasa=1123456a=224681012a=3369121518a=44812162024a=551015202530a=661218243036Con bandera: 1 parejaa=1123456a=224681012a=3369121518a=44812162024a=551015202530a=661218243036En violeta, las casillas que se llegan a mirar; en coral, las que imprimen.
El break corta la fila, pero el for de fuera sigue con la siguiente.

Pensar que break sale de todos los bucles. Sale solo del más cercano. Para cortar también el de fuera hace falta una bandera en su condición (o una etiqueta, break busqueda;, como viste en la teoría).

Arreglo con bandera:

public class BuscarPareja {
    public static void main(String[] args) {
        boolean encontrada = false;
        for (int a = 1; a <= 6 && !encontrada; a++) {     // la bandera también para el de fuera
            for (int b = 1; b <= 6; b++) {
                if (a * b == 12) {
                    System.out.println("Encontrada: " + a + " x " + b);
                    encontrada = true;
                    break;
                }
            }
        }
        System.out.println("Fin de la búsqueda");
    }
}
Encontrada: 2 x 6
Fin de la búsqueda

Error 3

import java.util.Scanner;

public class MinimaMal {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        double minima = 0;
        System.out.print("Nota: ");
        double nota = sc.nextDouble();
        while (nota != -1) {
            if (nota < minima) {
                minima = nota;
            }
            System.out.print("Nota: ");
            nota = sc.nextDouble();
        }
        System.out.println("Mínima: " + minima);
    }
}

Con las notas 6, 8, 4 y 9, ¿cuál es la mínima? Salida real:

Nota: 6
Nota: 8
Nota: 4
Nota: 9
Nota: -1
Mínima: 0.0

minima empieza en 0, y ninguna nota real es menor que 0, así que el if no entra nunca y la «mínima» se queda en un 0 que nadie ha tecleado. El mismo fallo, al revés, haría que una máxima empezada en 100 no cambiara nunca.

Inicializar un mínimo (o un máximo) con un valor que «parece neutro». Para una suma, 0 es neutro; para un mínimo, no. O lo inicializas con el primer dato real, o con un valor que cualquier dato supere (Double.MAX_VALUE para un mínimo).

Arreglo con Double.MAX_VALUE:

import java.util.Scanner;

public class MinimaMal {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        double minima = Double.MAX_VALUE;          // cualquier nota real será menor
        System.out.print("Nota: ");
        double nota = sc.nextDouble();
        while (nota != -1) {
            if (nota < minima) {
                minima = nota;
            }
            System.out.print("Nota: ");
            nota = sc.nextDouble();
        }
        System.out.println("Mínima: " + minima);
    }
}
Nota: 6
Nota: 8
Nota: 4
Nota: 9
Nota: -1
Mínima: 4.0

Soluciones comentadas

Solución Ejercicio 1

import java.util.Scanner;

/**
 * Contador de vocales: un for recorre la frase y un switch suma a la vocal que toque.
 * Las vocales con tilde cuentan como su vocal (á → a) y da igual la mayúscula.
 */
public class ContadorVocales {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        System.out.println("=== CONTADOR DE VOCALES ===");
        System.out.print("Palabra o frase: ");
        String texto = sc.nextLine().toLowerCase();       // una sola conversión, fuera del bucle

        int a = 0, e = 0, i = 0, o = 0, u = 0;            // un contador por vocal, todos a 0
        for (int k = 0; k < texto.length(); k++) {        // k: la i ya es el contador de la vocal i
            switch (texto.charAt(k)) {
                case 'a', 'á' -> a++;
                case 'e', 'é' -> e++;
                case 'i', 'í' -> i++;
                case 'o', 'ó' -> o++;
                case 'u', 'ú', 'ü' -> u++;
                default -> { }                            // consonantes, espacios, dígitos: nada
            }
        }
        int total = a + e + i + o + u;
        System.out.println("--- Resultado ---");
        System.out.println("a: " + a + "  e: " + e + "  i: " + i + "  o: " + o + "  u: " + u);
        System.out.println("Total de vocales: " + total);

        if (total == 0) {
            System.out.println("No hay vocales.");
        } else {
            // La más repetida: se empieza suponiendo la a y se compara con las demás (> y no >=: en empate gana la primera)
            char masRepetida = 'a';
            int maximo = a;
            if (e > maximo) { masRepetida = 'e'; maximo = e; }
            if (i > maximo) { masRepetida = 'i'; maximo = i; }
            if (o > maximo) { masRepetida = 'o'; maximo = o; }
            if (u > maximo) { masRepetida = 'u'; maximo = u; }
            System.out.println("La más repetida: " + masRepetida + " (" + maximo + " veces)");
        }
        sc.close();
    }
}

Por qué está hecho así:

  • toLowerCase() una vez, fuera del bucle. Si lo hicieras dentro (Character.toLowerCase(c) en cada vuelta) también funcionaría, pero así el switch solo tiene que mirar minúsculas y no hay nada que repetir.
  • El índice se llama k. Los contadores a, e, i, o, u llevan el nombre de su vocal, y i ya está ocupada. Si el for usara int i, javac diría variable i is already defined in method main(String[]).
  • switch con flechas y varios valores por caso. case 'a', 'á' -> a++; junta la vocal con su tilde. El default -> { } vacío deja claro que el resto de caracteres se ignoran a propósito.
  • > y no >= para la más repetida. Con «programacion» la a y la o empatan a 2. Con >, la o no supera a la a y gana la primera (como pide el enunciado). Con >=, ganaría la última de las empatadas.
kcaráctercasoaio
2o'o'001
5a'a'101
7a'a'201
9i'i'211
10o'o'212

(Las vueltas de las consonantes van al default y no cambian nada; total: 2 + 1 + 2 = 5.)

Solución Ejercicio 2

import java.util.Scanner;

/**
 * Notas con valor centinela: se piden notas hasta que llegue -1. Acumulador para la media,
 * contadores y máximo/mínimo SIN guardar las notas (sin arrays).
 */
public class NotasCentinela {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        System.out.println("=== NOTAS DE LA ASIGNATURA ===");
        System.out.println("Escribe las notas una a una (de 0 a 10). Escribe -1 para terminar.");

        int cuantas = 0, aprobadas = 0;
        double suma = 0;
        double maxima = 0, minima = 0;            // se sobrescriben con la primera nota válida
        double nota;
        do {
            System.out.print("Nota: ");
            nota = sc.nextDouble();
            if (nota == -1) {
                break;                            // el centinela no es una nota: no se cuenta
            }
            if (nota < 0 || nota > 10) {
                System.out.println("  No vale: va de 0 a 10.");
                continue;                         // do-while: salta a la condición del final
            }
            cuantas++;
            suma += nota;
            if (nota >= 5) {
                aprobadas++;
            }
            if (cuantas == 1) {                   // la primera nota es a la vez la máxima y la mínima
                maxima = nota;
                minima = nota;
            } else if (nota > maxima) {
                maxima = nota;
            } else if (nota < minima) {
                minima = nota;
            }
        } while (true);                           // solo se sale con el break del centinela

        System.out.println("--- Resumen ---");
        if (cuantas == 0) {
            System.out.println("No hay notas: no se puede calcular la media.");
        } else {
            System.out.println("Notas: " + cuantas + " (aprobadas: " + aprobadas + ")");
            System.out.printf("Media: %.2f%n", suma / cuantas);
            System.out.println("Máxima: " + maxima + "  Mínima: " + minima);
        }
        sc.close();
    }
}

Por qué está hecho así:

  • do-while (true) con break. Hay que pedir la nota antes de poder saber si es el centinela, así que el cuerpo se ejecuta al menos una vez. La salida está en medio del cuerpo (en el break), no en la condición: por eso la condición es true.
  • El centinela no se cuenta. El break va antes de cuantas++ y suma += nota. Si fuera después, el -1 entraría en la media.
  • continue en las notas fuera de rango. En un do-while, salta a la condición del final (true), así que se vuelve a pedir otra nota sin contar el 11.
  • Máxima y mínima con la primera nota. Cuando cuantas pasa a 1, esa nota es a la vez la máxima y la mínima; a partir de ahí, solo se cambian si una nota las supera. El else if es seguro: una nota no puede ser a la vez mayor que la máxima y menor que la mínima.
  • Las cuentas. Notas válidas: 6, 8, 4, 9 y 7,5. Suma: 6 + 8 + 4 + 9 + 7,5 = 34,5. Media: 34,5 / 5 = 6,90. Aprobadas: todas menos el 4, es decir, 4. La máxima y la mínima salen con punto (9.0, 4.0) porque las imprime + con un double; la media sale con coma porque es printf.
Tecleado¿Cuenta?cuantassumamaximaminima
6Sí1666
8Sí21486
11No: continue21486
4Sí31884
9Sí42794
7,5Sí534,594
-1No: break534,594

Solución Ejercicio 3

import java.util.Scanner;

/**
 * Primos en un rango: el bucle de fuera recorre los números y el de dentro busca un divisor
 * hasta la raíz cuadrada (d * d <= n), cortando con break en cuanto lo encuentra.
 */
public class PrimosEnRango {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        System.out.println("=== NÚMEROS PRIMOS EN UN RANGO ===");
        System.out.print("Desde: ");
        int desde = sc.nextInt();
        System.out.print("Hasta: ");
        int hasta = sc.nextInt();

        if (desde > hasta) {
            System.out.println("Rango no válido: «desde» tiene que ser menor o igual que «hasta».");
            return;
        }
        if (desde < 2) {
            desde = 2;                                    // ni el 0 ni el 1 son primos: se empieza en 2
        }

        System.out.println("--- Primos encontrados ---");
        int total = 0, divisiones = 0;
        String fila = "";
        for (int n = desde; n <= hasta; n++) {            // bucle de fuera: cada candidato
            boolean esPrimo = true;                       // se reinicia en CADA candidato
            for (int d = 2; d * d <= n; d++) {            // bucle de dentro: divisores hasta la raíz
                divisiones++;
                if (n % d == 0) {
                    esPrimo = false;
                    break;                                // sale solo del bucle de dentro
                }
            }
            if (esPrimo) {
                total++;
                fila += n + " ";
                if (total % 5 == 0) {                     // cada 5 primos, una línea
                    System.out.println(fila.trim());
                    fila = "";
                }
            }
        }
        if (!fila.isEmpty()) {
            System.out.println(fila.trim());              // la última línea, si quedó a medias
        }
        System.out.println("Total: " + total + " primos (" + divisiones + " divisiones)");
        sc.close();
    }
}

Por qué está hecho así:

  • esPrimo = true dentro del bucle de fuera. Cada candidato empieza siendo «primo hasta que se demuestre lo contrario». Si se declarara fuera, en cuanto un número no fuera primo la bandera se quedaría en false para todos los siguientes.
  • d * d <= n en lugar de d < n. Los divisores van por parejas: si 28 = 2 × 14, al probar el 2 ya lo has encontrado. Si un número tuviera un divisor mayor que su raíz, su pareja sería menor y habría salido antes. Así se ahorra la mayoría de las divisiones:
Hasta la raíz cuadrada bastaLos números del 2 al 28 en fila. Solo 2, 3, 4 y 5 cumplen d por d menor o igual que 29; con 6, 36 ya pasa de 29 y el bucle se para. Son 4 divisiones en lugar de 27.¿Es primo el 29? Divisores que se prueban23456789101112131415161718192021222324252627286 × 6 = 36 > 29: se parad * d <= n4 divisiones (2, 3, 4, 5)d < n27 divisiones (de 2 a 28)Si 29 tuviera un divisor mayor que 5, su pareja sería menor que 5 y ya habría salido.
Los divisores van por parejas (2 × 14 = 28): basta con buscar la pequeña.
  • break sale solo del bucle de dentro, que es justo lo que queremos aquí: dejar de probar divisores de este candidato y pasar al siguiente. Es el mismo break que daba problemas en el error 2; la diferencia es lo que se quería hacer.
  • Las filas de cinco. total % 5 == 0 es verdadero con el 5.º, el 10.º… primo. Lo que queda a medias (el 29 en el rango 10-30) se imprime después del bucle.
  • Las cuentas del rango 10-30. Primos: 11, 13, 17, 19, 23 y 29, seis. Divisiones: 38. Por ejemplo, el 29 prueba 2, 3, 4 y 5 (4 divisiones); con d < n habrían sido 27.
ndivisores probados¿Primo?divisiones acumuladas
102 (10 % 2 = 0, break)No1
112, 3 (4 × 4 = 16 > 11, para)Sí3
122 (break)No4
132, 3Sí6

Cuestionario tipo examen

Ahora ponte a prueba como en el examen. El cuestionario de Java de FP2 es así: 15 preguntas en 15 minutos sobre todo el temario de Java, de las que te tocan unas pocas de cada tema. Aquí tienes las de bucles: contesta sin ejecutar nada, corrige y lee la explicación de las que falles. Estas preguntas son también el banco del simulacro de teoría de FP2.

Pregunta 1Respuesta corta

¿Qué número imprime este fragmento?

int n = 0;
for (int i = 10; i > 0; i -= 3) n++;
System.out.println(n);
Solución

Respuesta: 4

i toma los valores 10, 7, 4 y 1: cuatro vueltas. Después pasa a −2, la condición i > 0 es falsa y el bucle termina. Contar los valores de i uno a uno es la forma segura de no equivocarse en uno.

Pregunta 2Rellenar huecos

En Python tienes for i in range(10, 0, -2):. Completa el bucle de Java que hace lo mismo:

for (int i = ____; i ____ 0; i ____ 2)

Palabras:

  • 0
  • 10
  • +=
  • <
  • -=
  • >=
  • >
Solución

for (int i = 10; i > 0; i -= 2)

range(10, 0, -2) empieza en 10, baja de 2 en 2 y no incluye el 0: 10, 8, 6, 4, 2. Por eso la condición es i > 0 (con >= se colaría el 0). El tercer argumento de range es el paso: aquí, restar 2.

Pregunta 3Respuesta corta

¿Qué imprime este fragmento?

int k = 5;
do {
    System.out.print(k);
    k++;
} while (k < 3);
System.out.println();
Solución

Respuesta: 5

El do-while comprueba la condición al final, así que el cuerpo se ejecuta al menos una vez aunque 5 < 3 sea falso desde el principio. Con un while normal no se imprimiría nada.

Pregunta 4Respuesta corta

¿Qué imprime este fragmento?

for (int i = 1; i <= 6; i++) {
    if (i % 2 == 0) continue;
    if (i == 5) break;
    System.out.print(i);
}
System.out.println();
Solución

Respuesta: 13

Los pares se saltan con continue (pasan a la siguiente vuelta sin imprimir). Se imprimen el 1 y el 3; al llegar al 5, break corta el bucle entero, así que el 5 no sale.

Pregunta 5Única

¿Qué imprime este fragmento?

int[] v = {1, 2, 3};
for (int x : v) x = x * 10;
System.out.println(v[0] + v[1] + v[2]);
  1. 6
  2. 60
  3. 123
  4. No compila
Solución

Respuesta: 6

En un for-each, la variable recibe una copia del valor de cada elemento (con primitivos). Para modificar el array necesitas su índice: for (int i = 0; i < v.length; i++) v[i] *= 10;.

Pregunta 6Respuesta corta

¿Qué número imprime este fragmento?

int c = 0;
for (int i = 0; i < 4; i++)
    for (int j = i; j < 4; j++)
        c++;
System.out.println(c);
Solución

Respuesta: 10

El bucle interno empieza en i, así que da 4 vueltas cuando i = 0, 3 cuando i = 1, 2 y 1: 4 + 3 + 2 + 1 = 10. Es el patrón de recorrer solo la mitad de una matriz (o comparar cada pareja una vez).

Pregunta 7Verdadero o falso

Indica si es verdadero o falso:

  1. El cuerpo de un do-while se ejecuta al menos una vez.
  2. El for-each te da en cada vuelta el índice del elemento.
  3. Una variable declarada en la cabecera del for no existe después del bucle.
  4. while (true) con un break dentro es un bucle válido.
  5. for (;;) no compila porque le faltan las tres partes.
Solución
  • V — El cuerpo de un do-while se ejecuta al menos una vez.
  • F — El for-each te da en cada vuelta el índice del elemento.
  • V — Una variable declarada en la cabecera del for no existe después del bucle.
  • V — while (true) con un break dentro es un bucle válido.
  • F — for (;;) no compila porque le faltan las tres partes.

El for-each da el valor, no la posición: si necesitas el índice, usa un for clásico. Las tres partes del for son opcionales: for (;;) es un bucle infinito, igual que while (true).

Pregunta 8Única

¿Qué número imprime este fragmento?

int suma = 0;
for (int i = 1; i <= 10; i += 2) suma += i;
System.out.println(suma);
  1. 25
  2. 30
  3. 36
  4. 55
Solución

Respuesta: 25

Con paso 2 desde el 1, i vale 1, 3, 5, 7 y 9; al pasar a 11 la condición falla. La suma de los impares es 25.

Pregunta 9Ordenar

Ordena lo que hace un for (inicio; condición; actualización) en sus primeras vueltas:

  1. Ejecuta la inicialización (una sola vez)
  2. Vuelve a comprobar la condición
  3. Ejecuta el cuerpo
  4. Comprueba la condición
  5. Ejecuta la actualización
Solución

Orden correcto:

  1. Ejecuta la inicialización (una sola vez)
  2. Comprueba la condición
  3. Ejecuta el cuerpo
  4. Ejecuta la actualización
  5. Vuelve a comprobar la condición

La inicialización va una sola vez al principio. Después se repite: condición → cuerpo → actualización. Si la condición es falsa desde el principio, el cuerpo no se ejecuta nunca.

Pregunta 10Relacionar

Relaciona cada situación con el bucle más adecuado:

Repetir un número de veces que ya conoces
Pedir un dato hasta que sea válido (al menos una vez)
Recorrer todos los elementos sin necesitar su posición
Repetir mientras se cumpla algo que puede ser falso desde el principio

Definiciones:

  • switch
  • while
  • for-each
  • do-while
  • for
Solución
  • Repetir un número de veces que ya conoces → for
  • Pedir un dato hasta que sea válido (al menos una vez) → do-while
  • Recorrer todos los elementos sin necesitar su posición → for-each
  • Repetir mientras se cumpla algo que puede ser falso desde el principio → while

El for es para contar; el do-while, para «hazlo una vez y repite si hace falta» (validar entradas); el for-each, para recorrer; y el while, para condiciones que no dependen de un contador. switch no es un bucle.

Pregunta 11Respuesta corta

¿Qué imprime este fragmento?

String s = "";
int i = 3;
while (i > 0) {
    s = s + i;
    i--;
}
System.out.println(s + i);
Solución

Respuesta: 3210

En cada vuelta se pega i al final de s: "3", "32", "321". Cuando i llega a 0 el bucle termina, pero i sigue existiendo (se declaró fuera) y vale 0, así que se imprime 3210.

Míralo paso a paso en Python Tutor

Python Tutor (pythontutor.com) ejecuta el código línea a línea y enseña cómo cambian las variables. Elige Java en el desplegable y pega este programa, la búsqueda de primos de 10 a 15:

public class TutorPrimos {
    public static void main(String[] args) {
        int total = 0;
        for (int n = 10; n <= 15; n++) {
            boolean esPrimo = true;
            for (int d = 2; d * d <= n; d++) {
                if (n % d == 0) {
                    esPrimo = false;
                    break;
                }
            }
            if (esPrimo) {
                total++;
                System.out.println(n + " es primo");
            }
        }
        System.out.println("Total: " + total);
    }
}

Salida:

11 es primo
13 es primo
Total: 2

Qué observar paso a paso:

  1. Con n = 10, el bucle de dentro da una sola vuelta: 10 % 2 == 0, esPrimo pasa a false y el break lo saca enseguida.
  2. Con n = 11, prueba d = 2 y d = 3; con d = 4, 4 * 4 = 16 ya no es <= 11 y el bucle termina sin break: esPrimo sigue en true.
  3. Fíjate en que esPrimo vuelve a true al empezar cada candidato: se crea de nuevo en cada vuelta de fuera.
  4. total solo sube con 11 y 13: termina en 2.

Resumen

  • Un bucle tiene que tener una forma de terminar: alguna variable de su condición cambia en cada vuelta (o hay un break que se alcanza seguro).
  • Recorrer un texto: for (int k = 0; k < texto.length(); k++), con <.
  • Centinela: pedir, comprobar si es el valor de salida con break y, si no, procesarlo. El centinela nunca se cuenta.
  • Acumuladores y contadores, fuera del bucle y a 0; máximo y mínimo, con el primer dato real (o con Double.MAX_VALUE/-Double.MAX_VALUE).
  • break sale solo del bucle más cercano; para cortar el de fuera, una bandera en su condición o una etiqueta.
  • En bucles anidados, lo que se reinicia en cada vuelta de fuera (como esPrimo) se declara dentro del bucle de fuera.

Chuletario: bucles en Java

Lo esencial en 30 segundos: si sabes cuántas vueltas, for; si depende de lo que pase, while; si hay que hacerlo al menos una vez, do-while. Las posiciones van de 0 a length() - 1, así que <. Algo de la condición tiene que cambiar en cada vuelta. break sale del bucle más cercano y continue salta a la siguiente vuelta. Los acumuladores empiezan en 0; los máximos y mínimos, con el primer dato.

Quiero…CódigoResultado
Recorrer un textofor (int k = 0; k < t.length(); k++)posiciones 0 a length() - 1
Recorrerlo al revésfor (int k = t.length() - 1; k >= 0; k--)de la última a la 0
Solo los caracteresfor (char c : t.toCharArray())sin índice
Dos índices a la vezfor (int i = 0, j = n - 1; i < j; i++, j--)se cruzan a mitad
Repetir mientras se cumplawhile (intentos < MAX && !acertado)puede no entrar nunca
Repetir al menos una vezdo { … } while (opcion != 0);entra siempre
Leer hasta un centinelado { x = sc.nextInt(); if (x == -1) break; … } while (true);el -1 no se procesa
Saltar un dato maloif (malo) { continue; }vuelve a la condición
Salir de dos buclesbandera en la condición de fuera, o break etiqueta;corta los dos
Mínimo sin datos previosdouble min = Double.MAX_VALUE;cualquier dato es menor
¿Es primo?for (int d = 2; d * d <= n; d++)hasta la raíz

Plantillas de los ejercicios:

EjercicioPatrónCon estos datosSale
Vocalesfor + switch con flechas, un contador por vocalprogramaciontotal 5, más repetida a (2)
Centinelado-while (true) + break + continue, máx/mín con el primer dato6, 8, 11, 4, 9, 7,5, -15 notas, media 6,90, 9.0 / 4.0
Primosanidados, bandera reiniciada, d * d <= n + breakde 10 a 306 primos, 38 divisiones
SíntomaCausa probable
El programa no terminanada cambia la variable de la condición (falta el i++)
StringIndexOutOfBoundsException: Index N out of bounds for length N<= en lugar de <
La media incluye el -1el break del centinela va después de sumar
El mínimo sale 0 (o el máximo no cambia)se inicializó con 0 en lugar del primer dato
Salen varios resultados y se quería unobreak solo sale del bucle de dentro
Después del primer no-primo, ninguno es primola bandera se declaró fuera del bucle de fuera
variable i is already definedel mismo nombre en dos bucles anidados (o en un contador)

Antes de entregar, pregúntate:

  1. ¿Qué línea del cuerpo cambia la condición de cada bucle?
  2. ¿He probado el caso vacío (el -1 a la primera, un texto sin vocales, un rango sin primos)?
  3. ¿Mis acumuladores están fuera del bucle y lo que se reinicia, dentro?
  4. ¿Cada break sale del bucle que yo creo?

Con esto cierras los bucles. El siguiente tema es métodos en Java: el bloque que repetías tres veces en el adivino, y la comprobación de primo, se convierten en un método con nombre que se llama desde donde haga falta.

Sigue aprendiendoTodos los artículos de Java

¿Te ha servido este artículo? Así puedes apoyar SergioLearns →