Salta ai contenuti

Lezione 6: Array Monodimensionali Statici e Algoritmi Base

Copertina Lezione 6

Nelle lezioni precedenti abbiamo imparato a gestire variabili scalari, cicli e strutture di controllo. Tuttavia, ogni valore elaborato veniva subito “dimenticato”: con il while di Lezione 4, per esempio, non era possibile tornare indietro a rileggere un dato già processato. Questa lezione introduce il costrutto che risolve il problema: l’array monodimensionale statico. Un array è una sequenza di variabili dello stesso tipo allocate in modo contiguo in memoria, accessibili tramite un indice numerico. Impareremo a dichiararlo, inizializzarlo e a scrivere i tre algoritmi fondamentali che si applicano a qualsiasi sequenza di dati: calcolo della media, ricerca lineare e individuazione di massimo e minimo.


Supponiamo di voler leggere i voti di 5 esami e calcolarne la media. Con le variabili scalari che conosciamo, saremmo costretti a scrivere:

int voto1, voto2, voto3, voto4, voto5;
scanf("%d", &voto1);
scanf("%d", &voto2);
// ... e così via per ogni voto

Questo approccio è insostenibile per 100 esami, e soprattutto è impossibile rielaborare i dati: una volta calcolata la media, non possiamo “tornare indietro” a scoprire, ad esempio, quali voti la superano.

L’array risolve entrambi i problemi: raggruppa N variabili dello stesso tipo in un’unica struttura indicizzata, e le mantiene tutte in memoria per tutto il tempo necessario.

La sintassi di dichiarazione è:

tipo nome_array[dimensione];

Esempi pratici:

int voti[5]; // 5 interi contigui in RAM (5 x 4 byte = 20 byte)
double misure[10]; // 10 double contigui in RAM (10 x 8 byte = 80 byte)
char lettere[26]; // 26 char contigui in RAM (26 x 1 byte = 26 byte)

Le celle di un array sono allocate in modo contiguo nello Stack — la zona di memoria temporanea riservata dal sistema operativo per le variabili locali della funzione corrente. Grazie alla contiguità, la CPU può calcolare l’indirizzo di qualsiasi elemento in tempo costante, senza dover scorrere la memoria.

Ogni cella ha un proprio indice che parte sempre da 0 e arriva a N-1:

Indice01234
Elementovoti[0]voti[1]voti[2]voti[3]voti[4]
Indirizzo (fittizio)10001004100810121016

Gli indirizzi dell’ultima riga sono fittizi, ma mostrano come vengono salvati i dati: ogni int occupa 4 byte, quindi le celle si trovano una dopo l’altra, a distanza di 4 byte l’una dall’altra.

:::note[Perché gli indici partono da 0?] L’indice è in realtà un offset (scostamento) rispetto all’indirizzo base dell’array. Il primo elemento si trova esattamente all’indirizzo base, quindi il suo scostamento è 0. Questo diventerà ancora più chiaro quando studieremo i puntatori. :::

Un array può essere inizializzato alla dichiarazione tramite una lista di valori tra parentesi graffe:

int voti[5] = {28, 30, 25, 27, 18}; // inizializzazione completa
int zeri[5] = {0}; // tutti gli elementi inizializzati a 0
int parziale[5] = {10, 20}; // voti[2], [3], [4] vengono posti automaticamente a 0

Quando rilevante, è buona pratica definire la dimensione dell’array come costante simbolica tramite #define, così da poterla modificare in un solo punto:

#define N 5 // cambiando questo numero, si aggiorna tutto il codice che usa N
int main(void) {
int voti[N];
// ...
}

L’accesso ai singoli elementi avviene tramite l’operatore di indicizzazione []:

voti[0] = 28; // scrittura: assegna 28 al primo elemento
printf("%d\n", voti[2]); // lettura: stampa il terzo elemento (indice 2)

1.4 La dimensione di un Array: L’operatore sizeof

Sezione intitolata “1.4 La dimensione di un Array: L’operatore sizeof”

