11/07/17 7:00
AldoBaldo
Ah! Il potere del tempo libero! Uno si mette lì e si fa venire delle idee balzane...
Volendo creare in C una funzione che "compatti" aaRRRaay di puntatori di qualsiasi tipo e non potendo usare void**, al netto dei possibili errori che un programmatore disattento potrebbe fare passando parametri non validi, sarebbe plausibile una soluzione come quella che copio/incollo qui sotto?
Dai test che ho fatto sembrerebbe di sì, nessun errore in compilazione e puntatori piazzati esattamente dove uno se li aspetterebbe, però incombe sempre la paranoia dei "comportamenti indefiniti", quelli che danno luogo a codice che funziona in un certo ambiente e non funziona in un altro...
(il codice "incriminato" è quello contenuto tra la riga 39 e la riga 55, tutto il resto è solo contorno)
In uscita, il programma di prova mi dà...
Volendo creare in C una funzione che "compatti" aaRRRaay di puntatori di qualsiasi tipo e non potendo usare void**, al netto dei possibili errori che un programmatore disattento potrebbe fare passando parametri non validi, sarebbe plausibile una soluzione come quella che copio/incollo qui sotto?
Dai test che ho fatto sembrerebbe di sì, nessun errore in compilazione e puntatori piazzati esattamente dove uno se li aspetterebbe, però incombe sempre la paranoia dei "comportamenti indefiniti", quelli che danno luogo a codice che funziona in un certo ambiente e non funziona in un altro...
(il codice "incriminato" è quello contenuto tra la riga 39 e la riga 55, tutto il resto è solo contorno)
#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" ); }
In uscita, il programma di prova mi dà...
Prima del compattamento l'array contiene 5 puntatori non NULL e 5 puntatori NULL: | indirizzo | valore | array[01]: | (NULL) | ?? | array[02]: | 0x0022FED4 | 02 | array[03]: | (NULL) | ?? | array[04]: | 0x0022FEDC | 04 | array[05]: | (NULL) | ?? | array[06]: | (NULL) | ?? | array[07]: | 0x0022FEE8 | 07 | array[08]: | 0x0022FEEC | 08 | array[09]: | 0x0022FEF0 | 09 | array[10]: | (NULL) | ?? | Dopo il compattamento l'array contiene 5 puntatori non NULL e 5 puntatori NULL: | indirizzo | valore | array[01]: | 0x0022FED4 | 02 | array[02]: | 0x0022FEDC | 04 | array[03]: | 0x0022FEE8 | 07 | array[04]: | 0x0022FEEC | 08 | array[05]: | 0x0022FEF0 | 09 | array[06]: | (NULL) | ?? | array[07]: | (NULL) | ?? | array[08]: | (NULL) | ?? | array[09]: | (NULL) | ?? | array[10]: | (NULL) | ?? | Process returned 0 (0x0) execution time : 0.049 s Press any key to continue.
Ultima modifica effettuata da AldoBaldo 11/07/17 7:37
ATTENZIONE! Sono un hobbista e l'affidabilità delle mie conoscenze informatiche è molto limitata. Non prendere come esempio il codice che scrivo, perché non ho alcuna formazione accademica e rischieresti di apprendere pratiche controproducenti.