Accesso agli elementi di un Array in C#

In questo articolo, mostriamo come gestire l’accesso agli elementi di un array in C# tramite l’utilizzo degli indici, così da poter eseguire lettura e scrittura dei dati in modo efficace.

Presentiamo anche esempi pratici per mettere in evidenza concetti fondamentali come l’uso della proprietà Length e la prevenzione dello sfondamento degli indici.

Accesso agli elementi di un Array

In C# l'accesso agli elementi di un array può essere effettuato in maniera diretta adoperando gli indici. Ciascun elemento, infatti, può essere acceduto usando il nome dell'array e l'indice corrispondente.

La sintassi è la seguente:

mioArray[indice]

L'accesso può essere sia in lettura che in scrittura, il che vuol dire che possiamo trattare gli elementi come variabili.

Ad esempio, per accedere ad un elemento in lettura, possiamo scrivere:

int[] numeri = { 1, 2, 3, 4, 5 };

Console.WriteLine(numeri[0]); // Output: 1

In questo caso l'elemento con indice 0 (primo elemento) verrà stampato a video.

Per accedere ad un elemento in scrittura, possiamo scrivere:

numeri[3] = 10;

In questo caso, l'elemento con indice 3 (quarto elemento) verrà sovrascritto con il valore 10.

Vediamo l'esempio che segue:

int[] mioArray = new int[5];
mioArray[0] = 10;
mioArray[2] = 20;

In questo esempio, abbiamo creato un array di 5 elementi che verranno inizializzati al valore di default (0). Successivamente abbiamo assegnato il valore 10 all'elemento con indice 0 e il valore 20 all'elemento con indice 2. La situazione in memoria sarà quella mostrata nella figura che segue:

L'array mioArray dopo aver scritto gli elementi con indice 0 e 2
Figura 1: L'array mioArray dopo aver scritto gli elementi con indice 0 e 2

Come si può vedere, a parte gli elementi in posizione 0 e 2 che abbiamo modificato in modo esplicito, gli altri elementi sono stati inizializzati al valore di default (0).

Dal momento che l'accesso agli elementi di un array avviene attraverso un indice numerico, possiamo adoperare, al posto di una costante, una variabile di tipo int in cui memorizzare l'indice desiderato.

int[] numeri = { 1, 2, 3, 4, 5 };
int indice = 2;

Console.WriteLine(numeri[indice]); // Output: 3

In questo caso, abbiamo usato una variabile indice per accedere all'elemento con indice 2 dell'array numeri.

Questa tecnica è molto utile quando si vuole accedere ad un elemento in base ad una condizione o ad un calcolo. Ma soprattutto, torna comoda quando vogliamo scorrere gli elementi di un array. Possiamo, infatti, adoperare un ciclo for, come mostra l'esempio che segue:

int[] numeri = { 1, 2, 3, 4, 5 };

for (int i = 0; i < numeri.Length; i++)
{
    Console.WriteLine(numeri[i]);
}

In questo caso, il ciclo for scorre tutti gli elementi dell'array numeri e li stampa a video. Vedremo nel dettaglio come usare i cicli e gli array nelle prossime lezioni.

Un dettaglio molto importante da notare nell'esempio di sopra è la proprietà Length di un array. Questa proprietà restituisce il numero di elementi presenti nell'array. In questo modo, possiamo adoperare la proprietà Length per scorrere tutti gli elementi dell'array senza dover conoscere a priori la sua dimensione.

Sfondamento degli indici

Una delle situazioni da evitare quando si lavora con gli array è il tentare di accedere ad un elemento usando un indice che non esiste. Questo errore, noto come sfondamento degli indici, può causare errori di runtime e comportamenti inaspettati.

Fortunatamente, la piattaforma .NET su cui si basa C# fornisce un meccanismo di sicurezza che controlla l'accesso agli elementi di un array. Se si tenta di accedere ad un elemento con un indice non valido, verrà generata un'eccezione di tipo IndexOutOfRangeException. Questo controllo automatico permette agli sviluppatori di individuare gli errori più facilmente e di scrivere codice più robusto.

Ovviamente, il controllo degli indici ha un suo costo in termini di tempo di esecuzione e, quindi, sulle performance del programma. Tuttavia si tratta di un piccolo prezzo da pagare per evitare errori di programmazione che possono essere molto difficili da individuare.

Vediamo un esempio:

int[] numeri = { 1, 2, 3, 4, 5 };
Console.WriteLine(numeri[5]);

In questo esempio abbiamo allocato un array di 5 elementi, ma proviamo a stampare a schermo l'elemento con indice 5. Questo indice non esiste, poiché l'array ha solo 5 elementi (con indici da 0 a 4).

