6  Estructures de selecció

Objectius

  • Entendre què és una estructura de selecció i per què un programa ha de “prendre decisions”.
  • Escriure condicions amb if, if-else i cadenes else if.
  • Construir condicions booleanes amb operadors relacionals i lògics.
  • Triar entre molts camins amb switch, tant en la forma clàssica com en la moderna (->).
  • Fer servir l’operador ternari per a decisions curtes.
  • Reconèixer i evitar els errors típics: confondre == amb = i oblidar el break al switch.

Fins ara els nostres programes s’executaven sempre igual, de dalt a baix. Però un programa útil ha de reaccionar: si la nota és un 5 o més, aprovat; si no, suspès. Si l’usuari escriu “sí”, continuem; si no, parem. Aquesta capacitat de triar un camí o un altre segons una condició és el que aporten les estructures de selecció, la base de tota la lògica que vindrà (i que combinarem amb els bucles).

6.1 Prendre decisions

Una estructura de selecció (o condicional) permet que un programa executi unes instruccions només si es compleix una condició.

La condició és sempre una expressió booleana: una pregunta amb resposta true (cert) o false (fals).

ConsellAnalogia: el semàfor

Quan arribes a un encreuament, no camines sempre igual: mires el semàfor. Si està verd, passes; si no, esperes. La teva acció depèn d’una condició.

Un programa amb if fa exactament això: comprova una condició i actua en conseqüència.

flowchart TD
    A([Inici]) --> B{"Condició<br/>certa?"}
    B -->|Sí| C["Instruccions<br/>del bloc"]
    B -->|No| D["Se salta el bloc"]
    C --> E([Continua])
    D --> E

6.2 Condicions booleanes

Abans de decidir, cal saber escriure la pregunta. Una condició es construeix amb:

  • Operadors relacionals: comparen dos valors.
  • Operadors lògics: combinen condicions.
Operador Significat Exemple Resultat
== igual a edat == 18 Cert si val 18
!= diferent de nota != 0 Cert si no és 0
>, < més gran / més petit preu > 100
>=, <= més gran o igual / més petit o igual nota >= 5
&& i (les dues certes) edat >= 18 && teCarnet
|| o (almenys una certa) esFestiu || esCapDeSetmana
! no (nega) !estaObert


Exemple mínim. Combinar condicions per decidir si algú pot conduir:

int edat = 20;
boolean teCarnet = true;

boolean potConduir = edat >= 18 && teCarnet;            // true només si totes dues
System.out.println("Pot conduir? " + potConduir);
AlertaError típic: confondre == amb =

No podem confondre els dos operadors:

  • Operador = assigna un valor
  • Operador == compara.
int x = 5;        // assignació: posa 5 dins de x
if (x == 5) { }   // comparació: x val 5?

En Java, escriure if (x = 5) dona error de compilació amb enters (perquè x = 5 no és un booleà), cosa que t’ajuda a detectar-ho.

Però amb booleans if (obert = true) sí que compila i és un error lògic silenciós: assigna true a obert en comptes de comparar. Escriu sempre == per comparar.

6.3 El if simple

La forma més bàsica: executa un bloc només si la condició és certa.

if (condició) {
    // instruccions que s'executen només si la condició és certa
}

Exemple: avisar si un dipòsit té poca benzina:

int litres = 3;
if (litres < 5) {
    System.out.println("Atenció: queda poc combustible!");
}
System.out.println("Fi de la comprovació.");

Si litres fos 10, el missatge d’atenció no apareixeria, però “Fi de la comprovació.” sempre s’escriu, perquè és fora del bloc.

AlertaError típic: el punt i coma fantasma

No posis mai punt i coma just després del if:

if (litres < 5);   // ⟵ aquest ; buida el if!
{
    System.out.println("Atenció!");   // s'executa SEMPRE
}

El ; tanca el if amb un cos buit, i el bloc de sota es converteix en codi normal que s’executa sempre. És un error molt difícil de veure.

6.4 El if-else

Quan volem fer una cosa si es compleix i una altra de diferent si no, afegim else.

if (condició) {
    // camí A: condició certa
} else {
    // camí B: condició falsa
}

Exemple: decidir aprovat o suspès:

int nota = 4;
if (nota >= 5) {
    System.out.println("Aprovat!");
} else {
    System.out.println("Suspès. A repassar.");
}

Exactament un dels dos blocs s’executa sempre: mai els dos, mai cap.

ConsellMini-repte

Demana un nombre enter amb Scanner i escriu si és parell o senar. Pista: un nombre és parell si n % 2 == 0.

6.5 Encadenament de else if

Sovint hi ha més de dos camins. Per triar entre diverses opcions excloents, encadenem else if.

Java comprova les condicions de dalt a baix i executa el primer bloc la condició del qual sigui certa; la resta les ignora.

int nota = 7;

if (nota < 5) {
    System.out.println("Suspès");
} else if (nota < 7) {
    System.out.println("Aprovat");
} else if (nota < 9) {
    System.out.println("Notable");
} else {
    System.out.println("Excel·lent");
}

Fixa’t que a la segona branca no cal escriure nota >= 5 && nota < 7: si hem arribat allà, és que la primera condició (nota < 5) ja era falsa, així que nota >= 5 es dona per descomptat.

AlertaError típic: ordre de les condicions

L’ordre importa. Si poses les condicions “a l’inrevés”, una de més general pot capturar casos que volies tractar a part:

if (nota >= 5) {
    System.out.println("Aprovat");
} else if (nota >= 9) {          // MAI s'hi arriba amb un 9!
    System.out.println("Excel·lent");   // un 9 ja ha entrat a "Aprovat"
}

Ordena de la condició més restrictiva a la més general, o revisa bé els llindars.

