// Libreria LDE (Liste Di Estrazione)
// di Aldo Carpanelli, v1.0.0 - 08/02/2020
#include "liste_di_estrazione.h"
static int LDE_gSRandInvocata = 0;
static int LDE_gUltimoErrore = LDEErr_NoErr;
static const short LDE_InitOk = 0x6B6F; // 'ok'
static void LDE_InizializzaCaso( void ) {
char cifre[] = "0123456789ABCDEF";
int i;
// mischia un po' le carte, per cominciare...
for( srand(time(NULL)), i=0; i<10; rand(), ++i );
// crea un numero con 8 cifre casuali
char semeStr[12];
for( semeStr[8]='\0', i=0; i<8; ++i )
semeStr[i] = cifre[rand()%16];
srand( strtoul(semeStr,NULL,16) );
LDE_gSRandInvocata = 1;
}
static short LDE_Caso( short v ) {
return ((double)(v))*((double)rand())/((double)RAND_MAX);
}
LDE LDE_Crea( short qVal ) {
LDE lde = NULL;
// valida il parametro qVal
qVal = qVal>=0 ? qVal : -qVal; // qVal e' interpretato come valore assoluto
if( qVal<2 ) { LDE_gUltimoErrore=LDEErr_NoEl; return lde; }
// alloca la struttura LDE
lde = calloc( 1, sizeof(*lde) );
if( NULL == lde ) { LDE_gUltimoErrore=LDEErr_NoMem; return lde; }
// alloca il nuovo array in memoria dinamica
if( NULL == (lde->v=(short*)calloc(qVal,sizeof(*(lde->v)))) )
{ LDE_gUltimoErrore=LDEErr_NoMem; return LDE_Distruggi( lde ); }
lde->qv = qVal; // memorizza la quantita' dei valori
lde->ue = -1; // non esiste un ultimo estratto valido
lde->ok = LDE_InitOk;
LDE_Reset(lde); // inizializza l'array e imposta lde->de
if( !LDE_gSRandInvocata ) LDE_InizializzaCaso();
return lde;
}
int LDE_Dimensiona( LDE lde, short qVal ) {
short *vTmp = NULL;
// valida il parametro qVal
qVal = qVal>=0 ? qVal : -qVal; // qVal e' interpretato come valore assoluto
if( qVal<2 )
return LDE_gUltimoErrore=LDEErr_NoEl;
if( !LDE_Valida(lde) ) return LDE_gUltimoErrore;
if( qVal != lde->qv ) {
// alloca il nuovo array in memoria dinamica
if( NULL == (vTmp=(short*)calloc(qVal,sizeof(*vTmp))) )
return LDE_gUltimoErrore = LDEErr_NoMem;
free( lde->v );
lde->v = vTmp;
lde->qv = qVal; // memorizza la quantita' dei valori
}
return LDE_Reset(lde); // inizializza l'array e imposta lde->de
}
LDE LDE_Duplica( const LDE originale ) {
LDE duplicato = NULL;
if( !LDE_Valida(originale) ) return duplicato;
duplicato = LDE_Crea( originale->qv );
if( NULL != duplicato ) {
memcpy( duplicato->v, originale->v,
originale->qv*sizeof(*originale->v) );
duplicato->qv = originale->qv;
duplicato->ue = originale->ue;
duplicato->de = originale->de;
}
return duplicato;
}
int LDE_Copia( LDE destinazione, const LDE origine ) {
if( !LDE_Valida(destinazione) )
return LDE_gUltimoErrore;
if( !LDE_Valida(origine) )
return LDE_gUltimoErrore;
if( destinazione->qv != origine->qv ) {
LDE ldeTmp = LDE_Crea( origine->qv );
if( ldeTmp ) {
free( destinazione->v );
destinazione->v = ldeTmp->v;
free( ldeTmp );
}
}
memcpy( destinazione->v, origine->v, sizeof(*origine->v)*origine->qv );
destinazione->qv = origine->qv;
destinazione->ue = origine->ue;
destinazione->de = origine->de;
return LDE_gUltimoErrore;
}
LDE LDE_Distruggi( LDE lde ) {
if( NULL != lde ) {
if( NULL != lde->v ) {
free( lde->v );
lde->v = NULL;
}
free( lde );
lde = NULL;
}
return lde;
}
int LDE_Valida( const LDE lde ) {
if( NULL==lde )
{ LDE_gUltimoErrore = LDEErr_PtrNULL; return 0; }
if( NULL==lde->v )
{ LDE_gUltimoErrore = LDEErr_NoArray; return 0; }
if( LDE_InitOk!=lde->ok )
{ LDE_gUltimoErrore = LDEErr_NoInit; return 0; }
if( lde->qv < 2 )
{ LDE_gUltimoErrore = LDEErr_NoEl; return 0; }
if( lde->qv < lde->de )
{ LDE_gUltimoErrore = LDEErr_NoEl; return 0; }
LDE_gUltimoErrore = LDEErr_NoErr;
return 1;
}
int LDE_Reset( LDE lde ) {
short *auxPtr, i;
if( !LDE_Valida(lde) ) return LDE_gUltimoErrore;
for( auxPtr=lde->v, lde->de=lde->qv, i=0; i<lde->qv; ++i ) *auxPtr++ = i;
// tutti i valori sono ora disponibili per un nuovo ciclo di estrazioni
return LDE_gUltimoErrore;
}
short LDE_Estrai( LDE lde ) {
short posizione, estratto = -1;
short *vAlias, *stop;
if( !LDE_Valida(lde) ) return estratto;
if( !lde->de ) LDE_Reset( lde ); // non ci sono piu' numeri da estrarre!
do {
posizione = LDE_Caso(lde->de); // una posizione a caso
estratto = *(lde->v+posizione); // cosa c'e' in quella posizione?
} while( estratto == lde->ue ); // evita d'estrarre 2 volte
// lo stesso valore
stop = lde->v + lde->de-1; // "stop" punta all'ultimo elemento
vAlias = lde->v + posizione; // "vAlias" punta all'elemento estratto
// "compatta" l'array eliminandone il valore estratto
while( vAlias != stop ) { *vAlias = *(vAlias+1); ++vAlias; }
lde->ue = estratto; // memorizza l'ultimo valore estratto
--lde->de; // c'e' un elemento in meno tra quelli da estrarre
return estratto; // restituisce il valore estratto
}
int LDE_UltimoErrore( void ) {
return LDE_gUltimoErrore;
}
const char *DescrizioneUltimoErrore( void ) {
return LDE_DescrizioneErrore( LDE_gUltimoErrore );
}
const char *LDE_DescrizioneErrore( int codice ) {
static const char *kStrErr[] = {
"nessun errore",
"puntatore NULL",
"array mancante",
"struttura non inizializzata",
"quantita' di valori insufficiente",
"quantita' dei valori da estrarre maggiore della quantita' dei valori disponibili",
"allocazione di memoria non riuscita"
};
if( codice>=LDEErr_NoErr && codice<LDE_MaxErr )
return kStrErr[codice];
else return "errore non previsto";
}