3.c.1 - Estructuras de Salto (switch-case)

Objetivo

Escribir y probar código que haga uso de estructuras de salto (switch-case).

1. Contenidos

1.1 Introducción a las estructuras de salto (switch-case)

La estructura switch-case (también llamada "selección múltiple" o "estructura de salto") permite que un programa salte a diferentes bloques de código según el valor exacto de una variable o expresión.

A diferencia de las estructuras de decisión (if-else-if) que evalúan condiciones complejas (mayor que, menor que, rangos, etc.), switch-case se utiliza cuando queremos comparar una variable con valores concretos y discretos.

¿Cuándo usar switch-case?

  • Cuando la variable puede tomar un conjunto limitado de valores conocidos (días de la semana, meses del año, códigos de error, opciones de menú, etc.).
  • Cuando queremos que el código sea más legible y organizado que una larga cadena de if-else-if.
  • Cuando el rendimiento puede ser importante (switch-case puede ser más eficiente que múltiples if-else).

Tipos de datos permitidos en switch: En Java, la expresión del switch puede ser de tipo: byte, short, int, char, String (desde Java 7), y enum. En este curso usaremos Integer y String.

1.2 Estructura switch-case (con break)

La forma básica de switch-case evalúa una expresión y, según el valor que tenga, salta al bloque case correspondiente. La instrucción break es fundamental porque sale del switch; sin ella, el programa continuaría ejecutando los siguientes casos (efecto "fall-through").

Sintaxis:

  • PSeInt: Segun variable Hacer ... valor1: ... valor2: ... FinSegun
  • Java: switch (variable) { case valor1: ... break; case valor2: ... break; }

Ejemplo en PSeInt: Días de la semana


Algoritmo EjemploSwitchBasico
    Definir dia Como Cadena
    dia <- "martes"
    
    Segun dia Hacer
        "lunes":
            Escribir "Inicio de semana"
        "martes":
            Escribir "Segundo día"
        "miercoles":
            Escribir "Mitad de semana"
        "jueves":
            Escribir "Casi viernes"
        "viernes":
            Escribir "Último día laboral"
        "sabado":
            Escribir "Fin de semana"
        "domingo":
            Escribir "Descanso"
    FinSegun
FinAlgoritmo
                

Diagrama de Flujo

Ejemplo en Java: Días de la semana (con break)


public class EjemploSwitchBasico {
    public static void main(String[] args) {
        String dia = "martes";
        
        switch (dia) {
            case "lunes":
                System.out.println("Inicio de semana");
                break;
            case "martes":
                System.out.println("Segundo día");
                break;
            case "miercoles":
                System.out.println("Mitad de semana");
                break;
            case "jueves":
                System.out.println("Casi viernes");
                break;
            case "viernes":
                System.out.println("Último día laboral");
                break;
            case "sabado":
                System.out.println("Fin de semana");
                break;
            case "domingo":
                System.out.println("Descanso");
                break;
        }
    }
}
                

¿Qué pasa si olvidas el break?


public class EjemploBreakOmitido {
    public static void main(String[] args) {
        Integer opcion = 2;
        
        switch (opcion) {
            case 1:
                System.out.println("Opción 1 seleccionada");
                // ¡No hay break!
            case 2:
                System.out.println("Opción 2 seleccionada");
                // ¡No hay break!
            case 3:
                System.out.println("Opción 3 seleccionada");
                break;
        }
    }
}
// Salida (cuando opcion = 2):
// Opción 2 seleccionada
// Opción 3 seleccionada
// El programa "cae" al caso 3 después de ejecutar el caso 2
                

¡Cuidado con el "fall-through"! En Java, cuando un case termina sin un break, la ejecución continúa con el siguiente case (incluyendo su código). A veces esto es útil (como veremos en el siguiente apartado), pero normalmente es un error.

1.3 Estructura switch-case-default

La estructura switch-case-default añade un bloque default (por defecto) que se ejecuta cuando ninguno de los valores de los casos coincide con la expresión evaluada. Es como el else en las estructuras if-else.

Sintaxis:

  • PSeInt: Segun variable Hacer ... valor1: ... valor2: ... De Otro Modo: ... FinSegun
  • Java: switch (variable) { case valor1: ... break; ... default: ... }

