%%{init: {"flowchart": {"nodeSpacing": 120}}}%%
%%| fig-align: center
%%{init: {"flowchart": {"nodeSpacing": 120}}}%%
%%| fig-align: center
flowchart TB
%% Orden invers: workaround del bug de Mermaid #7741 (els subgrafs
%% germans sense arestes es mostren a l'inrevés de la definició).
subgraph Repetició
direction TB
Q{Condició?} -->|Cert| AC[Acció]
AC --> Q
Q -->|Fals| FI[Continua]
end
subgraph Selecció
direction TB
C{Condició?} -->|Cert| A[Acció A]
C -->|Fals| B[Acció B]
end
classDef noBox fill:none,stroke:none;
class Selecció,Repetició noBox;
3 Estructures de control
Objectius
- Recordar que tot algorisme es pot construir amb tres tipus d’estructures.
- Dominar les estructures de selecció (prendre decisions).
- Dominar les estructures de repetició (bucles).
- Conèixer les estructures de salt i quan (no) usar-les.
- Introduir el control d’excepcions i les assercions.
3.1 Els tres pilars de tot algorisme
El teorema del programa estructurat ens diu que qualsevol algorisme, per complex que sigui, es pot escriure combinant només tres estructures:
- Seqüència: fer les coses una darrere l’altra.
- Selecció: triar entre camins segons una condició.
- Repetició: repetir accions mentre calgui.
A nivell visual, ho podem representar així:
Amb aquestes estructures i les variables, es pot programar qualsevol cosa.
3.2 Estructures de selecció
La selecció simple: SI
Executa unes instruccions només si una condició és certa.
SI edat >= 18 LLAVORS
ESCRIURE "Ets major d'edat"
FI_SI
flowchart TB
A[Inici] --> C{edat >= 18?}
C -->|Cert| B["ESCRIURE major d'edat"]
C -->|Fals| D[Continua]
B --> D
La selecció doble: SI ... SI_NO
Un camí si es compleix, un altre si no.
SI nota >= 5 LLAVORS
ESCRIURE "Aprovat"
SI_NO
ESCRIURE "Suspès"
FI_SI
flowchart TB
A[Inici] --> C{nota >= 5?}
C -->|Cert| B["ESCRIURE Aprovat"]
C -->|Fals| E["ESCRIURE Suspès"]
B --> D[Continua]
E --> D
Seleccions encadenades: SI_NO_SI
Per triar entre més de dues opcions.
SI nota >= 9 LLAVORS
ESCRIURE "Excel·lent"
SI_NO_SI nota >= 7 LLAVORS
ESCRIURE "Notable"
SI_NO_SI nota >= 5 LLAVORS
ESCRIURE "Aprovat"
SI_NO
ESCRIURE "Suspès"
FI_SI
flowchart TB
A[Inici] --> C1{nota >= 9?}
C1 -->|Cert| B["ESCRIURE Excel·lent"]
C1 -->|Fals| C2{nota >= 7?}
C2 -->|Cert| D["ESCRIURE Notable"]
C2 -->|Fals| C3{nota >= 5?}
C3 -->|Cert| E["ESCRIURE Aprovat"]
C3 -->|Fals| G["ESCRIURE Suspès"]
B --> FI[Continua]
D --> FI[Continua]
E --> FI[Continua]
G --> FI[Continua]
L’ordre de les condicions importa Les condicions es comproven de dalt a baix i s’atura a la primera certa. Si posessis nota >= 5 abans que nota >= 9, un 10 entraria per “Aprovat” i mai arribaria a “Excel·lent”. Ordena sempre de la condició més restrictiva a la més general.
La selecció múltiple: SEGONS
Quan comparem una variable amb valors concrets, és més net que un SI encadenat.
SEGONS diaSetmana FER
CAS 1: ESCRIURE "Dilluns"
CAS 2: ESCRIURE "Dimarts"
...
CAS 6, 7: ESCRIURE "Cap de setmana"
PER_DEFECTE: ESCRIURE "Dia no vàlid"
FI_SEGONS
flowchart TB
A[Inici] --> C{diaSetmana}
C -->|1| B["ESCRIURE Dilluns"]
C -->|2| D["ESCRIURE Dimarts"]
C -->|...| H["..."]
C -->|6, 7| E["ESCRIURE Cap de setmana"]
C -->|PER_DEFECTE| F["ESCRIURE Dia no vàlid"]
B --> FI[Continua]
D --> FI[Continua]
H --> FI[Continua]
E --> FI[Continua]
F --> FI[Continua]
En Java això serà el switch. Serveix per a valors discrets (números, caràcters, cadenes), no per a rangs (nota >= 5), on cal el SI.
3.3 Estructures de repetició (bucles)
Un bucle repeteix un bloc d’instruccions. Cada volta s’anomena iteració.
Hi ha tres formes bàsiques; totes són equivalents en potència, però cada una encaixa millor segons el cas.
MENTRE: repetir mentre es compleixi (0 o més cops)
Comprova la condició abans de cada iteració. Si de bon principi és falsa, no s’executa mai.
i ← 1
MENTRE i <= 5 FER
ESCRIURE i
i ← i + 1
FI_MENTRE
flowchart TB
A["i ← 1"] --> C{i <= 5?}
C -->|Cert| B["ESCRIURE i"]
B --> D["i <- i + 1"]
D --> C
C -->|Fals| E[Fi]
El malson del bucle infinit Si dins del MENTRE oblides modificar la variable de la condició (aquí, i <- i + 1), la condició mai es fa falsa i el programa no s’atura mai. És l’error més comú amb bucles. Regla d’or: en escriure un MENTRE, comprova immediatament què fa que acabi.
FES ... MENTRE: repetir almenys un cop
Comprova la condició al final, així que el cos s’executa com a mínim una vegada. Ideal per validar entrades (demanar fins que sigui correcte).
FES
ESCRIURE "Introdueix un número positiu:"
LLEGIR n
MENTRE n <= 0
PER A: quan saps quantes voltes
Quan coneixes el nombre d’iteracions per endavant. Gestiona el comptador sol.
PER A i DES DE 1 FINS A 10 FER
ESCRIURE i
FI_PER
Bucles aniuats
Un bucle dins d’un altre. Per exemple, per dibuixar una graella o recórrer una taula:
PER A fila DES DE 1 FINS A 3 FER
PER A columna DES DE 1 FINS A 4 FER
ESCRIURE "*"
FI_PER
SALT_DE_LÍNIA
FI_PER
Resultat:
****
****
****
PER A: sé exactament quantes voltes (recórrer 1..N, els elements d’una llista).MENTRE: repeteixo mentre una condició es compleixi, sense saber quants cops (llegir fins que arribi un0, per exemple).FES...MENTRE: com elMENTRE, però necessito almenys una execució (menús, validar dades).
3.4 Estructures de salt
Modifiquen el flux normal dels bucles:
TRENCAR(break): surt immediatament del bucle.CONTINUAR(continue): salta a la següent iteració, sense acabar l’actual.
Exemple de TRENCAR: esperem l’entrada de 10 valors numèrics. Si s’entra un 0 ha d’acabar l’execució del bucle.
C ← 0
PER A i DES DE 1 FINS A 10 FER
LLEGIR num
SI num = 0 LLAVORS
TRENCAR // 0 = final de les dades
FI_SI
C ← C + 1
FI_PER
ESCRIURE "Números llegits:", C
flowchart TB
A[Inici: C ← 0] --> LOOP{i <= 10?}
LOOP -->|Fals| FI["ESCRIURE C"]
LOOP -->|Cert| R["LLEGIR num"]
R --> Z{num = 0?}
Z -->|TRENCAR el bucle| FI
Z -->|Fals| INC[C ← C + 1]
INC --> LOOP
Exemple de CONTINUAR: esperem l’entrada de 5 notes. Els valors fora que no estiguin entre 1 i 10 no són vàlids: els ignorem i passem a la següent iteració del bucle.
C ← 0
PER A i DES DE 1 FINS A 5 FER
LLEGIR num
SI num < 1 O num > 10 LLAVORS
CONTINUAR // fora de rang, l'ignorem
FI_SI
C ← C + 1
FI_PER
ESCRIURE "Números vàlids:", C
flowchart TB
A[Inici: C ← 0] --> LOOP{i <= 5?}
LOOP -->|Fals| FI["ESCRIURE C"]
LOOP -->|Cert| R["LLEGIR num"]
R --> V{num < 1 o num > 10?}
V -->|CONTINUAR: propera iteració| LOOP
V -->|Fals| INC[C ← C + 1]
INC --> LOOP
TRENCARiCONTINUARsón útils, però abusar-ne fa el codi difícil de seguir.- Existeix també el
GOTO(saltar a qualsevol línia), però està prohibit de facto: genera “codi espagueti” impossible de mantenir. No el farem servir mai.
3.5 Control d’excepcions
Fins ara hem suposat que tot va bé. Però… i si l’usuari escriu “hola” quan demanem un número? I si intentem dividir per zero? Aquestes situacions anòmales s’anomenen excepcions.
Una excepció és un esdeveniment que interromp el flux normal perquè ha passat alguna cosa inesperada. En lloc de deixar que el programa “peti”, podem capturar-la i reaccionar-hi amb una estructura INTENTA ... CAPTURA:
INTENTA
resultat ← a / b
CAPTURA divisióPerZero
ESCRIURE "Error: no es pot dividir per zero"
FI_INTENTA
flowchart TB
A[INTENTA: codi que pot fallar] --> C{Hi ha error?}
C -->|No| OK[Continua normal]
C -->|Sí| H[CAPTURA: gestiona l'error]
H --> OK
Un programa professional no confia en què les dades siguin correctes. Preveu què pot anar malament i ho gestiona amb elegància.
3.6 Documentació
Un programa ben documentat s’entén sense haver de desxifrar-lo.
La documentació inclou:
- Comentaris al codi (el perquè).
- Noms clars de variables i funcions (documentació implícita).
- Documentació externa: manuals, README,…