Paolo Guccini
"Impossibile" non è mai la risposta giusta
Cosa fa:
Varie funzioni per effettuare ricerche in matrice, verificare che una stringa sia numerica o testuale, rimuovere caratteri di controllo o spazi, suddividere una stringa (split) in una matrice, ...
Parti di questo progetto:
Il materiale accessibile da queste pagine fanno parte di una serie di progetti per i quali non è previsto ulteriore sviluppo, ma mantengono la propria validità per studio o base per implementarle in altri progetti. Il loro impiego in altri software e' libero. La loro riproduzione su siti e/o stampa deve avvenire nel rispetto della normativa del diritto d'autore. Per qualunque domanda, mandare una email utilizzando la sezione Contatti di questo sito.
Modulo:
Listato/Codice sorgente: /* ---------------------------------------------------------------------- History 06/set/94 rilevato errore nella picture 999,999.99 per valori interi */ /* ------------------------------------ Include ------------------------- */ #include <stdio.h> #include <string.h> /* ------------------------------------ Defines ------------------------- */ #define MAXLEN_PICTURE_NUM 63 /* ------------------------------------ Global -------------------------- */ int SymDecimale = '.' ; /* ------------------------------------ Function Prototypes ------------- */ char * picture( char * dest , char numero[] , char picture[] ) ; int picture_calcoladecpic( char *stringa ) ; int picture_calcoladecnum( char *stringa ) ; int picture_checknumero( char * numero , char * p_numero ) ; int picture_lunghezzaobbl( char * picture ) ; /* ---------------------------------------------------------------------- */ char * picture( char * dest , char * p_numero , char picture[] ) { char * dbg_dest = dest ; char numero[ MAXLEN_PICTURE_NUM + 1 ] ; char * old_dest = dest ; int n ; int p ; int numero_segno ; int nonripetere_money = 0 ; int nonripetere_sign = 0 ; int lung_decnum = 0 ; int lung_decpic = 0 ; int lung_obbligatoria = 0 ; /* copia su variabile locale il numero per poterlo modificare * se occorresse */ numero_segno = picture_checknumero( numero , p_numero ) ; * dest = NULL ; /* inizio elaborazione per bilanciamento decimali */ lung_decnum = picture_calcoladecnum( numero ) ; lung_decpic = picture_calcoladecpic( picture ) ; // calcolo lunghezza obblibatoria lung_obbligatoria = picture_lunghezzaobbl( picture ) ; /* bilanciamento decimali */ if ( lung_decnum < lung_decpic ) /* nella picture ci sono piu' decimali che nel numero */ { char * runner = numero + strlen(numero) ; /* se il numero non ha decimali e non termina per punto decimale , * allora mettere punto decimale */ if ( ( ! lung_decnum ) && ( *runner != (char ) SymDecimale ) ) { * runner++ = (char ) SymDecimale ; } /* accoda al numero tanti zeri quanti * ne occorrono per avere lo stesso numero * di decimali quanti ce ne sono nella picture */ while ( lung_decnum < lung_decpic ) { lung_decpic -- ; * runner ++ = '0' ; } /* termina la stringa */ * runner = NULL ; } else { /* nel numero ci sono piu' decimali che nella picture */ if ( lung_decnum > lung_decpic ) { /* toglie i numeri decimali non utilizzabili nella picture * senza guardare l'arrotondamento * sottrae 1 per togliere il segno decimale */ * ( numero + strlen( numero ) - ( lung_decnum - lung_decpic ) - 1 ) = NULL ; } /* else : lunghezze uguali */ } /* la stringa finale deve essere costituita sulla base della picture */ /* calcola la lunghezza del numero * ( si sottrae 1 perche la gestione delle matrici nel linguaggio C * inizia da 0 anziche da 1) */ n = strlen( numero ) - 1 ; /* non viene sottratto 1 a 'p' in quanto all'interno * del loop e' gia' decrementato perche' il test * dell'instruzione loop ha l'operatore '--' */ for ( p = strlen( picture ) ; p -- > 0 ; ) { /* verifica se il carattere della picture e' punto decimale * nel caso verifica che il numero abbia il punto decimale * in corrispondenza */ if ( picture [p] == (char ) SymDecimale ) { if ( numero[n] == (char ) SymDecimale ) { * dest++ = picture [p] ; n-- ; // indispensabile per le picure decimali } else { fprintf( stderr , "PICTURE:internal error\n") ; } } else { /* ATTENZIONE : * * se si aggiungono dei caratteri validi per una mask * e' indispensabile modificare anche la funzione * 'picture_calcoladec()' inserendovi il nuovo * carattere, pena errore nel computo dei * decimali */ switch ( picture [p] ) { /* caratteri di cui ne deve apparire solo uno * controllando il segno * e va messo dove non c'e' il numero */ case ( '+' ) : case ( '-' ) : if ( n >= 0) { * dest ++ = numero[n--] ; } else { /* se il segno e' gia' stato utilizzato, * immettere un blank */ if ( nonripetere_sign ) { * dest ++ = ' ' ; } else { if ( numero_segno == (int ) '-' ) { /* numero negativo : il segno deve apparire sempre */ * dest ++ = '-' ; } else { /* numero positivo : il segno deve apparire * solo se nella mask c'e' il segno '+' */ * dest ++ = ( picture[p] == '+' ) ? '+' : ' ' ; } nonripetere_sign = 1 ; } } break ; /* caratteri modificanti */ case ( 'B' ) : *dest ++ = ' ' ; break ; /* caratteri di cui ne deve apparire solo uno */ case ( '$' ) : if ( n >= 0) { * dest ++ = numero[n--] ; } else { if ( nonripetere_money ) { * dest ++ = ' ' ; } else { * dest ++ = picture [p] ; nonripetere_money ++ ; } } break ; case ( '#' ) : case ( '9' ) : * dest ++ = (n >= 0) ? numero[n--] : '0' ; break ; case ( 'Z' ) : /* controlla che non sia lo zero iniziale di un numero * decimale xes.: 0.123 con picture ZZ.ZZZ * questo codice e' possibile in quanto la funzione * 'picture_checknumero' toglie gli eventuali * zeri iniziali inutili xes.: 00123 oppure 00000 */ if ( numero[n] == '0' && n == 0 ) { * dest++ = ' ' ; n-- ; } else { * dest++ = (n >= 0) ? numero[n--] : ' ' ; } break ; /* simboli che devono apparire sempre ovvero anche * quando il numero e' terminato */ case ( '/' ) : case ( '*' ) : case ( '0' ) : * dest ++ = (n >= 0) ? numero[n--] : picture [p] ; break ; /* caratteri che NON devono essere gestiti anche * quando il numero e' terminato */ case ( '.' ) : case ( ',' ) : * dest++ = (n >= 0 || picture[p+1]=='9') ? picture [p] : ' ' ; break ; default : printf( "PICTURE:unknown mask\n" ) ; } } } /* chiude stringa e la ribalta */ * dest = NULL ; strrev( old_dest ) ; return old_dest ; } /* ---------------------------------------------------------------------- * Function * calcola quanti decimali sono richiesti nella picture * considerando che i blank 'B' le barre '/' eccetera * non devono considerarsi * Note * Se vengono implementati nuovi caratteri ammessi dalla picture * allora li si devono implementare anche questa funzione */ int picture_calcoladecpic( char *stringa ) { int lung_dec = 0 ; while ( *stringa ) { /* conta caratteri prima del decimale */ if ( *stringa != SymDecimale ) { stringa ++ ; } else { stringa ++ ; /* scavalva segno decimale */ /* conta caratteri dopo il decimale * non si considerano i caratteri di riempiemento come la barra * o il blank */ while ( *stringa ) { switch ( * stringa ++ ) { case ( 'Z' ) : case ( '9' ) : case ( '#' ) : case ( '-' ) : case ( '+' ) : case ( '$' ) : case ( '0' ) : lung_dec ++ ; break ; } } } } return lung_dec ; } /* ---------------------------------------------------------------------- */ /* ---------------------------------------------------------------------- * Function */ int picture_calcoladecnum( char *stringa ) { int lung_dec = 0 ; while ( *stringa ) { /* scavalca caratteri prima del decimale */ if ( *stringa != SymDecimale ) { stringa ++ ; } else { stringa ++ ; /* scavalva segno decimale */ while ( *stringa++ ) { lung_dec ++ ; } } } return lung_dec ; } /* ---------------------------------------------------------------------- * function * esegue alcuni controlli sul numero, copia il numero ricevuto * dal programma in una variabile locale, * verifica il segno (memorizzandolo per il 'return' e togliendolo * dal numero stesso * controlla che il numero abbia almeno una cifra prima del punto * decimale (se il numero e' decimale) * returns * segno del numero */ int picture_checknumero( char * numero , char * p_numero ) { int numero_segno ; /* copia il numero in una variabile locale della funzione chiamante */ strcpy( numero , p_numero ) ; /* controlla il segno * il segno deve essere il primo carattere. * per abilitare segno in coda, modificare questa parte di codice */ if ( * numero != '-' ) { numero_segno = '+' ; } else { int xloop ; int xlen ; numero_segno = '-' ; /* toglie il meno dal numero * spostando tutti i caratteri a sinistra di una posizione */ xlen = strlen( numero ) ; for ( xloop = 1 ; xloop <= xlen ; xloop ++ ) { numero[xloop-1] = numero[xloop] ; } } /* controllo che non ci siano degli zeri iniziali inutili * ad esempio : 00123 00000 */ if ( numero[0] == '0' ) { if ( numero [1] != SymDecimale ) { int xlen = 0 ; int xloop = 0 ; /* conta gli zeri inutili */ while ( numero [xloop] != SymDecimale && numero [ xloop ++ ] ) { xlen++ ; } /* toglie gli zeri inutili * spostando tutti i caratteri a sinistra */ for ( xloop = 1 ; numero[xlen] ; xlen ++ ) { numero[xloop] = numero[xlen] ; } numero[xloop] = NULL ; } } /* controlla che il numero non sia solo decimale senza lo zero davanti * ovvero .12 anziche' 0.12 */ if ( *numero == (char ) SymDecimale ) { int xloop ; /* crea uno spazio a sinistra del numero * spostando tutti i caratteri a destra di una posizione */ for ( xloop = strlen( numero ) ; xloop > 0 ; xloop -- ) { numero[xloop] = numero[xloop-1] ; } /* * ( numero + strlen(numero) ) = NULL ; */ /* mette nello spazio creato lo zero */ numero [0] = '0' ; } return numero_segno ; } /* ---------------------------------------------------------------------- */ int picture_lunghezzaobbl( char * picture ) { int l = strlen( picture ) ; while ( * picture ) { if ( * picture == '9' || * picture == '#' ) { break ; } picture ++ ; l -- ; } return l ; } // Paolo Guccini (lettori@paologuccini.it) /* ---------------------------------------------------------------------- */ /* #include <conio.h> #define TOTA 40 void main() { char dest[80] ; char dest2[80] ; int l ; char num[TOTA][30] = { "1111" , "-1111" , "999,999,999,999" , "1" , "-1" , "99.99" , "0" , "-0" , "9" , "-.7" , ".7" , "$--,---,ZZZ.ZZ" , "1234" , "-1234" , "+-$,$$$,$$$.$$" , "1234.5" , "-1234.5", "$$$,$$$,$$$.$$" , "1234567.55" , "-1234567.55", "ZZZ,999,999" , "1234567" , "-1234567","ZZZ,999,999.99" , "1234567.87" ,"-1234567.87", "ZZZ,999,999.99" , "123456.7" , "-123456.7","ZZZ,999,999" , "0" ,"-0", "ZZZ,ZZZ,ZZZ.ZZ" , "0.0" ,"-0.0", "ZZZ,ZZZ,ZZZ" , "1" , "-1" , "999,999.00" } ; clrscr() ; for ( l = 0 ; l < TOTA ; ) { // memset( dest , ' ' , 79 ) ; // dest[0] = NULL ; // dest2[0] = NULL ; picture( dest , num[l] , num[l+2] ) ; picture( dest2 , num[l+1] , num[l+2] ) ; printf( "PIC=%s V=%s R=%s V=%s R=%s\n" , num[l+2] , num[l] , dest , num[l+1] , dest2 ) ; l+=3 ; } } */