L’operatore sizeof restituisce lo spazio occupato in memoria da un tipo di dato o da una variabile, espresso in byte. Quando viene applicato a un array statico, sizeof restituisce la dimensione totale in byte dell’intero array, non il numero di elementi.

Ad esempio, se abbiamo un array di 5 interi:

int voti[5];
printf("Spazio occupato: %zu byte\n", sizeof(voti)); // Stampa 20 (5 elementi * 4 byte ciascuno)

Per determinare in modo automatico il numero di elementi (la lunghezza dell’array) senza cablare la costante nel codice, si divide la dimensione totale dell’array per la dimensione di un singolo elemento (solitamente il primo elemento a indice 0):

int lunghezza = sizeof(voti) / sizeof(voti[0]);
// Equivale a: 20 byte / 4 byte = 5 elementi

Questa espressione viene calcolata a compile-time (durante la compilazione) ed è estremamente comoda per scrivere cicli generici in cui non vogliamo hardcodare la costante numerica:

for (int i = 0; i < (sizeof(voti) / sizeof(voti[0])); i++) {
// codice di scansione
}

Attenzione al ciclo di vita della dimensione

L’operatore sizeof restituisce la dimensione corretta dell’array solo all’interno dello stesso scope (blocco di codice) in cui l’array è stato dichiarato. Se l’array viene passato come parametro a una funzione, decade a un semplice puntatore (Array Decay) e sizeof restituirà la dimensione del puntatore (8 byte su sistemi a 64-bit), rendendo impossibile risalire alla lunghezza originaria in questo modo.


2.1 Il Ciclo for come Strumento Universale sugli Array

Sezione intitolata “2.1 Il Ciclo for come Strumento Universale sugli Array”

Quasi tutti gli algoritmi su array condividono lo stesso schema mentale: un ciclo for che scorre tutti gli indici da 0 a N-1.

for (int i = 0; i < N; i++) {
// opera su arr[i]
}

Questo pattern è così ricorrente che vale la pena memorizzarlo come un blocco atomico di pensiero. Vediamo come usarlo per leggere e stampare un array:

#include <stdio.h>
#define N 5
int main(void) {
int voti[N];
// Lettura dell'array
printf("Inserisci %d voti:\n", N);
for (int i = 0; i < N; i++) {
printf("Voto %d: ", i + 1); // i+1 perche l'utente conta da 1
scanf("%d", &voti[i]);
}
// Stampa dell'array
printf("\nVoti inseriti: ");
for (int i = 0; i < N; i++) {
printf("%d ", voti[i]);
}
printf("\n");
return 0;
}

Si noti che usiamo due cicli distinti: uno per la lettura, uno per la stampa. Con un array possiamo ripercorrere i dati tutte le volte che vogliamo — cosa impossibile con variabili scalari.

La media aritmetica si calcola accumulando la somma in un unico ciclo e dividendo una sola volta alla fine.

#include <stdio.h>
#define N 5
int main(void) {
int voti[N] = {28, 30, 25, 27, 18};
int somma = 0;
for (int i = 0; i < N; i++) {
somma += voti[i];
}
double media = (double)somma / N; // cast esplicito per la divisione reale!
printf("Media: %.2f\n", media);
return 0;
}

Il cast (double) è obbligatorio

Senza il cast esplicito, somma / N sarebbe una divisione intera che tronca il risultato decimale. Ad esempio, 128 / 5 darebbe 25 invece di 25.60. Il cast (double)somma converte il dividendo in virgola mobile prima della divisione.

2.3 La Prima Vera Dimostrazione del Valore degli Array: la Seconda Passata

Sezione intitolata “2.3 La Prima Vera Dimostrazione del Valore degli Array: la Seconda Passata”

Dopo aver calcolato la media, possiamo fare una seconda passata sull’array per scoprire quali voti la superano. Questa operazione sarebbe impossibile senza un array: con variabili scalari, ogni valore inserito dall’utente viene scartato dopo l’elaborazione e non può essere riletto.

// ... dopo aver calcolato 'media' con il ciclo precedente ...
printf("\nVoti superiori alla media (%.2f):\n", media);
for (int i = 0; i < N; i++) {
if (voti[i] > media) {
printf(" - voti[%d] = %d\n", i, voti[i]);
}
}