Se proviamo ad eseguire il programma di sopra, otteniamo un output del genere:

Unhandled exception. System.IndexOutOfRangeException: Index was outside the bounds of the array.
   at Program.<Main>$(String[] args) in /home/user/Program.cs:line 2

Esempio: Inversione di un Array

Proviamo ad applicare le conoscenze acquisite finora, scrivendo un programma che prende un array e ne inverte l'ordine degli elementi.

// Array di Partenza
int[] startArray = { 1, 2, 3, 4, 5 };

// Otteniamo la lunghezza dell'array
int length = startArray.Length;

// Dichiariamo e creiamo l'array di destinazione
int[] endArray = new int[length];

// Invertiamo l'array
for (int i = 0; i < length; i++)
{
    endArray[i] = startArray[length - i - 1];
}

// Stampa l'array
for (int i = 0; i < length; i++)
{
    Console.Write(endArray[i] + " ");
}

Console.Write("\n");

Se proviamo a compilare ed eseguire il programma otteniamo il seguente output:

5 4 3 2 1

L'esempio funziona in questo modo:

  • Inizialmente allochiamo un array monodimensionale di tipo int e lo inizializziamo con 5 numeri da 1 a 5;
  • Successivamente, otteniamo la lunghezza dell'array di partenza e la memorizziamo in una variabile length. Per far questo abbiamo adoperato la proprietà Length dell'array;
  • Poi, dichiariamo l'array endArray che conterrà gli elementi dell'array di partenza ma in ordine inverso;
  • Per invertire gli elementi abbiamo usato un ciclo for che scorre tutti gli elementi dell'array di partenza e li copia nell'array di destinazione partendo dall'ultimo elemento.

Vediamo cosa accade nel ciclo for nel dettaglio.

Prima che il ciclo cominci, abbiamo che la variabile i vale 0. Quindi, l'elemento endArray[0] verrà inizializzato con l'elemento startArray[5 - 0 - 1], cioè startArray[4]. In questo modo, l'elemento endArray[0] conterrà il valore che rappresenta l'ultimo elemento dell'array di partenza.

Nel secondo ciclo, la variabile i vale 1. Quindi, l'elemento endArray[1] verrà inizializzato con l'elemento startArray[5 - 1 - 1], cioè startArray[3]. In questo modo, l'elemento endArray[1] conterrà il valore che rappresenta il penultimo elemento dell'array di partenza. E così via.

Lettura di un array da Console

Vediamo, ora, come possiamo leggere i valori di un array dalla console. Utilizzeremo, anche in questo caso, un ciclo for e le funzioni messe a disposizione dall'ambiente .NET per leggere da console.

Per prima cosa, leggiamo da console una riga di testo adoperando Console.ReadLine(). Poiché il risultato di questa operazione è una stringa, ossia una sequenza di caratteri, dobbiamo trasformarla in un numero intero che rappresenta la lunghezza dell'array. Per farlo possiamo usare il metodo int.Parse().

Fatto questo, possiamo, poi, dichiarare e creare un array di dimensione pari al valore letto da console.

// Leggiamo la dimensione dell'array da console
int n = int.Parse(Console.ReadLine())

// Dichiariamo e creiamo l'array
int[] numeri = new int[n];

Adesso, possiamo adoperare un ciclo for per iterare su tutti gli elementi dell'array e leggere da console i valori da assegnare. Ad ogni iterazione, impostiamo l'elemento corrente dell'array con il valore letto da console. Il ciclo esegue le proprie istruzioni n volte, dove n è la dimensione dell'array. Per cui, il ciclo itera su tutti gli elementi dell'array e legge un valore per ogni elemento dell'array.

for (int i = 0; i < n; i++)
{
    numeri[i] = int.Parse(Console.ReadLine());
}

Esempio: verifica se un array è simmetrico

Proviamo a scrivere un programma che verifica se un array sia simmetrico o meno.

Un array è simmetrico se il suo primo elemento è uguale all'ultimo, il secondo è uguale al penultimo e così via. Bisogna solo fare attenzione al caso in cui il numero di elementi dell'array sia pari o dispari.

Per comprendere meglio, guardiamo la figura che segue:

Esempio di Array simmetrico con un numero pari di elementi
Figura 2: Esempio di Array simmetrico con un numero pari di elementi

Come si può notare, l'array è simmetrico poiché il primo elemento è uguale all'ultimo (8), il secondo è uguale al penultimo (5) e così via.

