/*==============================================================================
PARAMETRI IN INGRESSO
const int a[] l'array di interi da elaborare
non viene modificato durante le operazioni
int n la quantita' di elementi contenuti nell'array a
PARAMETRI IN USCITA
int *qDoppi la quantita' degli elementi contenuti nell'array allocato
in memoria dinamica del quale viene restituito il puntatore
come valore di ritorno
VALORE DI RITORNO
int * un puntatore a int che punta a uno spazio di memoria allocato
dinamicamente con malloc(), contenente l'array dei valori interi
doppi trovati nell'array puntato dal parametro a[]
in caso di errori nell'allocazione, restituisce NULL
==============================================================================*/
int *estrai_doppi( const int a[], int n, int *qDoppi ) {
// alloca lo spazio di memoria nel quale collocare i valori doppi
// eventualmente trovati (lo spazio allocato ha le stesse dimensioni
// dell'array in ingresso a[]
// se l'allocazione e' riuscita... (primo "if")
// alloca lo spazio di memoria nel quale colloca una copia dei dati
// contenuti nell'array in ingresso a[]
// se l'allocazione e' riuscita... (secondo "if")
// ordina la copia appena creata
// scorre l'array ordinato verificando quante volte si presenta ogni
// nuovo valore trovato in esso; il ciclo segue questa logica:
// Cominci con l'impostare a zero il contatore dei valori doppi
// trovati qDoppi (quello che segnalera' al chiamante quanti valori
// doppi sono stati trovati e sono contenuti nell'array restituito
// come valore di ritorno).
// Imposti a zero anche il contatore ausiliario, quello che conta la
// quantita' di ripetizioni per ciascun valore diverso trovato
// nell'array a[]. Questo contatore avra' sempre un valore pari alla
// quantita' degli elementi uguali MENO UNO. Inizialmente e' zero
// perche' ovviamente il primo valore e' sempre un valore "nuovo".
// Imposti un secondo contatore (il classico "i") su 1, non su 0
// perche' il confronto prende in considerazione un elemento e
// quello che lo precede, dunque inizi con gli elementi 1 e 0 di
// a[]. Con questo contatore scorri tutto l'array a[], fino
// all'elemento a[n-1].
// Ad ogni ripetizione del ciclo, se i due elementi presi in
// considerazione sono diversi, azzeri qr per indicare che hai
// appena trovato un nuovo valore (infatti hai inizializzato qr su 0
// fin dall'inizio, e il primo valore e' sempre "nuovo").
// Se invece i due elementi sono uguali serve una premessa: se qr e'
// zero, si e' trovato IL SECONDO di una serie di valori uguali; se
// qr NON e' zero, si e' trovato IL TERZO O PIU' di una serie di
// valori uguali. Dunque, se qr e' zero, copi DUE VALORI da a[] in
// coda a doppi[], ALTRIMENTI ne copi UNO SOLO. In entrambi i casi
// incrementi qr. Per copiare in coda a doppi[], usi come indice
// *qDoppi, incrementandolo di uno ad ogni valore copiato.
// fine secondo "if"
// libera la memoria allocata per la copia dei dati
// fine primo "if"
// restituisce il puntatore allo spazio di memoria che contiene gli elementi
// dell'array a[] il cui valore si ripete piu' di una volta; per come sono
// stati trovati quegli elementi, ovviamente il loro ordine potrebbe essere
// "scombinato" rispetto a quello nel quale comparivano in a[]
}
Il codice del ciclo è senz'altro più comprensibile e sintetico delle parole che servono per descriverlo (è 7 righe in tutto!), ma non mi è consentito fartelo vedere direttamente.