Il confronto voti[i] > media funziona correttamente: poiché media è un double, il compilatore promuove automaticamente voti[i] (intero) a double prima del confronto.


Sezione intitolata “3.1 Algoritmo: Ricerca Lineare (Sequential Search)”

La ricerca lineare è l’algoritmo più semplice per trovare un elemento in un array non ordinato: si esaminano le celle una per una dall’inizio, finché non si trova l’elemento cercato o si esaurisce l’array.

Esistono due varianti comuni:

Pattern A: Determinare SE l’elemento esiste (flag booleano)

Sezione intitolata “Pattern A: Determinare SE l’elemento esiste (flag booleano)”
#define N 5
int voti[N] = {28, 30, 25, 27, 18};
int target = 30;
int trovato = 0; // flag: 0 = non trovato, 1 = trovato
for (int i = 0; i < N; i++) {
if (voti[i] == target) {
trovato = 1;
break; // inutile continuare una volta trovato
}
}
if (trovato) {
printf("Valore %d trovato nell'array.\n", target);
} else {
printf("Valore %d non presente.\n", target);
}

Pattern B: Determinare DOVE si trova (indice sentinella)

Sezione intitolata “Pattern B: Determinare DOVE si trova (indice sentinella)”
int indice = -1; // -1 indica "non trovato" (nessun indice valido e' negativo)
for (int i = 0; i < N; i++) {
if (voti[i] == target) {
indice = i;
break;
}
}
if (indice != -1) {
printf("Valore %d trovato alla posizione %d.\n", target, indice);
} else {
printf("Valore %d non presente.\n", target);
}

L’algoritmo per trovare il massimo e il minimo di un array segue la stessa logica già vista in Lezione 4 per la sequenza fissa: si inizializzano le variabili di riferimento con il primo elemento dell’array (non con 0 o un valore arbitrario), poi si scorre il resto dell’array dal secondo elemento in poi.

#include <stdio.h>
#define N 5
int main(void) {
int voti[N] = {28, 30, 25, 27, 18};
int max = voti[0]; // inizializzazione corretta: primo elemento
int min = voti[0];
int pos_max = 0; // teniamo anche l'indice della posizione
int pos_min = 0;
for (int i = 1; i < N; i++) { // partiamo da 1, non da 0!
if (voti[i] > max) {
max = voti[i];
pos_max = i;
}
if (voti[i] < min) {
min = voti[i];
pos_min = i;
}
}
printf("Voto massimo: %d (posizione %d)\n", max, pos_max);
printf("Voto minimo: %d (posizione %d)\n", min, pos_min);
return 0;
}

3.3 Esempio Integrato: Analisi Statistica dei Voti

Sezione intitolata “3.3 Esempio Integrato: Analisi Statistica dei Voti”

Quest’ultimo esempio mette insieme tutti gli algoritmi visti: leggiamo N voti validati da tastiera, calcoliamo media, massimo e minimo, e contiamo i voti superiori alla media.

#include <stdio.h>
#define N 5
int main(void) {
int voti[N];
int somma = 0;
// Acquisizione con validazione do-while (ripasso Lezione 5)
printf("Inserisci %d voti (18-30):\n", N);
for (int i = 0; i < N; i++) {
do {
printf("Voto %d: ", i + 1);
scanf("%d", &voti[i]);
} while (voti[i] < 18 || voti[i] > 30);
somma += voti[i];
}
// Calcolo media
double media = (double)somma / N;
// Calcolo max, min e conteggio in un unico ciclo
int max = voti[0], min = voti[0];
int superano_media = 0;
for (int i = 0; i < N; i++) {
if (voti[i] > max) max = voti[i];
if (voti[i] < min) min = voti[i];
if (voti[i] > media) superano_media++;
}
// Report finale
printf("\n--- Analisi Voti ---\n");
printf("Media: %.2f\n", media);
printf("Massimo: %d\n", max);
printf("Minimo: %d\n", min);
printf("Sopra la media: %d/%d\n", superano_media, N);
return 0;
}

1. Qual è il primo indice valido di un array in C?

  • A) 1
  • B) -1
  • C) 0
  • D) Dipende dal tipo dell’array
Mostra Risposta Corretta

Risposta corretta: C

In C gli indici degli array partono sempre da 0. L’ultimo elemento valido di un array di N elementi si trova all’indice N-1.


2. Se dichiaro int arr[8];, quali sono gli indici validi?

  • A) Da 0 a 8
  • B) Da 1 a 8
  • C) Da 0 a 7
  • D) Da 1 a 7
Mostra Risposta Corretta

Risposta corretta: C

Un array di dimensione N ha indici validi da 0 a N-1. Per arr[8], gli indici validi sono da 0 a 7. Accedere ad arr[8] è un accesso fuori dai limiti (out-of-bounds).


3. Cosa produce il codice int a[3] = {0};?

  • A) Errore di compilazione: mancano tutti i valori.
  • B) Un array di 3 elementi, tutti inizializzati a 0.
  • C) Un array di 3 elementi, solo il primo a 0, gli altri con garbage value.
  • D) Un array di 1 elemento con il valore 0.
Mostra Risposta Corretta

Risposta corretta: B

In C, quando si fornisce un inizializzatore parziale, tutti gli elementi non specificati vengono inizializzati automaticamente a 0. {0} è un modo comune e corretto per azzerare un intero array.


4. Perché è necessario il cast (double)somma nell’espressione (double)somma / N?

  • A) Per aumentare la velocità di esecuzione.
  • B) Per evitare l’overflow del tipo int.
  • C) Per forzare una divisione in virgola mobile invece che una divisione intera che tronca il risultato.
  • D) Perché N è sempre un double.
Mostra Risposta Corretta

Risposta corretta: C

Senza il cast, somma / N sarebbe una divisione intera. Per esempio, 128 / 5 darebbe 25 invece di 25.6. Il cast (double)somma converte il dividendo in double prima della divisione, forzando un’operazione in virgola mobile.


5. Quale valore si usa convenzionalmente per inizializzare indice a “elemento non trovato” nella ricerca lineare?

  • A) 0
  • B) N (la dimensione dell’array)
  • C) -1
  • D) INT_MAX
Mostra Risposta Corretta

Risposta corretta: C

Il valore -1 è la convenzione universale per indicare “non trovato” negli algoritmi di ricerca in C. Poiché gli indici validi sono sempre >= 0, il valore -1 non può mai essere un indice reale e serve come sentinella inequivocabile.


6. Come si deve inizializzare la variabile max nell’algoritmo per trovare il massimo di un array?

  • A) A 0, per confrontare valori positivi.
  • B) Al valore più grande possibile (INT_MAX).
  • C) Al valore del primo elemento dell’array (arr[0]).
  • D) Non importa, qualsiasi valore va bene.
Mostra Risposta Corretta

Risposta corretta: C

L’inizializzazione corretta è sempre il primo elemento dell’array. Inizializzare a 0 sarebbe sbagliato se tutti gli elementi fossero negativi. L’unica strategia sempre corretta è usare il primo elemento come valore di partenza.


7. Nel ciclo for (int i = 1; i < N; i++) per trovare il massimo, perché si parte da i = 1?

  • A) Per evitare un accesso fuori dai limiti.
  • B) Perché arr[0] è già usato come valore iniziale di max: confrontarlo di nuovo sarebbe ridondante.
  • C) Perché il primo elemento non può mai essere il massimo.
  • D) Per una convenzione del linguaggio C.
Mostra Risposta Corretta

Risposta corretta: B

Poiché abbiamo già assegnato max = arr[0], il primo elemento ha già “concorso” come candidato. Iniziare il ciclo di confronto da i = 1 evita un confronto inutile dell’elemento con sé stesso.


8. Cosa accade se si accede a un indice fuori dai limiti in C (es. arr[N] su un array di N elementi)?

  • A) Il compilatore genera sempre un errore che blocca la compilazione.
  • B) Il programma si arresta immediatamente con un messaggio di errore chiaro.
  • C) Il comportamento è non definito (Undefined Behavior): il programma potrebbe leggere dati casuali, corrompere la memoria o crashare.
  • D) Il programma ritorna automaticamente all’ultimo elemento valido.