Nella figura che segue, invece, abbiamo un array sempre simmetrico ma con un numero di elementi dispari:

Esempio di Array simmetrico con un numero dispari di elementi
Figura 3: Esempio di Array simmetrico con un numero dispari di elementi

Quando il numero di elementi è dispari non dobbiamo controllare l'elemento centrale, poiché è uguale a se stesso.

Vediamo il codice:

// Lettura del numero di elementi dell'array
Console.Write("Inserisci il numero di elementi dell'array: ");
int n = int.Parse(Console.ReadLine());

// Dichiariamo e creiamo l'array
int[] numeri = new int[n];

// Leggiamo i valori dell'array da console
Console.WriteLine("Inserisci i valori dell'array:");

for (int i = 0; i < n; i++)
{
    numeri[i] = int.Parse(Console.ReadLine());
}

// Verifica se l'array è simmetrico
bool simmetrico = true;
for (int i = 0; i < numeri.Length / 2; i++)
{
    if (numeri[i] != numeri[n - i - 1])
    {
        simmetrico = false;
        break;
    }
}

if (simmetrico)
{
    Console.WriteLine("L'array è simmetrico.");
}
else
{
    Console.WriteLine("L'array non è simmetrico.");
}

Provando a compilare ed eseguire il programma, possiamo inserire i valori dell'array e verificare se è simmetrico o meno. Ad esempio:

Inserisci il numero di elementi dell'array: 5
Inserisci i valori dell'array:
1
2
3
2
1
L'array è simmetrico.

In questo caso, l'array è simmetrico poiché il primo elemento è uguale all'ultimo, il secondo è uguale al penultimo e così via.

Inserisci il numero di elementi dell'array: 6
Inserisci i valori dell'array:
1
2
3
4
5
6
L'array non è simmetrico.

In questo caso, l'array non è simmetrico poiché il primo elemento è diverso dall'ultimo.

Il programma funziona in questo modo:

  1. Dapprima leggiamo il numero di elementi dell'array da console e creiamo l'array di conseguenza.
  2. Poi, leggiamo i valori dell'array da console e verifichiamo se l'array è simmetrico o meno. Per farlo, usiamo un ciclo for che scorre solo metà degli elementi dell'array.
  3. Ad ogni iterazione, controlliamo se l'elemento corrente è uguale all'elemento simmetrico rispetto alla metà dell'array. Se troviamo un elemento diverso, settiamo la variabile simmetrico a false e usciamo dal ciclo attraverso l'istruzione break.
  4. Infine, stampiamo a video il risultato.

Stampa di un array su Console

Spesso dobbiamo stampare gli elementi di un array sulla console, dopo aver terminato di utilizzarli.

Stampiamo gli elementi di un array sulla console in modo simile a come inizializziamo gli elementi, cioè usando un ciclo per scorrere l’array. Non ci sono regole rigide per la stampa, ma spesso si utilizza una formattazione adatta.

Un errore frequente è tentare di stampare un array come se fosse un numero:

string[] array = { "one", "two", "three", "four" };
Console.WriteLine(array);

Sfortunatamente, questo codice non stampa gli elementi dell’array, ma solo il suo tipo. Ecco cosa otteniamo dopo l’esecuzione di questo codice:

System.String[]
Press any key to continue . . .

Stampiamo invece gli elementi di un array manualmente, usando un ciclo for:

string[] array = { "one", "two", "three", "four" };

for (int index = 0; index < array.Length; index++)
{
    // Stampa ciascun elemento su una riga separata
    Console.WriteLine("Element[{0}] = {1}", index, array[index]);
}

Stiamo iterando sull’array usando il ciclo for, che verrà eseguito array.Length volte, e stampiamo l’elemento corrente usando Console.WriteLine() e una stringa formattata. Ecco il risultato:

Element[0] = one
Element[1] = two
Element[2] = three
Element[3] = four

In Sintesi

In questa lezione sull'accesso agli elementi di un array in C#, abbiamo visto che:

  • Utilizziamo gli indici per accedere agli elementi di un array in lettura e in scrittura.
  • Bisogna fare attenzione a evitare lo sfondamento degli indici, che si verifica quando cerchiamo di accedere a una posizione inesistente.
  • Sfruttiamo la proprietà Length per conoscere la dimensione dell’array e iterare i suoi elementi.
  • Gestiamo la lettura dei valori da console convertendoli nel formato desiderato, così da creare e popolare l’array dinamicamente.
  • Verifichiamo condizioni specifiche, ad esempio la simmetria di un array, confrontando gli elementi a coppie (primo con ultimo, secondo con penultimo, e così via).