Sentències de repetició

Les sentències de repetició permeten repetir l'execució d'un bloc de codi més d'una vegada. Per a fer-ho, Java proporciona les sentències for, while i do-while.

Aprendràs:

A utilitzar la sentència for A utilitzar les sentències while i do-while

Sentència For

La sentència for proporciona una forma comptacta d'iterar (repetir) un bloc de codi. Habitualment se l'anomena bucle for.

El for té la següent sintaxi:

for (inicialitzacio; condicio; modificacio) { // bloc de codi }

Les parts del bucle són:

A dintre del bloc del bucle, el programa pot realitzar qualssevol sentències vàlides. Pot inclús tenir altres sentències de bucle.

El bucle for s'utilitza freqüentment per a iterar en un rang de valors. Anem a escriure un bucle-for per a imprimir números de 0 a 9 a la mateixa línia:

int n = 10; for (int i = 0; i < n; i++) { System.out.print(i + " "); } int n = 10; for (int i = 0; i < n; i++) { System.out.print(i + " "); } La primera vegada s'executa la inicialització int n = 10; for (int i = 0; i < n; i++) { System.out.print(i + " "); } n: 10 S'avalua la condició i < n, com 0 és menor que 10, es fa una iteració. int n = 10; for (int i = 0; i < n; i++) { System.out.print(i + " "); } n: 10 i: 0 int n = 10; for (int i = 0; i < n; i++) { System.out.print(i + " "); } n: 10 i: 0 Després de cada iteració es fa la modificació int n = 10; for (int i = 0; i < n; i++) { System.out.print(i + " "); } n: 10 i: 0 0␣ Es torna a avaluar la condició per veure si s'ha de fer una altra iteració. Com 1 < 10 no és false, es torna a iterar. int n = 10; for (int i = 0; i < n; i++) { System.out.print(i + " "); } n: 10 i: 1 0␣ int n = 10; for (int i = 0; i < n; i++) { System.out.print(i + " "); } n: 10 i: 1 0␣ Després de cada iteració es fa la modificacio int n = 10; for (int i = 0; i < n; i++) { System.out.print(i + " "); } n: 10 i: 1 0␣1␣ Es torna a comprovar la condició. Com i segueix sent menor que n, es fa una nova iteració int n = 10; for (int i = 0; i < n; i++) { System.out.print(i + " "); } n: 10 i: 2 0␣1␣ Es torna a comprovar la condició. Com i segueix sent menor que n, es fa una nova iteració int n = 10; for (int i = 0; i < n; i++) { System.out.print(i + " "); } n: 10 i: 2 0␣1␣ int n = 10; for (int i = 0; i < n; i++) { System.out.print(i + " "); } n: 10 i: 2 0␣1␣2␣ int n = 10; for (int i = 0; i < n; i++) { System.out.print(i + " "); } n: 10 i: 3 0␣1␣2␣ int n = 10; for (int i = 0; i < n; i++) { System.out.print(i + " "); } n: 10 i: 3 0␣1␣2␣ int n = 10; for (int i = 0; i < n; i++) { System.out.print(i + " "); } n: 10 i: 3 0␣1␣2␣3␣ int n = 10; for (int i = 0; i < n; i++) { System.out.print(i + " "); } n: 10 i: 4 0␣1␣2␣3␣ int n = 10; for (int i = 0; i < n; i++) { System.out.print(i + " "); } n: 10 i: 4 0␣1␣2␣3␣ int n = 10; for (int i = 0; i < n; i++) { System.out.print(i + " "); } n: 10 i: 4 0␣1␣2␣3␣4␣ int n = 10; for (int i = 0; i < n; i++) { System.out.print(i + " "); } n: 10 i: 5 0␣1␣2␣3␣4␣ int n = 10; for (int i = 0; i < n; i++) { System.out.print(i + " "); } n: 10 i: 5 0␣1␣2␣3␣4␣ int n = 10; for (int i = 0; i < n; i++) { System.out.print(i + " "); } n: 10 i: 5 0␣1␣2␣3␣4␣5␣ int n = 10; for (int i = 0; i < n; i++) { System.out.print(i + " "); } n: 10 i: 6 0␣1␣2␣3␣4␣5␣ int n = 10; for (int i = 0; i < n; i++) { System.out.print(i + " "); } n: 10 i: 6 0␣1␣2␣3␣4␣5␣ int n = 10; for (int i = 0; i < n; i++) { System.out.print(i + " "); } n: 10 i: 6 0␣1␣2␣3␣4␣5␣6␣ int n = 10; for (int i = 0; i < n; i++) { System.out.print(i + " "); } n: 10 i: 7 0␣1␣2␣3␣4␣5␣6␣ int n = 10; for (int i = 0; i < n; i++) { System.out.print(i + " "); } n: 10 i: 7 0␣1␣2␣3␣4␣5␣6␣ int n = 10; for (int i = 0; i < n; i++) { System.out.print(i + " "); } n: 10 i: 7 0␣1␣2␣3␣4␣5␣6␣7␣ int n = 10; for (int i = 0; i < n; i++) { System.out.print(i + " "); } n: 10 i: 8 0␣1␣2␣3␣4␣5␣6␣7␣ int n = 10; for (int i = 0; i < n; i++) { System.out.print(i + " "); } n: 10 i: 8 0␣1␣2␣3␣4␣5␣6␣7␣ int n = 10; for (int i = 0; i < n; i++) { System.out.print(i + " "); } n: 10 i: 8 0␣1␣2␣3␣4␣5␣6␣7␣8␣ int n = 10; for (int i = 0; i < n; i++) { System.out.print(i + " "); } n: 10 i: 9 0␣1␣2␣3␣4␣5␣6␣7␣8␣ int n = 10; for (int i = 0; i < n; i++) { System.out.print(i + " "); } n: 10 i: 9 0␣1␣2␣3␣4␣5␣6␣7␣8␣ int n = 10; for (int i = 0; i < n; i++) { System.out.print(i + " "); } n: 10 i: 9 0␣1␣2␣3␣4␣5␣6␣7␣8␣9␣ En aquest punt la condició s'avalua a false (10 no és menor que 10), així que ja no es fa cap més iteració. int n = 10; for (int i = 0; i < n; i++) { System.out.print(i + " "); } n: 10 i: 10 0␣1␣2␣3␣4␣5␣6␣7␣8␣9␣ En aquest punt la condició s'avalua a false (10 no és menor que 10), així que ja no es fa cap més iteració. int n = 10; for (int i = 0; i < n; i++) { System.out.print(i + " "); } // el programa continuaria per aqui ... n: 10 // la variable i s'esborra de la memoria 0␣1␣2␣3␣4␣5␣6␣7␣8␣9␣

Les variables declarades a la sentència d'inicialització només són visibles en l'àmbit (scope) del bucle -incloent totes les seves parts: condició, bloc i modificació-.

És una pràctica molt comuna entre els programadors anomenar les variables dels bucles amb i, j, k, ... S'especula que l'origen ve dels Quaternions de Hamilton.

Veiem un altre exemple. Calculem la suma dels números enters des de ini fins a fin.

Farem una execució del programa per a ini = 2 i fin = 5, aleshores la suma serà 2 + 3 + 4 + 5 = 14.

int ini = scanner.nextInt(); int fin = scanner.nextInt(); int sum = 0; for (int i = ini; i <= fin; i++) { sum += i; } System.out.println(sum); int ini = scanner.nextInt(); int fin = scanner.nextInt(); int sum = 0; for (int i = ini; i <= fin; i++) { sum += i; } System.out.println(sum); int ini = scanner.nextInt(); int fin = scanner.nextInt(); int sum = 0; for (int i = ini; i <= fin; i++) { sum += i; } System.out.println(sum); 2 int ini = scanner.nextInt(); int fin = scanner.nextInt(); int sum = 0; for (int i = ini; i <= fin; i++) { sum += i; } System.out.println(sum); ini: 2 2 int ini = scanner.nextInt(); int fin = scanner.nextInt(); int sum = 0; for (int i = ini; i <= fin; i++) { sum += i; } System.out.println(sum); ini: 2 2 5 int ini = scanner.nextInt(); int fin = scanner.nextInt(); int sum = 0; for (int i = ini; i <= fin; i++) { sum += i; } System.out.println(sum); ini: 2 fin: 5 2 5 int ini = scanner.nextInt(); int fin = scanner.nextInt(); int sum = 0; for (int i = ini; i <= fin; i++) { sum += i; } System.out.println(sum); ini: 2 fin: 5 sum: 0 2 5 2 és menor o igual a 5, es fa una iteració int ini = scanner.nextInt(); int fin = scanner.nextInt(); int sum = 0; for (int i = ini; i <= fin; i++) { sum += i; } System.out.println(sum); ini: 2 fin: 5 sum: 0 i: 2 2 5 int ini = scanner.nextInt(); int fin = scanner.nextInt(); int sum = 0; for (int i = ini; i <= fin; i++) { sum += i; } System.out.println(sum); ini: 2 fin: 5 sum: 0 i: 2 2 5 int ini = scanner.nextInt(); int fin = scanner.nextInt(); int sum = 0; for (int i = ini; i <= fin; i++) { sum += i; } System.out.println(sum); ini: 2 fin: 5 sum: 2 i: 2 2 5 3 és menor o igual a 5, es fa una iteració int ini = scanner.nextInt(); int fin = scanner.nextInt(); int sum = 0; for (int i = ini; i <= fin; i++) { sum += i; } System.out.println(sum); ini: 2 fin: 5 sum: 2 i: 3 2 5 int ini = scanner.nextInt(); int fin = scanner.nextInt(); int sum = 0; for (int i = ini; i <= fin; i++) { sum += i; } System.out.println(sum); ini: 2 fin: 5 sum: 2 i: 3 2 5 int ini = scanner.nextInt(); int fin = scanner.nextInt(); int sum = 0; for (int i = ini; i <= fin; i++) { sum += i; } System.out.println(sum); ini: 2 fin: 5 sum: 5 i: 3 2 5 4 és menor o igual a 5, es fa una iteració int ini = scanner.nextInt(); int fin = scanner.nextInt(); int sum = 0; for (int i = ini; i <= fin; i++) { sum += i; } System.out.println(sum); ini: 2 fin: 5 sum: 5 i: 4 2 5 int ini = scanner.nextInt(); int fin = scanner.nextInt(); int sum = 0; for (int i = ini; i <= fin; i++) { sum += i; } System.out.println(sum); ini: 2 fin: 5 sum: 5 i: 4 2 5 int ini = scanner.nextInt(); int fin = scanner.nextInt(); int sum = 0; for (int i = ini; i <= fin; i++) { sum += i; } System.out.println(sum); ini: 2 fin: 5 sum: 9 i: 4 2 5 5 és menor o igual a 5, es fa una iteració int ini = scanner.nextInt(); int fin = scanner.nextInt(); int sum = 0; for (int i = ini; i <= fin; i++) { sum += i; } System.out.println(sum); ini: 2 fin: 5 sum: 9 i: 5 2 5 int ini = scanner.nextInt(); int fin = scanner.nextInt(); int sum = 0; for (int i = ini; i <= fin; i++) { sum += i; } System.out.println(sum); ini: 2 fin: 5 sum: 9 i: 5 2 5 int ini = scanner.nextInt(); int fin = scanner.nextInt(); int sum = 0; for (int i = ini; i <= fin; i++) { sum += i; } System.out.println(sum); ini: 2 fin: 5 sum: 14 i: 5 2 5 6 no és menor o igual a 5, no es fan més iteracions int ini = scanner.nextInt(); int fin = scanner.nextInt(); int sum = 0; for (int i = ini; i <= fin; i++) { sum += i; } System.out.println(sum); ini: 2 fin: 5 sum: 14 i: 6 2 5 int ini = scanner.nextInt(); int fin = scanner.nextInt(); int sum = 0; for (int i = ini; i <= fin; i++) { sum += i; } System.out.println(sum); ini: 2 fin: 5 sum: 14 // i esborrada 2 5 int ini = scanner.nextInt(); int fin = scanner.nextInt(); int sum = 0; for (int i = ini; i <= fin; i++) { sum += i; } System.out.println(sum); ini: 2 fin: 5 sum: 14 2 5 14

Ometre parts

Les tres parts (inicialització, condició i modificació) són opcionals, es poden posar o no segons convingui.

Per exemple, el següent for no utilitza cap de les tres:

for (;;) { System.out.println("all work and no play makes jack a dull boy"); } all work and no play makes jack a dull boy all work and no play makes jack a dull boy all work and no play makes jack a dull boy all work and no play makes jack a dull boy ... ...

El bucle for itera el bloc de codi fins que la condició és false, com no hem posat cap condició, el bucle itera indefinidament.

Al següent exemple només s'especifica la condició, no la incialització ni la modificació. El for d'aquest exemple avalua si la paraula llegida amb l'scanner és igual a si. El bucle farà iteracions del bloc fins que la condició sigui false, és a dir, fins que es llegeixi un String distint de si.

Scanner scanner = new Scanner(System.in); for(; scanner.next().equals("yes"); ){ System.out.println("Tornem a repetir"); } yes Tornem a repetir yes Tornem a repetir yes Tornem a repetir prou!

Una altre petit exemple, el programa "Endevina el número":

System.out.println("Endevina el número secret:"); for(; scanner.nextInt() != 6;) { System.out.println("Segueix intentant-ho"); } System.out.println("L'has endevinat!"); System.out.println("Endevina el número secret:"); for(; scanner.nextInt() != 6;) { System.out.println("Segueix intentant-ho"); } System.out.println("L'has endevinat!"); System.out.println("Endevina el número secret:"); for(; scanner.nextInt() != 6;) { System.out.println("Segueix intentant-ho"); } System.out.println("L'has endevinat!"); Endevina el número secret: System.out.println("Endevina el número secret:"); for(; scanner.nextInt() != 6;) { System.out.println("Segueix intentant-ho"); } System.out.println("L'has endevinat!"); Endevina el número secret: 4 4 != 6 és true, es fa la iteració System.out.println("Endevina el número secret:"); for(; scanner.nextInt() != 6;) { System.out.println("Segueix intentant-ho"); } System.out.println("L'has endevinat!"); scanner.nextInt(): 4 Endevina el número secret: 4 System.out.println("Endevina el número secret:"); for(; scanner.nextInt() != 6;) { System.out.println("Segueix intentant-ho"); } System.out.println("L'has endevinat!"); Endevina el número secret: 4 System.out.println("Endevina el número secret:"); for(; scanner.nextInt() != 6;) { System.out.println("Segueix intentant-ho"); } System.out.println("L'has endevinat!"); Endevina el número secret: 4 Segueix intentant-ho System.out.println("Endevina el número secret:"); for(; scanner.nextInt() != 6;) { System.out.println("Segueix intentant-ho"); } System.out.println("L'has endevinat!"); Endevina el número secret: 4 Segueix intentant-ho 2 2 != 6 és true, es fa la iteració System.out.println("Endevina el número secret:"); for(; scanner.nextInt() != 6;) { System.out.println("Segueix intentant-ho"); } System.out.println("L'has endevinat!"); scanner.nextInt(): 2 Endevina el número secret: 4 Segueix intentant-ho 2 System.out.println("Endevina el número secret:"); for(; scanner.nextInt() != 6;) { System.out.println("Segueix intentant-ho"); } System.out.println("L'has endevinat!"); Endevina el número secret: 4 Segueix intentant-ho 2 System.out.println("Endevina el número secret:"); for(; scanner.nextInt() != 6;) { System.out.println("Segueix intentant-ho"); } System.out.println("L'has endevinat!"); Endevina el número secret: 4 Segueix intentant-ho 2 Segueix intentant-ho System.out.println("Endevina el número secret:"); for(; scanner.nextInt() != 6;) { System.out.println("Segueix intentant-ho"); } System.out.println("L'has endevinat!"); Endevina el número secret: 4 Segueix intentant-ho 2 Segueix intentant-ho 6 6 != 6 és false, ja no es fa cap iteració més System.out.println("Endevina el número secret:"); for(; scanner.nextInt() != 6;) { System.out.println("Segueix intentant-ho"); } System.out.println("L'has endevinat!"); scanner.nextInt(): 6 Endevina el número secret: 4 Segueix intentant-ho 2 Segueix intentant-ho 6 System.out.println("Endevina el número secret:"); for(; scanner.nextInt() != 6;) { System.out.println("Segueix intentant-ho"); } System.out.println("L'has endevinat!"); Endevina el número secret: 4 Segueix intentant-ho 2 Segueix intentant-ho 6 System.out.println("Endevina el número secret:"); for(; scanner.nextInt() != 6;) { System.out.println("Segueix intentant-ho"); } System.out.println("L'has endevinat!"); Endevina el número secret: 4 Segueix intentant-ho 2 Segueix intentant-ho 6 L'has endevinat

Bucles niats

És possible niar un bucle-for dintre d'un altre bucle-for. Ens pot servir per a processar estructures multidimensionals com taules (matrius), cubs, etc...

Com a exemple, el següent programa imprimeix la taula de mutliplicar del 1 fins al 9:

for (int i = 1; i < 10; i++) { for (int j = 1; j < 10; j++) { System.out.print(i * j + "\t"); } System.out.println(); } 1 2 3 4 5 6 7 8 9 2 4 6 8 10 12 14 16 18 3 6 9 12 15 18 21 24 27 4 8 12 16 20 24 28 32 36 5 10 15 20 25 30 35 40 45 6 12 18 24 30 36 42 48 54 7 14 21 28 35 42 49 56 63 8 16 24 32 40 48 56 64 72 9 18 27 36 45 54 63 72 81

Quan niem un bucle dintre d'un altre cal tenir en compte que el bucle intern es repetirà des del principi cada vegada que es faci una nova repetició de l'extern.

Per exemple, als següents dos bucles, l'extern es repeteix 2 vegades, per tant l'intern es repetirà des del principi cadascuna d'aquestes dues vegades. És a dir, el bucle intern es farà 3 vegades la primera repetetició de l'extern, i 3 vegades més a la segona repetició de l'extern.

for (int i = 0; i < 2; i++) { // ... for (int j = 0; j < 3; j++) { // ... } // ... }

El següent codi calcula la suma dels números en el rang ini a fin (inclusiu). El resultat es va emmagatzemant en la variable acumulador.

int accumulator = 0; for (int i = start; i <= end; i++) { accumulator += i; }

Quin dels següents codis calcula la multiplicació dels números en el rang?

int accumulator = 1; for (int i = start; i <= end; i++) { accumulator *= i; } int accumulator = 0; for (int i = 1; i <= end; i++) { accumulator *= i; } int accumulator = 1; for (int i = start; i <= end; i *= 1) { accumulator += i; } int accumulator = 1; for (int i = 1; i <= end; i++) { accumulator += i; }

Què imprimeix el següent codi?

int i = 0; for (int k = 0; k < 100; k++) { i++; } System.out.println(i);
101 100 0 99

Línia de punts
Interval
Repeat X
Divisibles per 3
FizzBuzz

while i do-while

Java proporciona les sentències while i do-while per a repetir un fragment de codi.

while

El bucle while consisteix en un bloc de codi i una condició (expressió booleana). El codi es repeteix fins que la condició és false. La seva sintaxi és:

while (condicio) { // bloc de codi }

El bloc de codi pot contenir qualssevol sentències Java incloent altres sentències condicionals o de repetició.

Veiem un petit exemple, que imprimeix una variable mentre sigui menor a 5:

int i = 0; while (i < 5) { System.out.print(i + " "); i++; } int i = 0; while (i < 5) { System.out.print(i + " "); i++; } 0 és menor que 5, es fa una iteració int i = 0; while (i < 5) { System.out.print(i + " "); i++; } i: 0 int i = 0; while (i < 5) { System.out.print(i + " "); i++; } i: 0 int i = 0; while (i < 5) { System.out.print(i + " "); i++; } i: 0 0 1 és menor que 5, es fa una iteració int i = 0; while (i < 5) { System.out.print(i + " "); i++; } i: 1 0 int i = 0; while (i < 5) { System.out.print(i + " "); i++; } i: 1 0 int i = 0; while (i < 5) { System.out.print(i + " "); i++; } i: 1 0 1 2 és menor que 5, es fa una iteració int i = 0; while (i < 5) { System.out.print(i + " "); i++; } i: 2 0 1 int i = 0; while (i < 5) { System.out.print(i + " "); i++; } i: 2 0 1 int i = 0; while (i < 5) { System.out.print(i + " "); i++; } i: 2 0 1 2 3 és menor que 5, es fa una iteració int i = 0; while (i < 5) { System.out.print(i + " "); i++; } i: 3 0 1 2 int i = 0; while (i < 5) { System.out.print(i + " "); i++; } i: 3 0 1 2 int i = 0; while (i < 5) { System.out.print(i + " "); i++; } i: 3 0 1 2 3 4 és menor que 5, es fa una iteració int i = 0; while (i < 5) { System.out.print(i + " "); i++; } i: 4 0 1 2 3 int i = 0; while (i < 5) { System.out.print(i + " "); i++; } i: 4 0 1 2 3 int i = 0; while (i < 5) { System.out.print(i + " "); i++; } i: 4 0 1 2 3 4 5 < 5 és false, ja no es fa cap iteració int i = 0; while (i < 5) { System.out.print(i + " "); i++; } i: 5 0 1 2 3 4

Hauràs notat que el bucle while és molt similar al for. De fet són equivalents, l'exemple anterior es podria haver escrit així:

int i = 0; for (; i < 5;) { System.out.print(i + " "); i++; }

O així:

int i = 0; for (; i < 5; i++) { System.out.print(i + " "); }

O inclús així:

for (int i = 0; i < 5; i++) { System.out.print(i + " "); }

És important notar que en aquest últim exemple, Java eliminarà la variable i un cop acabi el for, cosa que no passa en els exemples anteriors.

do-while

En el bucle do-while, el bloc de codi s'executa primer, i la condició s'avalua després. Si la condició és true el bloc es torna a executar. D'aquesta manera es garanteix que el bloc s'executarà al menys una vegada.

La seva sintaxi és:

do { // bloc de codi } while (condicio);

Un bon exemple és el següent programa, que llegeix dades de l'entrada stàndard fins que s'introdueix un cert valor.

int valor; do { valor = scanner.nextInt(); System.out.println(valor); } while (valor != 0); 3 5 7 0 11 int valor; do { valor = scanner.nextInt(); System.out.println(valor); } while (valor != 0); 3 5 7 0 11 La primera vegada s'executa el bloc sense avaluar la condició. int valor; do { valor = scanner.nextInt(); System.out.println(valor); } while (valor != 0); valor: 3 5 7 0 11 int valor; do { valor = scanner.nextInt(); System.out.println(valor); } while (valor != 0); valor: 3 3 5 7 0 11 S'avalua la condició per veure si es fa una altra iteració int valor; do { valor = scanner.nextInt(); System.out.println(valor); } while (valor != 0); valor: 3 3 5 7 0 11 3 int valor; do { valor = scanner.nextInt(); System.out.println(valor); } while (valor != 0); valor: 3 3 5 7 0 11 3 int valor; do { valor = scanner.nextInt(); System.out.println(valor); } while (valor != 0); valor: 5 3 5 7 0 11 3 S'avalua la condició per veure si es fa una altra iteració int valor; do { valor = scanner.nextInt(); System.out.println(valor); } while (valor != 0); valor: 5 3 5 7 0 11 3 5 int valor; do { valor = scanner.nextInt(); System.out.println(valor); } while (valor != 0); valor: 5 3 5 7 0 11 3 5 int valor; do { valor = scanner.nextInt(); System.out.println(valor); } while (valor != 0); valor: 7 3 5 7 0 11 3 5 S'avalua la condició per veure si es fa una altra iteració int valor; do { valor = scanner.nextInt(); System.out.println(valor); } while (valor != 0); valor: 7 3 5 7 0 11 3 5 7 int valor; do { valor = scanner.nextInt(); System.out.println(valor); } while (valor != 0); valor: 7 3 5 7 0 11 3 5 7 int valor; do { valor = scanner.nextInt(); System.out.println(valor); } while (valor != 0); valor: 0 3 5 7 0 11 3 5 7 S'avalua la condició per veure si es fa una altra iteració. Com 0 != 0 és false, no es torna a iterar. int valor; do { valor = scanner.nextInt(); System.out.println(valor); } while (valor != 0); valor: 0 3 5 7 0 11 3 5 7 0 int valor; do { valor = scanner.nextInt(); System.out.println(valor); } while (valor != 0); // el programa continua per aqui... valor: 0 3 5 7 0 11 3 5 7 0

En la pràctica, el bucle do-while se sol utilitzar menys que el while.