CodeGym /Corsi /JAVA 25 SELF /Cicli annidati e il loro utilizzo

Cicli annidati e il loro utilizzo

JAVA 25 SELF
Livello 4, Lezione 5
Disponibile

1. Introduzione

Cominciamo con una domanda: perché mai annidare un ciclo dentro un altro? Spesso i dati o i problemi non sono organizzati su un’unica linea, ma, ad esempio, in una tabella, in una griglia o persino in una struttura multidimensionale. Mettiamo che vogliate stampare a schermo la tabellina, attraversare un array bidimensionale oppure calcolare le intersezioni tra tutte le coppie di elementi. In questi casi un solo ciclo non basta — serve un ciclo nel ciclo.

Nella programmazione un ciclo annidato è come due sveglie: quella esterna inizia a suonare e al suo interno se ne avvia un’altra che suonerà ogni volta finché la prima è attiva. Così, mentre si svolge una «iterazione esterna», quella interna percorre tutto il suo ciclo (e lo fa di nuovo per ogni iterazione dell’esterna).

Un buon esempio sono ore e minuti. Le ore sono il ciclo esterno da 0 a 23, i minuti sono il ciclo interno da 0 a 59. A ogni avanzamento del ciclo esterno, quello interno fa in tempo a scorrere tutti i suoi valori.

2. Sintassi dei cicli annidati

In Java la sintassi dei cicli annidati non differisce da quella dei cicli normali — basta scrivere un ciclo all’interno del corpo di un altro. Vediamo alcuni esempi con for e while:

// Ciclo esterno for
for (int i = 0; i < 3; i++)
{
    for (int j = 0; j < 4; j++)  // Ciclo interno for
    {
        System.out.print(i + "," + j + " ");
    }
    System.out.println(); // A capo dopo il ciclo interno
}

Qui il ciclo esterno controlla la variabile i (da 0 a 2), mentre quello interno la variabile j (da 0 a 3). Per ogni valore di i il ciclo interno percorre completamente da j == 0 a j == 3. Se eseguite questo codice, vedrete una piccola tabella di coordinate:

0,0 0,1 0,2 0,3 
1,0 1,1 1,2 1,3 
2,0 2,1 2,2 2,3 

Un esempio analogo con l’utilizzo di while:

int i = 0;
while (i < 3)
{
    int j = 0;
    while (j < 4)
    {
        System.out.print(i + "," + j + " ");
        j++;
    }
    System.out.println();
    i++;
}

Attenzione: a ogni iterazione del ciclo esterno la variabile del ciclo interno (j) deve essere reinizializzata; altrimenti vedremo solo una riga!

3. Esempi di utilizzo dei cicli annidati

Esempio 1: stampa di una scacchiera (8x8)

Come primo esercizio, stampiamo a schermo una scacchiera classica in celle nere e bianche (supponiamo che ‘#’ sia nera e ‘.’ bianca). Realizziamolo con cicli annidati for:

for (int row = 0; row < 8; row++)
{
    for (int col = 0; col < 8; col++)
    {
        // Se la somma di indice di riga e di colonna è pari, la cella è bianca, altrimenti è nera
        if ((row + col) % 2 == 0)
            System.out.print("_");
        else
            System.out.print("#");
    }
    System.out.println(); // Dopo ogni riga, vai a capo
}

Risultato:

_#_#_#_#
#_#_#_#_
_#_#_#_#
#_#_#_#_
_#_#_#_#
#_#_#_#_
_#_#_#_#
#_#_#_#_

Punto importante: l’annidamento fa sì che per ogni riga (row) si percorrono completamente tutte le colonne (col). Senza annidamento non otterremmo la struttura della scacchiera — solo una riga o una colonna.

Esempio 2: tabellina

Uno dei classici casi d’uso dei cicli annidati! Stampiamo la tabellina da 1–9:

for (int i = 1; i <= 9; i++)
{
    for (int j = 1; j <= 9; j++)
    {
        System.out.print(i * j + "\t");
    }
    System.out.println();
}

La formattazione i * j + "\t" aggiunge tabulazioni, così la tabella appare allineata.

Risultato:

  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 
...
  9  18  27  36  45  54  63  72  81 

4. Cicli annidati e loro controllo — particolarità

Sull’effetto di break e continue nei cicli annidati

Qui cascano in molti, soprattutto all’inizio! Se usate break o continue nel ciclo interno, essi influiscono solo su quel ciclo. Quello esterno continua a funzionare come se nulla fosse.

Esempio: uscita anticipata solo dal ciclo interno

for (int i = 0; i < 3; i++)
{
    for (int j = 0; j < 5; j++)
    {
        if (j == 3)
            break; // usciamo solo dal ciclo interno!
        System.out.print(i + "," + j + " ");
    }
    System.out.println();
}

Risultato:

0,0 0,1 0,2 
1,0 1,1 1,2 
2,0 2,1 2,2 

Se avete bisogno di uscire immediatamente da entrambi i cicli annidati (per esempio per terminare la ricerca al primo riscontro positivo in una tabella), di solito si usa un flag o una tecnica specifica (per esempio return, se tutto avviene all’interno di una funzione).

5. Visualizzazione dei cicli annidati

A volte è difficile «vedere» la sequenza di esecuzione dei cicli annidati. Diamo un’occhiata al seguente diagramma di flusso:

nested-loops-scheme

In forma tabellare — quante iterazioni in totale ci saranno con i da 1 a 3, j da 1 a 4?

i j (iterato per ogni i) Iterazioni del ciclo interno
1 1, 2, 3, 4 4
2 1, 2, 3, 4 4
3 1, 2, 3, 4 4
Totale: 3 × 4 = 12

6. Errori e insidie nell’uso dei cicli annidati

Un errore comune è inizializzare in modo scorretto la variabile del ciclo interno. Per esempio, dichiararla fuori dal ciclo esterno ma non azzerarla a ogni passo. Di conseguenza il ciclo interno può non eseguirsi affatto oppure comportarsi in modo errato.

int j = 0;
for (int i = 0; i < 3; i++)
{
    while (j < 4) // Ops! j potrebbe già essere pari a 4 dopo la prima iterazione.
    {
        System.out.print(i + "," + j + " ");
        j++;
    }
    System.out.println();
}

Qui il ciclo verrà eseguito una sola volta. Ricordate di inizializzare le variabili dei cicli interni all’interno dei cicli esterni!

Inoltre, se per errore scrivete due cicli annidati con le stesse variabili (for (int i = 0; ...) { for (int i = 0; ...) { ... } }), il compilatore si lamenterà: la variabile è già definita.

1
Compito
JAVA 25 SELF, livello 4, lezione 5
Bloccato
Griglia di coordinate sul radar 🗺️
Griglia di coordinate sul radar 🗺️
1
Compito
JAVA 25 SELF, livello 4, lezione 5
Bloccato
Rettangolo di asteroidi ⭐
Rettangolo di asteroidi ⭐
1
Compito
JAVA 25 SELF, livello 4, lezione 5
Bloccato
Creazione del campo di gioco 🎲
Creazione del campo di gioco 🎲
1
Compito
JAVA 25 SELF, livello 4, lezione 5
Bloccato
Selezione della password ideale 🔒
Selezione della password ideale 🔒
1
Sondaggio/quiz
Cicli, livello 4, lezione 5
Non disponibile
Cicli
Cicli while, for, do-while
Commenti
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION