2.02 · Selectivas Anidadas y `switch`
🎯 Objetivo de aprendizaje
Al terminar este tema vas a poder:
- Escribir cadenas de if-else if-else limpias y eficientes para decisiones con 3+ caminos.
- Construir menús interactivos profesionales que se repiten hasta que el usuario elige salir.
- Usar la estructura switch/case para decisiones con valores discretos (menús, días de la semana, etc.).
- Decidir cuándo usar if-else if-else vs switch/case según el problema.
- Aplicar la regla de oro: "una decisión, una indentación" para evitar la "pirámide del doom".
- Identificar y corregir el error de "case sin break" y la falta de default.
- Construir un sistema de menús modular con funciones y switch, base de cualquier programa interactivo.
Este tema te lleva de "tomo decisiones simples" a "construyo programas interactivos profesionales". El `switch` es una de las herramientas más usadas en interfaces de consola, formularios web, y menús de cualquier tipo.
🧠 Teoría y conceptos — 2.2.1 — La cadena if-else if-else: la forma elegante de múltiples caminos
El problema: 3 o más caminos
En el Tema 2.1 vimos cómo decidir entre 2 caminos con if-else. Pero en la vida real hay decisiones con muchos más caminos:
- Clasificar una nota en A, B, C, D, F (5 caminos).
- Determinar el día de la semana (7 caminos).
- Asignar un precio según el tipo de cliente (regular, premium, VIP, etc.).
- Decidir qué operación hacer en una calculadora (sumar, restar, multiplicar, dividir).
Con anidación tradicional de if-else esto se vuelve ilegible. La solución: `else if`, una sintaxis especial de C++ y Java que mantiene la indentación plana.
Sintaxis de else if
if (condición1) {
// bloque 1
} else if (condición2) {
// bloque 2
} else if (condición3) {
// bloque 3
} else {
// bloque "ninguno de los anteriores"
}
Cómo funciona:
- Se evalúa condición1. Si es verdadera, se ejecuta el bloque 1 y se sale.
- Si es falsa, se evalúa condición2. Si es verdadera, se ejecuta el bloque 2 y se sale.
- Y así sucesivamente.
- Si ninguna es verdadera, se ejecuta el bloque del else final (opcional pero recomendado).
Equivale a: anidar varios if-else pero con la indentación plana, mucho más legible.
Ejemplo: clasificar nota
Versión anidada (fea):
if (nota >= 9) {
cout << "A" << endl;
} else {
if (nota >= 8) {
cout << "B" << endl;
} else {
if (nota >= 7) {
cout << "C" << endl;
} else {
if (nota >= 6) {
cout << "D" << endl;
} else {
cout << "F" << endl;
}
}
}
}
Versión con `else if` (clara):
if (nota >= 9) {
cout << "A" << endl;
} else if (nota >= 8) {
cout << "B" << endl;
} else if (nota >= 7) {
cout << "C" << endl;
} else if (nota >= 6) {
cout << "D" << endl;
} else {
cout << "F" << endl;
}
Las dos hacen EXACTAMENTE LO MISMO, pero la segunda se lee en 5 segundos, la primera requiere concentración.
Regla de oro: orden de más específico a más general
// ✅ BIEN: de más específico a más general
if (nota >= 9) { // 9-10
cout << "A" << endl;
} else if (nota >= 8) { // 8-8.9
cout << "B" << endl;
} else if (nota >= 7) { // 7-7.9
cout << "C" << endl;
} else if (nota >= 6) { // 6-6.9
cout << "D" << endl;
} else { // 0-5.9
cout << "F" << endl;
}
// ❌ MAL: orden invertido
if (nota >= 0) { // Todas las notas positivas
cout << "F" << endl; // ¡Todas imprimen F!
} else if (nota >= 6) {
cout << "D" << endl;
} // ... esto no funciona
Por qué: la primera condición que sea verdadera se ejecuta y las siguientes NO. Si pones la más general primero, las específicas nunca se evalúan.
El else final es tu red de seguridad
// ✅ Con else final: todo caso queda cubierto
if (nota >= 9) {
cout << "A" << endl;
} else if (nota >= 8) {
cout << "B" << endl;
} // ... etc
else {
cout << "Nota fuera de rango" << endl; // Captura notas < 0 o > 10
}
convierte 3 algoritmos de cadenas de decisión anidadas (de los LAB 1.3, 1.4, 1.5) a la versión con `else if`. Mide la diferencia de líneas y legibilidad.
2.2.2 — El problema de la "pirámide del doom" y cómo evitarla
Qué es
La pirámide del doom (en inglés "arrow anti-pattern" o "deeply nested code") es cuando anidas tantos if que el código se va corriendo hacia la derecha:
if (condición1) {
if (condición2) {
if (condición3) {
if (condición4) {
if (condición5) {
// ... 4 espacios, 8, 12, 16, 20 ...
cout << "¡Por fin!" << endl;
}
}
}
}
}
Problemas:
- Es difícil de leer.
- Es difícil de mantener.
- Es difícil de debuggear (¿en qué nivel estoy?).
- Suele indicar que el código está mal diseñado.
4 técnicas para evitarla
- Usar `else if` en vez de anidar `if-else` (cuando los casos son excluyentes):
if (a) {
// ...
} else if (b) {
// ...
} else {
// ...
}
- Invertir la condición y hacer "early return" (salida temprana):
// ❌ Pirámide
void f() {
if (usuarioValido) {
if (tienePermisos) {
if (datosCorrectos) {
hacerAlgo();
}
}
}
}
// ✅ Sin pirámide
void f() {
if (!usuarioValido) return;
if (!tienePermisos) return;
if (!datosCorrectos) return;
hacerAlgo();
}
- Extraer a funciones:
// ❌ Pirámide
if (a) {
if (b) {
if (c) {
hacerX();
}
}
}
// ✅ Sin pirámide
if (a && b && c) {
hacerX();
}
- Usar la cláusula `default` en `switch` (lo veremos en 2.2.3): Para decisiones discretas con muchos casos, switch es más limpio que una cadena de if-else if.
La regla de los 3 niveles
Si tu código tiene más de 3 niveles de anidación de `if`, **es una señal de que hay que refactorizar**. Usa las 4 técnicas de arriba.
de tus programas del LAB 1.5 o 1.7, identifica alguno con más de 3 niveles de anidación. Refactorízalo usando una de las 4 técnicas. Mide la reducción de líneas y de niveles.
2.2.3 — La estructura switch/case: decisiones discretas
Qué es
La estructura switch/case es una forma especializada de decisión para cuando quieres comparar una variable contra múltiples valores discretos (enteros, caracteres, enumeraciones).
Aplica cuando:
- La variable es un entero, un carácter o una enumeración (no string, no double).
- Tienes 3 o más casos discretos a comparar.
- Cada caso es un valor específico, no un rango.
Sintaxis
switch (expresión) {
case valor1:
// instrucciones si expresión == valor1
break;
case valor2:
// instrucciones si expresión == valor2
break;
case valor3:
// instrucciones si expresión == valor3
break;
default:
// instrucciones si ningún caso coincide
break;
}
Cómo funciona:
- Se evalúa la expresión UNA SOLA VEZ.
- Se compara con cada case en orden.
- Cuando hay coincidencia, se ejecutan las instrucciones de ese case.
- El break hace que se salga del switch. Si no hay `break`, se sigue ejecutando el siguiente `case` (fall-through).
- Si ningún case coincide, se ejecuta default (si existe).
Ejemplo: día de la semana
#include <iostream>
using namespace std;
int main() {
int dia;
cout << "Ingresa un número del 1 al 7: ";
cin >> dia;
switch (dia) {
case 1:
cout << "Lunes" << endl;
break;
case 2:
cout << "Martes" << endl;
break;
case 3:
cout << "Miércoles" << endl;
break;
case 4:
cout << "Jueves" << endl;
break;
case 5:
cout << "Viernes" << endl;
break;
case 6:
cout << "Sábado" << endl;
break;
case 7:
cout << "Domingo" << endl;
break;
default:
cout << "Número inválido. Debe ser del 1 al 7." << endl;
break;
}
return 0;
}
Comparación con `if-else if`: la versión con switch es 50% más corta y más fácil de leer cuando hay muchos casos.
Ejemplo: menú de calculadora
#include <iostream>
using namespace std;
int main() {
int opcion;
double a, b;
cout << "=== Calculadora Simple ===" << endl;
cout << "1. Sumar" << endl;
cout << "2. Restar" << endl;
cout << "3. Multiplicar" << endl;
cout << "4. Dividir" << endl;
cout << "Opción: ";
cin >> opcion;
cout << "Número 1: ";
cin >> a;
cout << "Número 2: ";
cin >> b;
switch (opcion) {
case 1:
cout << "Resultado: " << a + b << endl;
break;
case 2:
cout << "Resultado: " << a - b << endl;
break;
case 3:
cout << "Resultado: " << a * b << endl;
break;
case 4:
if (b != 0) {
cout << "Resultado: " << a / b << endl;
} else {
cout << "Error: división entre 0" << endl;
}
break;
default:
cout << "Opción inválida" << endl;
break;
}
return 0;
}
Diagrama de flujo clásico del switch/case (menú calculadora)
┌─────────────┐
│ INICIO │ ⬭
└──────┬──────┘
│
▼
╱───────────────╲
╱ Mostrar menú ╲ ▱
╲ y leer opción ╱
╲───────────────╱
│
▼
◆─────────────◆ ◇ (decisión múltiple)
╱╱╱╱╱╱╱╲╲╲╲╲╲╲
┌──────────┴──┴──┴──┴──┴──────────┐
│ opción es... │
▼ ▼ ▼ ▼
╱─────────╲ ╱──────╲ ╱─────────╲ ╱─────────╲
╱ ESCRIBIR ╲║ ESCRIBIR ╲║ ESCRIBIR ╲║ ¿b!=0? ╲
╲ "Suma: ╱║ "Resta: ╱║ "Mult: ╱║ ──── ╲
╲ a+b" ╱ ║ a-b" ╱ ║ a*b" ╱ ║ │ ╲
╲────────╱ ╲─────────╱ ╲─────────╱ ║Sí │ ╲ No
│ │ │ │ │ │
│ │ │ ▼ │ ▼
│ │ │ ╱───────╲ ╱─────────╲
│ │ │║"Div: ╲║ "Opción ╲
│ │ │║ a/b" ╱║ inválida"╱
│ │ │ ╲────────╱ ╲─────────╱
│ │ │ │ │
└────────────┴─────┬──────┴──────┴──────────┘
│
▼
┌─────────────┐
│ FIN │ ⬭
└─────────────┘
Sobre el diagrama: el `switch/case` se representa con un rombo de decisión múltiple del que salen 4+ flechas (una por cada `case`). En draw.io, esto se dibuja como un rombo grande con varias salidas etiquetadas (1, 2, 3, 4, default). Es la forma estándar de representar decisiones discretas con varios casos.
convierte el menú de calculadora a `if-else if`. Compara líneas y claridad. ¿Cuál es mejor para este caso? ¿Por qué? Dibuja ambas versiones en tu cuaderno (con la simbología clásica).
2.2.4 — El default y el break: las claves del switch correcto
El break: la pieza que casi nadie entiende al principio
Sin break, el switch NO termina cuando encuentra un caso. Sigue ejecutando los siguientes casos (esto se llama fall-through).
int x = 1;
switch (x) {
case 1:
cout << "Caso 1" << endl;
// SIN break: sigue al siguiente caso
case 2:
cout << "Caso 2" << endl;
break; // Aquí sí termina
case 3:
cout << "Caso 3" << endl;
break;
}
Salida:
Caso 1
Caso 2
El `break` es necesario al final de CADA caso, excepto cuando intencionalmente quieres fall-through (raro).
El default: el caso "ninguno de los anteriores"
switch (opcion) {
case 1: /* ... */ break;
case 2: /* ... */ break;
// ...
default:
cout << "Opción inválida" << endl;
break;
}
`default` es opcional pero MUY recomendado. Sin él, si la opción no coincide con ningún case, el programa simplemente no hace nada (sin error, sin mensaje). Con default, capturas el caso no esperado y muestras un mensaje útil.
El error "case sin break"
El error más común de switch:
// ❌ MAL: olvidaste el break en case 1
switch (opcion) {
case 1:
cout << "Sumar" << endl;
// Falta break aquí
case 2:
cout << "Restar" << endl; // Se ejecuta también para opción 1
break;
// ...
}
Cómo evitarlo:
- Escribe el break INMEDIATAMENTE después de cada case, antes de las instrucciones.
- Usa la extensión de VS Code "C/C++" que resalta casos sin break.
- Compila con -Wall para que el compilador te avise: g++ -Wall main.cpp -o programa.
Cuándo SÍ quieres fall-through (raro pero existe)
A veces quieres que varios casos ejecuten el mismo código:
// Válido en C++: agrupar casos que ejecutan lo mismo
switch (dia) {
case 1: // lunes
case 2: // martes
case 3: // miércoles
case 4: // jueves
case 5: // viernes
cout << "Día laboral" << endl;
break;
case 6: // sábado
case 7: // domingo
cout << "Fin de semana" << endl;
break;
default:
cout << "Inválido" << endl;
break;
}
Esto es un patrón válido y útil. Los case sin break ni código ejecutan el mismo bloque que el siguiente.
el ejemplo de "día laboral vs fin de semana" usando `if-else` Y `switch`. ¿Cuál es más claro para este caso?
2.2.5 — switch vs if-else if: cuándo usar cada uno
La regla de decisión
¿La variable es un entero, carácter o enumeración?
├── NO → usa if-else if
└── SÍ
├── ¿Hay 3+ casos discretos?
│ ├── NO (1-2 casos) → if-else if es suficiente
│ └── SÍ → switch es más claro
└── ¿Cada caso es un valor específico (no un rango)?
├── NO (rangos: nota >= 7) → if-else if
└── SÍ (valores: 1, 2, 3, 4) → switch
Tabla comparativa
Ejemplos de cuándo usar cada uno
Usa `if-else if` cuando:
- La variable es double (no se puede usar en switch).
- La variable es string (en C++; Java sí permite String con Java 14+).
- Los casos son rangos: nota >= 7, edad < 18.
- Las comparaciones son complejas: edad >= 18 && tieneLicencia.
Usa `switch` cuando:
- La variable es int, char, o un enum.
- Los casos son valores específicos: 1, 2, 3, 4.
- Hay 3+ casos.
- Estás implementando un menú.
Ejemplo combinado
A veces necesitas ambos en el mismo programa:
// Menú con switch
switch (opcion) {
case 1:
// Login: usa if-else if para validar
if (usuario == "admin" && password == "12345") {
cout << "Acceso permitido" << endl;
} else if (intentos < 3) {
cout << "Contraseña incorrecta" << endl;
} else {
cout << "Cuenta bloqueada" << endl;
}
break;
case 2:
// Ver perfil: usa if-else para clasificar
if (edad < 18) {
cout << "Perfil de menor" << endl;
} else if (edad < 65) {
cout << "Perfil de adulto" << endl;
} else {
cout << "Perfil de adulto mayor" << endl;
}
break;
// ... más opciones
}
toma un programa tuyo del LAB 1.5 o 1.7 que tenga 4+ decisiones. Reescríbelo usando `switch` donde aplique y `if-else if` donde no. Mide la claridad.
2.2.6 — Menús interactivos profesionales con do-while + switch
El patrón fundamental de los programas interactivos
Casi cualquier programa de consola tiene este flujo:
- Mostrar menú de opciones
- Leer la opción del usuario
- Ejecutar la opción elegida
- Volver al paso 1
- Salir cuando el usuario elija "Salir"
Esto se implementa con un bucle do-while (que veremos en detalle en el Tema 2.5) que contiene un switch:
#include <iostream>
using namespace std;
int main() {
int opcion;
do {
// 1. Mostrar menú
cout << "\n=== Menú Principal ===" << endl;
cout << "1. Saludar" << endl;
cout << "2. Calcular suma" << endl;
cout << "3. Ver fecha" << endl;
cout << "4. Salir" << endl;
cout << "Opción: ";
cin >> opcion;
// 2. Procesar opción
switch (opcion) {
case 1:
cout << "¡Hola! ¿Cómo estás?" << endl;
break;
case 2: {
double a, b;
cout << "Número 1: ";
cin >> a;
cout << "Número 2: ";
cin >> b;
cout << "Suma: " << a + b << endl;
break;
}
case 3:
cout << "Hoy es un gran día para programar." << endl;
break;
case 4:
cout << "Saliendo..." << endl;
break;
default:
cout << "Opción inválida. Intente de nuevo." << endl;
break;
}
} while (opcion != 4);
cout << "Programa terminado." << endl;
return 0;
}
Cómo funciona:
- El do-while repite el bloque al menos una vez.
- Dentro, se muestra el menú, se lee la opción, y se procesa con switch.
- El bucle se repite mientras la opción NO sea 4 (Salir).
- Cuando el usuario elige 4, el bucle termina y se sale.
Los detalles que importan
- El menú debe ser claro:
- Títulos con bordes o separadores.
- Opciones numeradas.
- Una opción explícita de "Salir" (por convención, la última).
- La validación de la opción:
- Si el usuario escribe "5" cuando solo hay 1-4, el default lo captura.
- Si el usuario escribe letras, cin entra en estado de error. Necesitas limpiarlo:
if (cin.fail()) {
cin.clear(); // Limpia el estado de error
cin.ignore(10000, '\n'); // Ignora el resto de la línea
opcion = 0; // Fuerza al default
}
- La función para cada opción (limpio): En lugar de meter todo en el case, llama a una función:
switch (opcion) {
case 1:
saludar();
break;
case 2:
calcularSuma();
break;
case 3:
verFecha();
break;
case 4:
cout << "Saliendo..." << endl;
break;
default:
cout << "Opción inválida" << endl;
break;
}
Esto lo veremos en detalle en el Tema 2.9 (Funciones). Por ahora, está bien que el código esté dentro del case.
- Las llaves en `case 2:`:
case 2: {
double a, b; // Variables locales a este case
// ...
break;
}
Si declaras variables dentro de un case, necesitas llaves {} para crear un bloque. Si no, el compilador da error.
diseña 3 menús diferentes para 3 problemas (calculadora, agenda, sistema de calificaciones). Para cada uno, escribe el pseudocódigo y luego tradúcelo a C++ con `do-while + switch`.
⚠️ Errores típicos — ❌ Errores típicos del razonamiento
Error 1: "Si tengo muchos casos, mejor uso switch aunque sean rangos"
Idea equivocada: "Tengo que clasificar 5 rangos de notas, mejor uso switch."
Realidad: switch SOLO funciona con valores discretos. Para rangos (nota >= 7), necesitas if-else if. No se puede hacer `case nota >= 7:` en C++. La única excepción son los range patterns de Rust o C# 9+.
Cómo evitarlo: si los casos son rangos, usa if-else if. Si son valores discretos, usa switch.
Error 2: "Olvidé un break pero el programa funciona, no importa"
Idea equivocada: "Mi switch funciona aunque le falten breaks en algunos casos."
Realidad: "funciona" en un caso de prueba no significa que funcione en todos. Si cambias los casos o agregas más, el fall-through va a causar bugs difíciles de encontrar.
Cómo evitarlo: SIEMPRE pon break al final de cada case. Si intencionalmente quieres fall-through, pon un comentario // fall-through intencional.
Error 3: "No necesito default en el switch"
Idea equivocada: "Si cubrí todos los casos válidos, el default es redundante."
Realidad: los casos válidos son los que TÚ conoces. El usuario puede meter opciones no esperadas (por error, por malicia, por descuido). El default captura esos casos.
Cómo evitarlo: siempre incluye default en TODOS tus switch. Es 1 línea de código y te salva de bugs difíciles.
Error 4: "El menú se ve bien, pero los nombres de las opciones son feos"
Idea equivocada: "Poner '1. Opción 1' es suficiente."
Realidad: un buen menú tiene opciones descriptivas ("1. Registrar nuevo usuario", no "1. Opción 1"). El usuario no sabe qué hace cada opción solo por el número.
Cómo evitarlo: escribe opciones que digan QUÉ HACE cada una, no solo un número. Si es un sistema de biblioteca: "1. Buscar libro por título", no "1. Buscar".
Error 5: "Mi programa termina cuando el usuario elige 4, pero si escribe otra cosa sigue"
Idea equivocada: "El do-while con opcion != 4 es suficiente."
Realidad: ¿qué pasa si el usuario escribe "5" o "abc"? El default lo captura y muestra "opción inválida", pero el bucle sigue. Eso es correcto. El problema es cuando el cin entra en estado de error y el bucle se vuelve infinito.
Cómo evitarlo: valida SIEMPRE la entrada antes de procesarla. Si cin.fail(), limpia el buffer y vuelve a pedir.
🤖 IA como copiloto — 🤖 AI Mission 2.2 — Menús con IA
Regla de los 3 minutos (obligatoria): primero intenta por tu cuenta.
Prompts sugeridos
Prompt 1 — Diseñar un menú:
"Estoy construyendo un sistema de gestión de biblioteca en C++. Dame la estructura de un menú principal con 5 opciones: alta de libro, baja de libro, búsqueda, listado, salir. Dame el pseudocódigo del menú, NO el código en C++. Máximo 100 palabras."
Prompt 2 — Convertir if-else a switch:
"Te voy a pegar una cadena de if-else if en C++ que creo que se puede convertir a switch. NO me lo conviertas. Solo dime: (1) ¿se puede convertir? (2) ¿por qué sí o por qué no? (3) qué casos NO se podrían convertir. Máximo 100 palabras."
Prompt 3 — Encontrar error en switch:
"Te pego un switch en C++ que se comporta raro: '[código]'. NO me lo corrijas. Solo dime: (1) qué hace línea por línea, (2) dónde puede estar el problema. Máximo 150 palabras."
Prompt 4 — Comparar menús:
"Te voy a pegar 2 versiones de un menú en C++ que deberían hacer lo mismo. NO me digas cuál es mejor. Solo dime: (1) qué hace cada una, (2) qué ventajas y desventajas tiene cada una. Máximo 150 palabras."
🧪 Laboratorio — 🧪 LAB 2.2 — 6 ejercicios de decisiones complejas
Tiempo total: 1 h 30 min | Entregable: 6 programas funcionando.
🛠️ Herramienta recomendada para los diagramas de flujo de este LAB: Para los ejercicios que pidan un diagrama de flujo, usa [draw.io (diagrams.net)](https://app.diagrams.net/) — herramienta gratis, sin registro, que funciona en el navegador. Tiene plantillas con la simbología ANSI/ISO lista (en `General → Flowchart`). Exporta tus diagramas como PNG e insértalos en tu cuaderno digital o entrégalos junto con el código. Otras opciones libres: - [Mermaid](https://mermaid.live/) — diagramas desde código Markdown. Ideal para Git. - [Excalidraw](https://excalidraw.com/) — estilo "dibujado a mano", muy intuitivo. - Dibujar a mano en tu cuaderno — siempre válido, especialmente para trazar el razonamiento.
Ejercicio 1 — Clasificador de notas completo (básico, 15 min)
Enunciado. Crea un programa que pida una nota (0-10) y la clasifique:
- 9-10: A
- 8-8.9: B
- 7-7.9: C
- 6-6.9: D
- 0-5.9: F
- Cualquier otro: "Nota inválida"
Usa la cadena if-else if-else. Hazlo en los 3 lenguajes.
Criterio de éxito: los 6 casos (5 letras + inválido) funcionan.
Rúbrica (10 pts): 3 pts por versión + 1 pt por el caso inválido.
Ejercicio 2 — Calculadora con menú (básico, 20 min)
Enunciado. Construye una calculadora que tenga un menú con 5 opciones: sumar, restar, multiplicar, dividir, salir. Usa do-while + switch. Pide los 2 números solo si la opción es 1-4. Si elige división y el divisor es 0, muestra error.
Criterio de éxito: el menú se repite hasta elegir "Salir", y la división entre 0 se valida.
Rúbrica (10 pts): menú (3 pts) + 4 operaciones correctas (4 pts) + validación de división (2 pts) + salida limpia (1 pt).
Ejercicio 3 — Estación del año (intermedio, 20 min)
Enunciado. Crea un programa que pida un número de mes (1-12) y diga la estación del año (en el hemisferio norte, usando switch):
- 12, 1, 2: Invierno
- 3, 4, 5: Primavera
- 6, 7, 8: Verano
- 9, 10, 11: Otoño
- Otro: "Mes inválido"
Criterio de éxito: los 4 rangos de meses se asignan correctamente usando fall-through.
Rúbrica (10 pts): 4 estaciones correctas (8 pts) + caso inválido (2 pts).
Ejercicio 4 — Cajero automático (intermedio, 30 min)
Enunciado. Construye un cajero automático con menú: consultar saldo, depositar, retirar, salir. El saldo inicial es $5,000.
- Consultar: muestra el saldo.
- Depositar: pide monto (positivo), suma al saldo.
- Retirar: pide monto (positivo y menor o igual al saldo), resta al saldo. Si no hay suficiente, muestra error.
- Salir: termina.
Usa do-while + switch. Si el usuario elige una opción inválida, muestra "Opción inválida".
Criterio de éxito: el cajero maneja correctamente las 4 opciones, valida montos inválidos y saldo insuficiente.
Rúbrica (10 pts): menú (2 pts) + 4 opciones funcionales (4 pts) + validaciones (3 pts) + saldo final correcto (1 pt).
Ejercicio 5 — Sistema de calificaciones con switch (avanzado, 30 min)
Enunciado. Construye un sistema que pida 5 calificaciones y luego muestre un menú con opciones:
- Mostrar todas las calificaciones.
- Calcular y mostrar el promedio.
- Mostrar la calificación más alta y la más baja.
- Mostrar cuántos aprobados (>= 7) y reprobados (< 7).
- Salir.
Usa do-while + switch. Cada opción debe ser un bloque de código que use la información ya capturada.
Criterio de éxito: el sistema funciona como una mini-aplicación de consola.
Rúbrica (10 pts): menú (2 pts) + 4 opciones (6 pts) + datos consistentes (2 pts).
Ejercicio 6 — Mini sistema de ventas (avanzado, 30 min)
Enunciado. Construye un sistema de ventas con menú:
- Registrar producto (nombre, precio, stock).
- Vender producto (pide nombre, descuenta del stock, suma a ventas totales).
- Ver inventario (muestra todos los productos).
- Ver total de ventas.
- Salir.
Como aún no usamos arreglos, registra solo UN producto (variables simples). El sistema debe manejar el caso de que ya hay un producto registrado y no se puede registrar otro.
Criterio de éxito: el sistema maneja los 5 casos correctamente con validaciones.
Rúbrica (10 pts): estructura de datos (2 pts) + 4 opciones funcionales (4 pts) + validaciones (2 pts) + formato de salida (2 pts).
Ejercicio bonus — Conversor de unidades con menú (opcional, 30 min)
Enunciado. Construye un conversor de unidades con menú que tenga:
- Kilómetros a millas
- Celsius a Fahrenheit
- Kilogramos a libras
- Salir
Cada opción pide el dato y muestra la conversión. Usa do-while + switch + funciones (las funciones las verás en el Tema 2.9, pero intenta definirlas tú mismo por ahora).
Criterio de éxito: las 3 conversiones son correctas y el menú se repite.
Rúbrica bonus (5 pts): 3 conversiones correctas (3 pts) + menú (1 pt) + uso de funciones (1 pt).
🎯 Cierre del tema
Lo que aprendiste hoy:
- La cadena if-else if-else para decisiones con 3+ caminos.
- La "pirámide del doom" y 4 técnicas para evitarla.
- La estructura switch/case para valores discretos.
- El default y el break: las claves del switch correcto.
- Cuándo usar switch vs if-else if.
- El patrón do-while + switch para menús interactivos.
Lo que sigue: en el Tema 2.3 — Operadores Lógicos y Tablas de Verdad (6h), vas a profundizar en &&, || y !. Aunque ya los usaste en el Tema 2.1, aquí vas a dominar las tablas de verdad, las propiedades (conmutativa, asociativa, De Morgan), y vas a aprender a simplificar condiciones complejas para hacerlas más legibles.
Antes de seguir, asegúrate de tener en tu cuaderno:
- [ ] 6 programas del LAB 2.2 funcionando.
- [ ] Tabla comparativa de switch en C++/Java/Python.
- [ ] Pseudocódigo de 2 menús interactivos propios.
- [ ] Glosario con: if-else if-else, pirámide del doom, switch, case, break, default, fall-through, early return.
XP obtenida al completar este tema: 100 base + 30 por LAB (6 ejercicios) + 20 por Quest = 150 XP. Insignia desbloqueada al cerrar el capítulo: Branch Master (parcial).
*"Un menú con `switch` no es solo código: es la puerta de entrada a un programa interactivo. El usuario decide qué hacer, y tu código responde."* — De la introducción de este manual.
Fin del Tema 2.2
📝 Quest · Cuestionario — 📝 Quest — Reactivos para autoevaluación
Las siguientes preguntas te sirven para autoevaluarte después de leer el tema. Responde en tu cuaderno o mentalmente, y luego revisa las Respuestas modelo (disponibles en libre acceso, sin iniciar sesión).
Sección A · Opción múltiple
Elige la opción correcta (A, B, C o D). Las respuestas están en la sección Respuestas modelo.
-
¿Para qué sirve switch?
- Repetir
- Seleccionar entre múltiples caminos según un valor
- Definir función
- Compilar
-
¿Qué hace break en un switch?
- Termina el programa
- Sale del switch después de un case
- Salta al siguiente case
- No tiene efecto
-
¿Qué pasa si olvidas break en un case?
- Error
- Fall-through: ejecuta los cases siguientes
- Termina el switch
- El case se ignora
-
switch se puede usar con:
- Solo enteros
- En C++: enteros, char, enum; en JS/PHP también string
- Solo strings
- Solo floats
-
¿Cuál es la sintaxis correcta de switch?
- switch (x) { case 1: ... break; }
- switch x case 1: ...
- switch { x case 1 }
- switch (x) -> case 1
-
¿Cuándo es mejor if-else que switch?
- Siempre
- Para rangos o condiciones complejas
- Solo con strings
- Nunca
-
¿switch puede tener un case default?
- No
- Sí, es el caso por defecto si no hay match
- Solo en Java
- Solo en C++
-
¿Qué pasa si ningún case coincide y no hay default?
- Error
- No se ejecuta ningún bloque
- Se ejecuta el último case
- Se repite el switch
-
switch con float: ¿es válido en C++?
- Sí
- No (en C++ clásico)
- Solo en C++20
- Solo con double
-
¿Cuántos cases puede tener un switch?
- Máximo 10
- Sin límite práctico
- Máximo 255
- Solo 1
Sección B · Preguntas abiertas
Desarrolla tu respuesta en al menos 3 líneas. Compara con la respuesta modelo después de escribir.
-
¿Cuándo es preferible switch sobre if-else? Da un ejemplo donde switch es claramente mejor.→ Escribe tu respuesta aquí (en tu cuaderno o mentalmente)…
-
Explica qué es "fall-through" en switch y por qué a veces se usa intencionalmente.→ Escribe tu respuesta aquí (en tu cuaderno o mentalmente)…
-
Diseña un switch que imprima el número de días de un mes (considerando año no bisiesto).→ Escribe tu respuesta aquí (en tu cuaderno o mentalmente)…
🟢 Cuando termines, revisa las Respuestas modelo y compáralas con las tuyas. La mejor forma de aprender es discutir cada respuesta contigo mismo o con un compañero.