Ejemplo en PSeInt: Meses del año con mensaje por defecto


Algoritmo EjemploSwitchDefault
    Definir mes Como Entero
    mes <- 13
    
    Segun mes Hacer
        1:
            Escribir "Enero - 31 días"
        2:
            Escribir "Febrero - 28/29 días"
        3:
            Escribir "Marzo - 31 días"
        4:
            Escribir "Abril - 30 días"
        5:
            Escribir "Mayo - 31 días"
        6:
            Escribir "Junio - 30 días"
        7:
            Escribir "Julio - 31 días"
        8:
            Escribir "Agosto - 31 días"
        9:
            Escribir "Septiembre - 30 días"
        10:
            Escribir "Octubre - 31 días"
        11:
            Escribir "Noviembre - 30 días"
        12:
            Escribir "Diciembre - 31 días"
        De Otro Modo:
            Escribir "Mes inválido. Debe ser entre 1 y 12."
    FinSegun
FinAlgoritmo
                

Ejemplo en Java: Meses del año con default


public class EjemploSwitchDefault {
    public static void main(String[] args) {
        Integer mes = 13;
        String nombreMes;
        Integer dias;
        
        switch (mes) {
            case 1:
                nombreMes = "Enero";
                dias = 31;
                break;
            case 2:
                nombreMes = "Febrero";
                dias = 28;
                break;
            case 3:
                nombreMes = "Marzo";
                dias = 31;
                break;
            case 4:
                nombreMes = "Abril";
                dias = 30;
                break;
            case 5:
                nombreMes = "Mayo";
                dias = 31;
                break;
            case 6:
                nombreMes = "Junio";
                dias = 30;
                break;
            case 7:
                nombreMes = "Julio";
                dias = 31;
                break;
            case 8:
                nombreMes = "Agosto";
                dias = 31;
                break;
            case 9:
                nombreMes = "Septiembre";
                dias = 30;
                break;
            case 10:
                nombreMes = "Octubre";
                dias = 31;
                break;
            case 11:
                nombreMes = "Noviembre";
                dias = 30;
                break;
            case 12:
                nombreMes = "Diciembre";
                dias = 31;
                break;
            default:
                nombreMes = "inválido";
                dias = 0;
                System.out.println("Mes inválido. Debe ser entre 1 y 12.");
        }
        
        if (dias > 0) {
            System.out.println(nombreMes + " tiene " + dias + " días.");
        }
    }
}
                

Ejemplo con múltiples casos compartiendo el mismo código (fall-through intencional):


public class EjemploFallThrough {
    public static void main(String[] args) {
        String diaSemana = "sabado";
        String tipoDia;
        
        switch (diaSemana) {
            case "lunes":
            case "martes":
            case "miercoles":
            case "jueves":
            case "viernes":
                tipoDia = "Laborable";
                break;
            case "sabado":
            case "domingo":
                tipoDia = "Fin de semana";
                break;
            default:
                tipoDia = "Día no reconocido";
        }
        
        System.out.println(diaSemana + " es " + tipoDia);
    }
}
                

El default no es obligatorio, pero es altamente recomendable. Te protege contra valores inesperados y hace tu código más robusto. Siempre pregunta: "¿Qué pasa si la variable tiene un valor que no he considerado?"

1.4 Comparativa: switch vs if-else-if

Con switch-case


String opcion = "guardar";

switch (opcion) {
    case "nuevo":
        crearArchivo();
        break;
    case "abrir":
        abrirArchivo();
        break;
    case "guardar":
        guardarArchivo();
        break;
    case "salir":
        salirPrograma();
        break;
    default:
        mostrarError();
}
                        

Con if-else-if


String opcion = "guardar";

if (opcion.equals("nuevo")) {
    crearArchivo();
} else if (opcion.equals("abrir")) {
    abrirArchivo();
} else if (opcion.equals("guardar")) {
    guardarArchivo();
} else if (opcion.equals("salir")) {
    salirPrograma();
} else {
    mostrarError();
}
                        

Ventajas de switch-case:

  • Más legible cuando hay muchas opciones (3 o más).
  • Más fácil de mantener (añadir/quitar casos).
  • Puede ser más eficiente (la máquina virtual puede optimizarlo como una "tabla de saltos").

