📋 Introducción: de las decisiones a los bucles
En la primera parte de diagramas de flujo se estudiaron los fundamentos: los símbolos básicos (óvalo, rectángulo, rombo, paralelogramo, flechas), las estructuras secuenciales y las estructuras de decisión (if-else). Con esas herramientas se pueden representar algoritmos lineales y con bifurcaciones, pero la mayoría de los problemas reales requieren algo más: repetir acciones.
Las estructuras repetitivas (también llamadas bucles, ciclos o iteraciones) permiten ejecutar un bloque de acciones múltiples veces sin tener que dibujarlas repetidamente. Son la base de operaciones tan comunes como recorrer una lista de datos, pedir datos al usuario hasta que introduzca un valor válido, calcular sumatorios, o procesar ficheros línea a línea.
En esta segunda parte se abordan las tres estructuras repetitivas fundamentales (while, do-while y for), el concepto de subprocesos para modularizar algoritmos complejos, el anidamiento de estructuras, y la traducción directa de diagramas de flujo a código Java.
💡 Recordatorio de símbolos clave: El rombo (decisión) es el símbolo protagonista de los bucles. La diferencia entre una decisión simple y un bucle está en las líneas de flujo: si una flecha vuelve a un punto anterior, se forma un ciclo repetitivo.
🔁 Estructura repetitiva while (mientras)
La estructura while (mientras) evalúa una condición antes de ejecutar el bloque de acciones. Si la condición es verdadera, se ejecutan las acciones y se vuelve a evaluar la condición. El ciclo se repite hasta que la condición sea falsa. Si la condición es falsa desde el principio, el bloque no se ejecuta nunca.
Representación en diagrama de flujo
El diagrama de un while sigue este patrón visual: desde el flujo principal se llega a un rombo de condición. Si la condición es verdadera (rama «Sí»), se ejecutan las acciones en rectángulos y una flecha de retroalimentación vuelve al rombo. Si la condición es falsa (rama «No»), el flujo continúa hacia adelante, saliendo del bucle.
Pseudocódigo del whileMIENTRAS (condición) HACER acción 1 acción 2 ... acción que modifica la condición FIN MIENTRAS Ejemplo concreto: ────────────────── contador ← 1 MIENTRAS (contador ≤ 5) HACER ESCRIBIR "Iteración número: ", contador contador ← contador + 1 FIN MIENTRAS ESCRIBIR "Fin del bucle" Salida: Iteración número: 1 Iteración número: 2 Iteración número: 3 Iteración número: 4 Iteración número: 5 Fin del bucle
Traducción directa a Java
Java — Equivalente del diagrama whilepublic class EjemploWhile { public static void main(String[] args) { int contador = 1; while (contador <= 5) { System.out.println("Iteración número: " + contador); contador++; // ¡Imprescindible! Sin esto, bucle infinito } System.out.println("Fin del bucle"); } } // Salida: // Iteración número: 1 // Iteración número: 2 // Iteración número: 3 // Iteración número: 4 // Iteración número: 5 // Fin del bucle
⚠️ Bucle infinito: Si la condición del while nunca se vuelve falsa, el bucle se ejecuta indefinidamente. En un diagrama de flujo, esto se identifica cuando no existe ninguna acción dentro del bucle que pueda modificar la condición. Es el error más común al diseñar bucles.
Ejemplo práctico: sumar números hasta un valor
Java — Sumar números introducidos por el usuarioimport java.util.Scanner; public class SumaInteractiva { public static void main(String[] args) { Scanner teclado = new Scanner(System.in); double suma = 0; double numero; System.out.println("Introduce números para sumar (0 para terminar):"); System.out.print("Número: "); numero = teclado.nextDouble(); while (numero != 0) { // Condición: mientras no sea 0 suma = suma + numero; // Acción: acumular System.out.print("Número: "); numero = teclado.nextDouble(); // Modificar la condición } System.out.println("La suma total es: " + suma); teclado.close(); } } // Ejemplo de ejecución: // Número: 10 // Número: 25.5 // Número: 7 // Número: 0 // La suma total es: 42.5
🔂 Estructura do-while (repetir hasta)
La estructura do-while (hacer-mientras, también conocida como «repetir hasta» en pseudocódigo) es una variante del while en la que las acciones se ejecutan primero y la condición se evalúa después. Esto garantiza que el bloque se ejecuta al menos una vez, independientemente de la condición.
En un diagrama de flujo, la diferencia visual es clara: el rombo de condición aparece debajo de las acciones, no encima. La línea de retroalimentación sube desde el rombo (rama «Sí» o «Verdadero») de vuelta al inicio de las acciones.
Pseudocódigo vs Java — Do-while// Pseudocódigo // Java equivalente REPETIR do { ESCRIBIR "Introduce tu edad" System.out.print("Introduce tu edad: "); LEER edad edad = teclado.nextInt(); SI (edad < 0 O edad > 120) if (edad < 0 || edad > 120) { ESCRIBIR "Edad no válida" System.out.println("Edad no válida"); FIN SI } HASTA QUE (edad ≥ 0 Y edad ≤ 120) } while (edad < 0 || edad > 120); // Nota importante: en pseudocódigo "REPETIR...HASTA QUE" repite // mientras la condición sea FALSA (repite HASTA que sea verdadera). // En Java "do...while" repite mientras la condición sea VERDADERA. // La lógica se invierte al traducir.
¿Cuándo usar while y cuándo do-while?
| Situación | Estructura recomendada | Razón |
|---|---|---|
| Pedir un dato hasta que sea válido | do-while | Necesitamos pedir al menos una vez |
| Mostrar un menú de opciones | do-while | El menú debe mostrarse al menos una vez |
| Leer datos de un fichero | while | El fichero podría estar vacío |
| Buscar un elemento en una lista | while | La lista podría estar vacía |
| Juego que repite hasta «salir» | do-while | Al menos una ronda se debe jugar |
Java — Menú interactivo con do-whileimport java.util.Scanner; public class MenuInteractivo { public static void main(String[] args) { Scanner teclado = new Scanner(System.in); int opcion; do { System.out.println("\n=== MENÚ PRINCIPAL ==="); System.out.println("1. Consultar saldo"); System.out.println("2. Realizar transferencia"); System.out.println("3. Ver movimientos"); System.out.println("0. Salir"); System.out.print("Elige opción: "); opcion = teclado.nextInt(); switch (opcion) { case 1: System.out.println("→ Tu saldo es: 1.250,00 €"); break; case 2: System.out.println("→ Transferencia realizada"); break; case 3: System.out.println("→ Mostrando últimos movimientos..."); break; case 0: System.out.println("→ ¡Hasta pronto!"); break; default: System.out.println("→ Opción no válida"); } } while (opcion != 0); // Repetir hasta que elija salir teclado.close(); } }
🔢 Estructura repetitiva for (para)
La estructura for (para) se utiliza cuando se conoce de antemano el número exacto de repeticiones. Es una versión más compacta del while que agrupa en una sola línea la inicialización, la condición y el incremento de la variable de control.
En un diagrama de flujo, el for se descompone en sus tres partes constituyentes, ya que no existe un símbolo específico para él:
Descomposición del for en diagrama de flujoEn Java: En diagrama de flujo: ───────── ────────────────────── for (int i = 0; i < 10; i++) { ┌──────────────────┐ // acciones │ i = 0 │ ← Rectángulo: inicialización } └────────┬─────────┘ ▼ ◇ ¿i < 10? ◇───No──→ (continúa) │ Sí ▼ ┌──────────────────┐ │ acciones │ ← Rectángulo: cuerpo └────────┬─────────┘ ▼ ┌──────────────────┐ │ i = i + 1 │ ← Rectángulo: incremento └────────┬─────────┘ │ └───────→ (vuelve al rombo)
Ejemplo: tabla de multiplicar
Java — Tabla de multiplicar con forimport java.util.Scanner; public class TablaMultiplicar { public static void main(String[] args) { Scanner teclado = new Scanner(System.in); System.out.print("¿Tabla del número? "); int numero = teclado.nextInt(); System.out.println("\n=== Tabla del " + numero + " ==="); for (int i = 1; i <= 10; i++) { int resultado = numero * i; System.out.printf("%d × %d = %d%n", numero, i, resultado); } teclado.close(); } } // Entrada: 7 // Salida: // === Tabla del 7 === // 7 × 1 = 7 // 7 × 2 = 14 // ... // 7 × 10 = 70
🪆 Anidamiento de estructuras
El anidamiento consiste en colocar una estructura de control (secuencia, decisión o bucle) dentro de otra. Es una técnica fundamental para resolver problemas complejos. En los diagramas de flujo, el anidamiento se visualiza como estructuras contenidas dentro de otras, siguiendo siempre una jerarquía clara.
Las combinaciones más habituales de anidamiento son: un if dentro de un while (filtrar datos durante un recorrido), un for dentro de otro for (recorrer matrices o generar tablas bidimensionales), y un while dentro de un do-while (menú con opciones que requieren bucles internos).
Java — Bucles anidados: triángulo de asteriscospublic class TrianguloAsteriscos { public static void main(String[] args) { int filas = 5; // Bucle exterior: controla las filas for (int fila = 1; fila <= filas; fila++) { // Bucle interior: controla los asteriscos por fila for (int columna = 1; columna <= fila; columna++) { System.out.print("* "); } System.out.println(); // Salto de línea al terminar cada fila } } } // Salida: // * // * * // * * * // * * * * // * * * * *
Java — Anidamiento: encontrar números primos hasta Npublic class NumerosPrimos { public static void main(String[] args) { int limite = 50; System.out.println("Números primos del 2 al " + limite + ":"); for (int candidato = 2; candidato <= limite; candidato++) { boolean esPrimo = true; // Bucle interior: probar divisores for (int divisor = 2; divisor <= Math.sqrt(candidato); divisor++) { if (candidato % divisor == 0) { esPrimo = false; break; // No hace falta seguir probando } } if (esPrimo) { System.out.print(candidato + " "); } } } } // Salida: 2 3 5 7 11 13 17 19 23 29 31 37 41 43 47
📦 Subprocesos y modularización
Cuando un algoritmo se vuelve complejo, representarlo en un único diagrama de flujo resulta inmanejable. La solución es descomponer el problema en subprocesos (también llamados subrutinas o módulos). Cada subproceso se representa con un símbolo especial: un rectángulo con doble línea vertical en los laterales.
El concepto de subproceso en un diagrama de flujo es el equivalente directo a un método (función) en Java. El diagrama principal invoca al subproceso por su nombre, y el subproceso tiene su propio diagrama de flujo independiente con sus símbolos de inicio y fin.
Pseudocódigo — Algoritmo modular con subprocesosALGORITMO Principal INICIO LEER numero resultado ← LLAMAR calcularFactorial(numero) ESCRIBIR "El factorial de ", numero, " es ", resultado FIN SUBPROCESO calcularFactorial(n) INICIO factorial ← 1 i ← 1 MIENTRAS (i ≤ n) HACER factorial ← factorial × i i ← i + 1 FIN MIENTRAS DEVOLVER factorial FIN SUBPROCESO
Java — Equivalente con métodosimport java.util.Scanner; public class FactorialModular { // Subproceso → método en Java public static long calcularFactorial(int n) { long factorial = 1; for (int i = 1; i <= n; i++) { factorial *= i; } return factorial; } // Algoritmo principal → método main public static void main(String[] args) { Scanner teclado = new Scanner(System.in); System.out.print("Introduce un número: "); int numero = teclado.nextInt(); long resultado = calcularFactorial(numero); // Llamada al subproceso System.out.println("El factorial de " + numero + " es " + resultado); teclado.close(); } } // Entrada: 6 // Salida: El factorial de 6 es 720
🔄 Traducción de diagramas de flujo a Java
Una de las habilidades más valiosas en la formación de un programador es saber traducir directamente un diagrama de flujo a código. Cada símbolo del diagrama tiene un equivalente preciso en Java, y la traducción es mecánica si se sigue un proceso sistemático.
Proceso de traducción paso a paso
El proceso de traducción sigue estas reglas: primero se identifica la estructura general del diagrama (¿es secuencial, tiene decisiones, tiene bucles?). Después se traduce de arriba a abajo, símbolo por símbolo, respetando la indentación del código para reflejar la jerarquía visual del diagrama. Cada vez que se encuentra una línea de retroalimentación (flecha que vuelve hacia arriba), se abre un bloque while o do-while según dónde esté la condición.
📊 Tabla de equivalencias: diagrama ↔ Java
| Símbolo | Significado | Código Java equivalente |
|---|---|---|
| ⬭ Óvalo | Inicio / Fin del algoritmo | public static void main(String[] args) { } |
| ▭ Rectángulo | Proceso / Acción | Instrucción: suma = a + b; |
| ▱ Paralelogramo | Entrada / Salida de datos | Scanner.nextInt() / System.out.println() |
| ◇ Rombo | Decisión (condición) | if (condicion) { } else { } |
| ◇ + retroalimentación arriba | Bucle while | while (condicion) { } |
| Acciones + ◇ + retroalimentación | Bucle do-while | do { } while (condicion); |
| Init + ◇ + cuerpo + incremento | Bucle for | for (init; cond; incr) { } |
| ▭▭ Rectángulo doble borde | Subproceso / Módulo | Llamada a método: resultado = calcular(x); |
| → Flecha | Flujo de ejecución | Orden secuencial de instrucciones |
❌ Errores frecuentes en diagramas con bucles
Error 1: Bucle infinito (sin modificar la condición)
Java — ❌ vs ✅// ❌ INCORRECTO: la variable 'i' nunca cambia → bucle infinito int i = 1; while (i <= 10) { System.out.println(i); // Falta: i++; } // ✅ CORRECTO: i se incrementa y eventualmente supera 10 int i = 1; while (i <= 10) { System.out.println(i); i++; // Modifica la variable de control }
Error 2: Error off-by-one (uno de más o de menos)
Java// ❌ Error: imprime del 1 al 9 (falta el 10) for (int i = 1; i < 10; i++) { // < en vez de <= System.out.println(i); } // ✅ Correcto: imprime del 1 al 10 for (int i = 1; i <= 10; i++) { // <= incluye el 10 System.out.println(i); } // Tip: en el diagrama de flujo, verificar: ¿la condición del rombo // usa ≤ (menor o igual) o < (menor estricto)? Es la causa más // habitual de que un bucle se ejecute una vez de más o de menos.
Error 3: Confundir while y do-while al traducir
Al trasladar un diagrama a código, hay que observar dónde está el rombo de decisión: si está antes de las acciones es un while; si está después es un do-while. Invertir esta correspondencia hace que el programa se comporte de forma diferente al diagrama diseñado.
🖥️ Herramientas modernas para crear diagramas de flujo
Aunque los diagramas de flujo pueden dibujarse a mano, existen herramientas digitales que facilitan enormemente su creación, edición y compartición. Estas son las más populares en el ámbito educativo y profesional:
| Herramienta | Tipo | Características |
|---|---|---|
| draw.io (diagrams.net) | Web, gratuita | Muy completa, integración con Google Drive. Ideal para estudiantes. |
| Lucidchart | Web, freemium | Colaboración en tiempo real. Muy usada en empresas. |
| PSeInt | Escritorio, gratuita | Genera diagramas desde pseudocódigo y viceversa. Muy popular en universidades hispanohablantes. |
| Mermaid | Texto → diagrama | Genera diagramas desde código de texto. Integrado en GitHub y Notion. |
| Flowgorithm | Escritorio, gratuita | Ejecuta diagramas de flujo directamente. Genera código en Java, Python, C++, etc. |
✅ Recomendación para principiantes: PSeInt permite escribir pseudocódigo en español y genera automáticamente el diagrama de flujo correspondiente (y viceversa). Además, puede ejecutar el algoritmo paso a paso, lo que facilita enormemente la depuración visual. Es la herramienta más utilizada en las universidades de habla hispana.
🧩 Ejemplo integrador: sistema de cajero automático
El siguiente ejemplo integrador combina todas las estructuras estudiadas: bucles while y do-while, decisiones anidadas, subprocesos y validación de datos. Simula un cajero automático simplificado.
Java — CajeroAutomatico.java (ejemplo integrador)import java.util.Scanner; /** * Simulador de cajero automático. * Demuestra: do-while (menú), while (reintentos PIN), for (movimientos), * subprocesos (métodos), decisiones anidadas y validación. */ public class CajeroAutomatico { static double saldo = 2500.00; static String[] movimientos = new String[50]; static int numMovimientos = 0; static Scanner teclado = new Scanner(System.in); // ── SUBPROCESO: Verificar PIN ── static boolean verificarPin() { final String PIN_CORRECTO = "1234"; int intentos = 0; while (intentos < 3) { System.out.print("Introduce tu PIN: "); String pin = teclado.next(); if (pin.equals(PIN_CORRECTO)) { return true; } intentos++; System.out.println("PIN incorrecto. Intentos restantes: " + (3 - intentos)); } return false; // Tres intentos fallidos } // ── SUBPROCESO: Consultar saldo ── static void consultarSaldo() { System.out.printf("Tu saldo actual es: %.2f €%n", saldo); registrarMovimiento("Consulta de saldo"); } // ── SUBPROCESO: Retirar dinero ── static void retirarDinero() { double cantidad; do { System.out.print("Cantidad a retirar: "); cantidad = teclado.nextDouble(); if (cantidad <= 0) { System.out.println("La cantidad debe ser positiva."); } else if (cantidad > saldo) { System.out.println("Saldo insuficiente."); } else { saldo -= cantidad; System.out.printf("Retirados %.2f €. Nuevo saldo: %.2f €%n", cantidad, saldo); registrarMovimiento("Retirada: -" + cantidad + " €"); return; } } while (true); // Se sale con return cuando la operación es válida } // ── SUBPROCESO: Ver movimientos ── static void verMovimientos() { if (numMovimientos == 0) { System.out.println("No hay movimientos registrados."); return; } System.out.println("\n=== Últimos movimientos ==="); for (int i = 0; i < numMovimientos; i++) { System.out.println(" " + (i + 1) + ". " + movimientos[i]); } } // ── SUBPROCESO auxiliar: registrar movimiento ── static void registrarMovimiento(String descripcion) { if (numMovimientos < movimientos.length) { movimientos[numMovimientos] = descripcion; numMovimientos++; } } // ── ALGORITMO PRINCIPAL ── public static void main(String[] args) { System.out.println("╔══════════════════════════════╗"); System.out.println("║ CAJERO AUTOMÁTICO v1.0 ║"); System.out.println("╚══════════════════════════════╝"); // Paso 1: Verificar PIN (while con máximo 3 intentos) if (!verificarPin()) { System.out.println("Tarjeta bloqueada. Contacte con su banco."); return; } System.out.println("Acceso concedido.\n"); // Paso 2: Menú principal (do-while: al menos una vez) int opcion; do { System.out.println("\n── Menú ──────────────"); System.out.println("1. Consultar saldo"); System.out.println("2. Retirar dinero"); System.out.println("3. Ver movimientos"); System.out.println("0. Salir"); System.out.print("Opción: "); opcion = teclado.nextInt(); switch (opcion) { case 1: consultarSaldo(); break; case 2: retirarDinero(); break; case 3: verMovimientos(); break; case 0: System.out.println("Gracias por usar el cajero."); break; default: System.out.println("Opción no válida."); } } while (opcion != 0); teclado.close(); } }
📝 Ejercicios prácticos resueltos
Ejercicio 1: Media aritmética con centinela
Diseña un algoritmo (en pseudocódigo y Java) que lea números reales introducidos por el usuario y calcule su media aritmética. El usuario introduce -1 como centinela para indicar que ha terminado. Debe funcionar correctamente si el usuario introduce -1 como primer número (sin datos).
Ejercicio 2: Adivinar un número secreto
Escribe un programa que genere un número aleatorio entre 1 y 100 y pida al usuario que lo adivine. Tras cada intento, el programa indica si el número secreto es mayor o menor que el introducido. Al acertar, muestra cuántos intentos necesitó. Usa un bucle do-while.
Ejercicio 3: Validar contraseña con máximo de intentos
Escribe un programa que pida una contraseña al usuario. La contraseña correcta es "Java2026". El usuario tiene un máximo de 3 intentos. Si acierta, muestra "Acceso concedido"; si agota los 3 intentos, muestra "Acceso bloqueado". Combina while con una condición compuesta.
❓ Preguntas frecuentes sobre Diagramas de flujo: bucles, subprocesos y estructuras avanzadas
Las dudas más comunes respondidas de forma clara y directa.
💬 Foro de discusión
¿Tienes dudas sobre Diagramas de flujo: bucles, subprocesos y estructuras avanzadas? Comparte tu pregunta con la comunidad.
Todavía no hay mensajes. ¡Sé el primero en participar!