Mostra Risposta Corretta

Risposta corretta: C

L’accesso out-of-bounds è uno dei comportamenti non definiti più pericolosi del C. Il compilatore non garantisce alcun controllo a run-time sugli indici. Il programma potrebbe sembrare funzionare correttamente in alcuni casi e crashare in altri.


9. Qual è il vantaggio di usare #define N 5 rispetto a usare direttamente 5 nel codice?

  • A) Riduce il tempo di compilazione.
  • B) Permette di modificare la dimensione in un solo posto, aggiornando automaticamente tutto il codice che usa N.
  • C) Rende l’array allocato nello Heap invece che nello Stack.
  • D) Non ci sono vantaggi, è solo una convenzione stilistica.
Mostra Risposta Corretta

Risposta corretta: B

Usare una costante simbolica è il principio del “numero magico unico”: se la dimensione cambia, basta modificarla in un solo posto. Senza questa pratica, bisognerebbe trovare e modificare manualmente ogni occorrenza del numero 5, rischiando di dimenticarne qualcuna.


10. Quale affermazione sulla “seconda passata” su un array è corretta?

  • A) È impossibile scorrere un array due volte nello stesso programma.
  • B) Un array permette di elaborare gli stessi dati con più cicli sequenziali, cosa impossibile con variabili scalari.
  • C) La seconda passata è sempre più veloce della prima perché i dati sono in cache.
  • D) La seconda passata richiede che l’array sia ordinato.
Mostra Risposta Corretta

Risposta corretta: B

Questo è il vantaggio fondamentale degli array rispetto alle variabili scalari: i dati rimangono in memoria per tutta la durata del programma. Un esempio pratico è la stampa dei voti superiori alla media: possiamo prima calcolare la media, poi fare una seconda passata per confrontare ogni elemento con essa — operazione impossibile se avessimo letto i voti uno alla volta senza memorizzarli.