Desventajas:

  • Solo funciona con valores exactos (no con rangos como "mayor que").
  • Requiere no olvidar los break (aunque Java moderno tiene alternativas).

2. Ejercicios

2.1 Clasificador de notas por letra (Nivel básico)

Crea un programa en Java llamado ClasificadorNotas que, dada una calificación numérica fija en el código (entero entre 0 y 10), muestre la clasificación por letra utilizando una estructura switch-case.

Tabla de conversión:

  • 9 o 10 → "A (Sobresaliente)"
  • 7 o 8 → "B (Notable)"
  • 6 → "C (Bien)"
  • 5 → "D (Suficiente)"
  • 3 o 4 → "E (Insuficiente)"
  • 0, 1 o 2 → "F (Muy deficiente)"
  • Otro valor → "Nota no válida" (default)

Datos fijos para probar: Prueba con estos valores (puedes cambiarlos manualmente en el código):

  • nota = 8 → debe mostrar "B (Notable)"
  • nota = 5 → debe mostrar "D (Suficiente)"
  • nota = 2 → debe mostrar "F (Muy deficiente)"

Pista: Puedes usar el "fall-through" intencional para que varios valores compartan el mismo código. Por ejemplo: case 9: case 10:

2.2 Conversor de unidades con menú (Nivel intermedio)

Crea un programa en Java llamado ConversorUnidades que simule un conversor de unidades. El programa debe tener una variable opcion (entero fijo en el código) y una variable valor (real fijo) para convertir.

Menú de opciones:

  • 1. Convertir kilómetros a millas (1 km = 0.621371 millas)
  • 2. Convertir millas a kilómetros (1 milla = 1.60934 km)
  • 3. Convertir Celsius a Fahrenheit (°F = °C × 9/5 + 32)
  • 4. Convertir Fahrenheit a Celsius (°C = (°F - 32) × 5/9)
  • 5. Convertir kilogramos a libras (1 kg = 2.20462 libras)
  • 6. Convertir libras a kilogramos (1 libra = 0.453592 kg)

Datos fijos para probar:

  • Prueba 1: opcion = 1, valor = 10.0 → "10.00 km son 6.21 millas"
  • Prueba 2: opcion = 3, valor = 25.0 → "25.00 °C son 77.00 °F"
  • Prueba 3: opcion = 7 (opción inválida) → "Opción no válida"

Pista: Usa System.out.printf("%.2f", resultado) para mostrar los resultados con dos decimales.

Reto: Generador de horóscopo chino

El Horóscopo Chino asigna un animal a cada año según un ciclo de 12 años. Los animales y sus años correspondientes (en el ciclo) son:

Año % 12AnimalCaracterísticas
0MonoInteligente, creativo, juguetón
1GalloObservador, valiente, trabajador
2PerroLeal, honesto, protector
3CerdoGeneroso, noble, tranquilo
4RataAstuto, adaptable, ambicioso
5BueyFuerte, confiable, paciente
6TigreValiente, competitivo, impulsivo
7ConejoElegante, amable, cuidadoso
8DragónEnérgico, apasionado, carismático
9SerpienteSabio, misterioso, intuitivo
10CaballoLibre, enérgico, aventurero
11CabraArtístico, sensible, tranquilo

Desarrolla un programa en Java llamado HoroscopoChino que:

  1. Tenga una variable anio (entero fijo en el código, por ejemplo 1999, 2008, 2024).
  2. Calcule el resto de dividir el año entre 12 (Integer resto = anio % 12).
  3. Utilice una estructura switch-case con el resto para determinar el animal del horóscopo chino.
  4. Muestre un mensaje como: "Naciste en el año [año]. Tu animal es el [animal]. Características: [características]"
  5. Incluya un caso default que maneje restos no esperados (aunque teóricamente un resto de división entre 12 siempre está entre 0 y 11, es buena práctica tenerlo).

Requisitos adicionales:

Curiosidad: El horóscopo chino no solo asigna animales por años, sino que también combina con los cinco elementos (madera, fuego, tierra, metal, agua) creando un ciclo de 60 años. ¡Investígalo si te interesa!

3. Bibliografía