6.6 L’estructura switch

Quan comparem una mateixa variable amb molts valors concrets, una llarga cadena de else if es fa pesada.

El switch ho expressa de manera més neta. Hi ha dues formes:

  • La clàssica.
  • La moderna.

Estructura switch clàssica

La forma tradicional fa servir case, break i default:

int dia = 3;

switch (dia) {
    case 1:
        System.out.println("Dilluns");
        break;
    case 2:
        System.out.println("Dimarts");
        break;
    case 3:
        System.out.println("Dimecres");
        break;
    default:
        System.out.println("Un altre dia");
}
  • Cada case és un valor possible de la variable.
  • El break surt del switch un cop fet el bloc.
  • El default recull tots els casos no previstos (com un else final).
AlertaError típic: oblidar el break

Al switch clàssic, si t’oblides el break, l’execució continua caient cap als case següents (això s’anomena fall-through):

switch (dia) {
    case 1:
        System.out.println("Dilluns");
        // sense break!
    case 2:
        System.out.println("Dimarts");   // també s'escriu si dia == 1!
        break;
}

Amb dia == 1 s’escriuen Dilluns I Dimarts. Aquesta és la font d’errors número u del switch clàssic. La forma moderna l’elimina de soca-rel.

Estructura switch moderna

Des de Java 14, la fletxa -> fa el switch molt més segur i curt: no hi ha fall-through i, per tant, no calen break.

int dia = 3;

switch (dia) {
    case 1 -> System.out.println("Dilluns");
    case 2 -> System.out.println("Dimarts");
    case 3 -> System.out.println("Dimecres");
    default -> System.out.println("Un altre dia");
}

A més, el switch modern pot retornar un valor (aleshores s’anomena switch expression) i agrupar diversos valors amb comes:

String tipus = switch (dia) {
    case 6, 7 -> "Cap de setmana";
    default   -> "Dia laborable";
};
System.out.println(tipus);

Compara les dues formes:

Aspecte switch clàssic switch modern (->)
Sintaxi de cada cas case X:break; case X -> ...
Fall-through (cau al següent) Sí (font d’errors) No (segur)
Agrupar valors Repetint case case 1, 2, 3 ->
Pot retornar un valor No directament Sí (switch expression)
Recomanació Codi antic Preferible en codi nou
ConsellMini-repte

Escriu un switch modern que rebi un int mes (1–12) i retorni l’estació de l’any com a String. Agrupa els mesos amb comes (per exemple, case 12, 1, 2 -> "Hivern").

6.7 L’operador ternari

Per a decisions molt curtes que només trien entre dos valors, hi ha una drecera: l’operador ternari ? :.

Es llegeix “condició ? valor si cert : valor si fals”.

int nota = 6;
String resultat = (nota >= 5) ? "Aprovat" : "Suspès";
System.out.println(resultat);

És equivalent a un if-else que només assigna una variable, però en una sola línia. Compara:

// Amb if-else (4 línies)
String r;
if (nota >= 5) { r = "Aprovat"; } else { r = "Suspès"; }

// Amb ternari (1 línia)
String r = (nota >= 5) ? "Aprovat" : "Suspès";
AlertaError típic: abusar del ternari

El ternari és elegant per a casos senzills, però no l’aniuïs. Això és il·legible:

String x = a > b ? (a > c ? "a" : "c") : (b > c ? "b" : "c");   // difícil de llegir

Quan la decisió té més de dos camins o inclou instruccions (no només un valor), fes servir if-else o switch. La claredat és més important que estalviar línies.

6.8 Quina estructura triar

flowchart TD
    A{"Quantes<br/>opcions?"} -->|"1 (fer o no fer)"| B["if"]
    A -->|"2 camins"| C{"Només assignes<br/>un valor?"}
    C -->|Sí| D["operador ternari"]
    C -->|No| E["if-else"]
    A -->|"molts valors<br/>d'una variable"| F["switch (millor modern)"]
    A -->|"rangs o<br/>condicions complexes"| G["cadena else if"]

Cap regla és sagrada: totes es poden reescriure amb if-else. Tria la que faci el codi més clar de llegir.

6.9 Resum

  • Una estructura de selecció fa que el programa triï un camí segons una condició booleana.
  • if executa un bloc només si la condició és certa; if-else tria entre dos camins.
  • Les cadenes else if trien entre múltiples camins excloents; l’ordre de les condicions importa.
  • El switch compara una variable amb molts valors.
    • El clàssic necessita break (i oblidar-lo causa fall-through);
    • El modern amb -> és més curt i segur, i pot retornar un valor.
  • L’operador ternari ? : és una drecera per a decisions curtes que assignen un valor.
  • Els dos errors més freqüents: confondre == (comparar) amb = (assignar), i oblidar el break al switch clàssic.

6.10 Per practicar

  1. Classificador de notes. Demana una nota (0–10) i escriu la qualificació (Suspès, Aprovat, Notable, Excel·lent) amb una cadena else if.
  2. Calculadora simple. Demana dos nombres i una operació (+, -, *, /) i fes servir un switch modern per calcular i mostrar el resultat.
  3. Any de traspàs. Demana un any i digues si és de traspàs (divisible per 4, però no per 100 tret que ho sigui per 400). Practica els operadors lògics.
  4. Major de tres. Demana tres nombres i escriu el més gran. Fes-ho primer amb if-else i després intenta-ho amb ternaris.
  5. Preu amb descompte. Demana un import; si supera 100 €, aplica un 10 % de descompte amb l’operador ternari i mostra el preu final.
  6. Menú de restaurant. Amb un switch clàssic, mostra el preu d’un plat segons un codi numèric, i afegeix a propòsit un error de break oblidat per veure què passa.