Scrivete un programma che legga N interi da tastiera (con #define N 6) e li stampi nell’ordine inverso rispetto a quello di inserimento.

Mostra Soluzione
#include <stdio.h>
#define N 6
int main(void) {
int arr[N];
printf("Inserisci %d numeri:\n", N);
for (int i = 0; i < N; i++) {
printf("Numero %d: ", i + 1);
scanf("%d", &arr[i]);
}
printf("Array al contrario: ");
for (int i = N - 1; i >= 0; i--) {
printf("%d ", arr[i]);
}
printf("\n");
return 0;
}

Per stampare l’array al contrario, il secondo ciclo for parte dall’ultimo indice valido (N - 1) e decrementa i fino a 0 incluso (i >= 0). Non è necessario creare un secondo array: basta percorrere il primo in senso inverso.


Scrivete un programma che legga N interi (con #define N 8) e stampi la loro somma e la loro media con 2 decimali.

Mostra Soluzione
#include <stdio.h>
#define N 8
int main(void) {
int arr[N];
int somma = 0;
printf("Inserisci %d numeri interi:\n", N);
for (int i = 0; i < N; i++) {
printf("Numero %d: ", i + 1);
scanf("%d", &arr[i]);
somma += arr[i];
}
double media = (double)somma / N;
printf("\nSomma: %d\n", somma);
printf("Media: %.2f\n", media);
return 0;
}

Accumulo la somma durante il ciclo di lettura per evitare un ciclo extra. La media richiede il cast (double) su somma per ottenere la divisione in virgola mobile.


Esercizio 3: Contare gli Elementi Maggiori di una Soglia

Sezione intitolata “Esercizio 3: Contare gli Elementi Maggiori di una Soglia”

Scrivete un programma che legga N temperature in gradi Celsius (con #define N 7) e conti quante superano 36.5. Usate un array di double.

Mostra Soluzione
#include <stdio.h>
#define N 7
int main(void) {
double temp[N];
int febbre = 0;
printf("Inserisci %d temperature:\n", N);
for (int i = 0; i < N; i++) {
printf("Temperatura %d: ", i + 1);
scanf("%lf", &temp[i]);
}
for (int i = 0; i < N; i++) {
if (temp[i] > 36.5) {
febbre++;
}
}
printf("\nTemperature sopra 36.5: %d su %d\n", febbre, N);
return 0;
}

Si noti l’uso di %lf in scanf per leggere i valori double. La seconda passata con il ciclo di conteggio dimostra il valore dell’array: elaboriamo i dati separatamente rispetto alla lettura.


Scrivete un programma che legga N interi (con #define N 6) e stampi il valore massimo e l’indice in cui si trova.

Mostra Soluzione
#include <stdio.h>
#define N 6
int main(void) {
int arr[N];
printf("Inserisci %d numeri:\n", N);
for (int i = 0; i < N; i++) {
printf("Numero %d: ", i + 1);
scanf("%d", &arr[i]);
}
int max = arr[0];
int pos_max = 0;
for (int i = 1; i < N; i++) {
if (arr[i] > max) {
max = arr[i];
pos_max = i;
}
}
printf("Massimo: %d (indice %d)\n", max, pos_max);
return 0;
}

max viene inizializzato al primo elemento (arr[0]) e pos_max a 0. Il ciclo parte da i = 1. Ogni volta che troviamo un elemento maggiore dell’attuale massimo, aggiorniamo sia il valore che la posizione.


Scrivete un programma che legga N interi (con #define N 5), chieda un valore da cercare e stampi l’indice della prima occorrenza, oppure un messaggio se non è presente.

Mostra Soluzione
#include <stdio.h>
#define N 5
int main(void) {
int arr[N];
printf("Inserisci %d numeri:\n", N);
for (int i = 0; i < N; i++) {
printf("Numero %d: ", i + 1);
scanf("%d", &arr[i]);
}
int target;
printf("Numero da cercare: ");
scanf("%d", &target);
int indice = -1;
for (int i = 0; i < N; i++) {
if (arr[i] == target) {
indice = i;
break;
}
}
if (indice != -1) {
printf("%d trovato all'indice %d.\n", target, indice);
} else {
printf("%d non presente nell'array.\n", target);
}
return 0;
}

La variabile indice viene inizializzata a -1 come sentinella. Il break interrompe la ricerca appena l’elemento viene trovato, evitando scansioni inutili.


Scrivete un programma che legga N interi (con #define N 7) e stampi sia il valore minimo che il massimo in un unico ciclo di scansione.

Mostra Soluzione
#include <stdio.h>
#define N 7
int main(void) {
int arr[N];
printf("Inserisci %d numeri:\n", N);
for (int i = 0; i < N; i++) {
printf("Numero %d: ", i + 1);
scanf("%d", &arr[i]);
}
int max = arr[0];
int min = arr[0];
for (int i = 1; i < N; i++) {
if (arr[i] > max) max = arr[i];
if (arr[i] < min) min = arr[i];
}
printf("Massimo: %d\n", max);
printf("Minimo: %d\n", min);
return 0;
}

Entrambe le variabili vengono inizializzate ad arr[0]. Nello stesso ciclo for, aggiorniamo massimo e minimo con due if indipendenti, evitando due passate separate.


Scrivete un programma che legga N voti interi (con #define N 6), calcoli la media e stampi gli indici e i valori dei voti che la superano.

Mostra Soluzione
#include <stdio.h>
#define N 6
int main(void) {
int voti[N];
int somma = 0;
printf("Inserisci %d voti:\n", N);
for (int i = 0; i < N; i++) {
printf("Voto %d: ", i + 1);
scanf("%d", &voti[i]);
somma += voti[i];
}
double media = (double)somma / N;
printf("Media: %.2f\n", media);
printf("\nVoti superiori alla media:\n");
int trovati = 0;
for (int i = 0; i < N; i++) {
if (voti[i] > media) {
printf(" - voti[%d] = %d\n", i, voti[i]);
trovati++;
}
}
if (trovati == 0) {
printf(" Nessun voto superiore alla media.\n");
}
return 0;
}

Questo esercizio esemplifica la “seconda passata”: prima calcoliamo la media, poi scorriamo nuovamente l’array per trovare gli elementi che la superano.


Esercizio 8: Array con Inizializzazione e Stampa Formattata

Sezione intitolata “Esercizio 8: Array con Inizializzazione e Stampa Formattata”

Dichiarate e inizializzate un array di 5 interi con i valori {12, 7, 25, 3, 18}. Stampate ogni elemento con il formato arr[i] = valore, poi stampate la somma totale.

Mostra Soluzione
#include <stdio.h>
#define N 5
int main(void) {
int arr[N] = {12, 7, 25, 3, 18};
int somma = 0;
printf("Contenuto dell'array:\n");
for (int i = 0; i < N; i++) {
printf("arr[%d] = %d\n", i, arr[i]);
somma += arr[i];
}
printf("\nSomma totale: %d\n", somma);
return 0;
}

L’array viene inizializzato alla dichiarazione. Un unico ciclo gestisce sia la stampa formattata che l’accumulo della somma.


Scrivete un programma che legga N interi (con #define N 8), chieda un valore target e stampi quante volte compare nell’array.

Mostra Soluzione
#include <stdio.h>
#define N 8
int main(void) {
int arr[N];
printf("Inserisci %d numeri:\n", N);
for (int i = 0; i < N; i++) {
printf("Numero %d: ", i + 1);
scanf("%d", &arr[i]);
}
int target;
printf("Valore da contare: ");
scanf("%d", &target);
int contatore = 0;
for (int i = 0; i < N; i++) {
if (arr[i] == target) {
contatore++;
}
}
printf("%d compare %d volta/e nell'array.\n", target, contatore);
return 0;
}

A differenza della ricerca con break, qui non usciamo dal ciclo appena troviamo il valore: dobbiamo contare tutte le occorrenze. Il ciclo scorre l’intero array senza interruzioni.


Esercizio 10: Analisi Completa di Temperature Giornaliere

Sezione intitolata “Esercizio 10: Analisi Completa di Temperature Giornaliere”

Scrivete un programma che simuli l’analisi di N temperature giornaliere (con #define N 7). Il programma deve:

  1. Leggere le 7 temperature (double tra -50.0 e 60.0, validate con do-while).
  2. Calcolare e stampare la temperatura media settimanale.
  3. Stampare il giorno con la temperatura massima e quello con la minima.
  4. Contare e stampare quanti giorni hanno avuto temperatura superiore alla media.
Mostra Soluzione
#include <stdio.h>
#define N 7
int main(void) {
double temp[N];
double somma = 0.0;
printf("Inserisci le temperature dei %d giorni:\n", N);
for (int i = 0; i < N; i++) {
do {
printf("Giorno %d (gradi C): ", i + 1);
scanf("%lf", &temp[i]);
} while (temp[i] < -50.0 || temp[i] > 60.0);
somma += temp[i];
}
double media = somma / N;
double max = temp[0], min = temp[0];
int pos_max = 0, pos_min = 0;
int sopra_media = 0;
for (int i = 0; i < N; i++) {
if (temp[i] > max) { max = temp[i]; pos_max = i; }
if (temp[i] < min) { min = temp[i]; pos_min = i; }
if (temp[i] > media) sopra_media++;
}
printf("\n--- Analisi Settimanale ---\n");
printf("Media: %.2f gradi C\n", media);
printf("Massima: %.2f gradi C (Giorno %d)\n", max, pos_max + 1);
printf("Minima: %.2f gradi C (Giorno %d)\n", min, pos_min + 1);
printf("Giorni sopra media: %d/%d\n", sopra_media, N);
return 0;
}

Questo esercizio integra tutti i pattern della lezione: acquisizione validata con do-while, media come divisione double, max/min con tracciamento della posizione, e conteggio degli elementi superiori alla media in un’unica passata. Si noti che pos_max + 1 viene usato nella stampa per convertire dall’indice base-0 al numero del giorno da 1 a 7, più naturale per l’utente.