#include <stdio.h>
#include <string.h>
/*==============================================================================
Riceve tramite il parametro array un puntatore ad un array di puntatori di tipo
qualsiasi che contiente la quantita' di elementi indicata dal parametro qEl.
Compatta tutti i puntatori non NULL in testa all'array, spostando in coda tutti
i puntatori NULL.
Occorre fare molta attenzione al dato da passare alla funzione tramite il
parametro array, assicurandosi che sia effettivamente un array di puntatori come
ad esempio...
void esempio( void ) {
int i, numeri[10];
int *array[10];
size_t non_nulli;
for( i=0; i<10; ++i ) {
numeri[i] = i+1;
array[i] = &numeri[i];
}
// annulla alcuni puntatori
array[0] = NULL;
array[2] = NULL;
array[4] = NULL;
array[5] = NULL;
array[9] = NULL;
non_nulli = compatta_array_di_puntatori( array, 10 );
}
In caso di successo restituisce la quantita' dei puntatori non NULL presenti
nell'array. In caso di insuccesso restituisce (size_t)-1. L'unica causa di
insuccesso segnalata e' il passaggio di un parametro array nullo.
==============================================================================*/
size_t compatta_array_di_puntatori( void *array, size_t qEl ) {
if( array ) {
char **po = (char**) array; /* per scorrere l'array originale */
char **pm = (char**) array; /* per scorrere l'array modificato */
size_t i, l = 0; /* l: per la lunghezza dell'array risultante */
for( i=0; i<qEl; ++i ) { /* per tutti i puntatori dell'array */
if( *po!=NULL ) { /* se il puntatore corrente non e' NULL */
++l; /* copia, quindi l'array modificato si "allunga" */
*pm++ = *po; /* copia il puntatore corrente */
*po++ = NULL; /* annulla l'originale del puntatore spostato */
} else po++; /* avanza di una posizione, senza copiare */
}
return l; /* restituisce la lunghezza dell'array modificato */
} else return (size_t) -1; /* restituire il valore massimo per size_t */
}
/*==============================================================================
QUEL CHE SEGUE E' SOLO UN PROGRAMMA DI PROVA SENZA ALCUNA UTILITA'!
==============================================================================*/
#define Q_EL 10
void inizializza_array( int **array, int *numeri, size_t *annullati );
void visualizza_array( int **array, size_t qEl, size_t non_nulli );
int main( void ) {
size_t annullati, non_nulli;
int numeri[Q_EL];
int *array[Q_EL];
inizializza_array( array, numeri, &annullati );
printf( " %s", "Prima del compattamento" );
visualizza_array( array, Q_EL, Q_EL-annullati );
non_nulli = compatta_array_di_puntatori( array, Q_EL );
printf( " %s", "Dopo il compattamento" );
visualizza_array( array, Q_EL, non_nulli );
return 0;
}
void inizializza_array( int **array, int *numeri, size_t *annullati ) {
int i;
for( i=0; i<Q_EL; ++i ) {
numeri[i] = i+1;
array[i] = &numeri[i];
}
array[0] = NULL; /* il primo */
array[2] = NULL;
array[4] = NULL; /* con questo... */
array[5] = NULL; /* due consecutivi */
array[9] = NULL; /* l'ultimo */
*annullati = 5;
}
void visualizza_array( int **array, size_t qEl, size_t non_nulli ) {
size_t i;
printf( " l'array contiene\n %u puntatori"
" non NULL e %u puntatori NULL:\n\n"
"\t | indirizzo | valore |\n",
non_nulli, qEl-non_nulli );
for( i=0; i<qEl; ++i ) {
if( array[i] ) {
printf( "\tarray[%02u]: | 0x%08X | %02d |\n",
i+1, (unsigned int)array[i], *(array[i]) );
}
else {
printf( "\tarray[%02u]: | (NULL) | ?? |\n", i+1 );
}
}
printf( "%s", "\n" );
}