19/05/17 20:25
AldoBaldo
Non so se a qualcuno possa tornare utile questa roba, però ho messo insieme un po' di funzioni di (in)utilità per stringhe dinamiche in C. In caso valga la pena (ditemelo voi) posso aggiungerlo alla sezione "esempi" o "utilità" o chissà quale dell'elenco dei programmi di Pierotofy.
Se intendete leggere sedetevi, perché il codice è un po' lunghetto...
utilita_stringhe_dinamiche.h:
utilita_stringhe_dinamiche.c:
Lo scopo di tanto lavorio è sempre lo stesso: passare il tempo a far qualcosa di più attivo rispetto a guardare la TV.
Se intendete leggere sedetevi, perché il codice è un po' lunghetto...
utilita_stringhe_dinamiche.h:
#ifndef UTILITA_STRINGHE_DINAMICHE_H_INCLUDED #define UTILITA_STRINGHE_DINAMICHE_H_INCLUDED /*============================================================================== duplica_stringa() Riceve il puntatore ad una stringa C, ne effettua una copia in un'area di memoria dinamica appositamente allocata, restituisce il puntatore alla memoria allocata (NULL se l'allocazione fallisce). Spetta al chiamante liberare con libera_buffer() la memoria allocata. ==============================================================================*/ char *duplica_stringa( const char *str ); /*============================================================================== dimensiona_stringa() Alloca la quantita' di memoria indicata da dim (dim NON include il carattere terminatore) e copia la stringa str nello spazio di memoria allocato. Se dim e' minore della lunghezza corrente della stringa, la stringa viene troncata. Se dim e' maggiore della lunghezza corrente della stringa, lo spazio eccedente viene impostato su una serie di zeri. Restituisce il puntatore alla memoria allocata (NULL se l'allocazione fallisce). Spetta al chiamante liberare con libera_buffer() la memoria allocata. ==============================================================================*/ char *dimensiona_stringa( const char *str, size_t dim ); /*============================================================================== inserisci_stringa() Inserisce la stringa agg nella posizione pos della stringa s. Se pos eccede la lunghezza della stringa, l'aggiunta viene effettuata in coda alla stringa stessa. Colloca la stringa risultante in un'area di memoria dinamica appositamente allocata e restituisce il puntatore alla memoria allocata (NULL se l'allocazione fallisce). Spetta al chiamante liberare con libera_buffer() la memoria allocata. ==============================================================================*/ char *inserisci_stringa( const char *str, const char *agg, size_t pos ); /*============================================================================== inserisci_intero() Converte in stringa il valore indicato da n, quindi lo inserisce nella posizione pos della stringa s. Se pos eccede la lunghezza della stringa, l'aggiunta viene effettuata in coda alla stringa stessa. Colloca la stringa risultante in un'area di memoria dinamica appositamente allocata e restituisce il puntatore alla memoria allocata (NULL se l'allocazione fallisce). Spetta al chiamante liberare con libera_buffer() la memoria allocata. ==============================================================================*/ char *inserisci_intero( const char *str, int n, size_t pos ); /*============================================================================== sostituisci_caratteri() Sostituisce nella stringa str tutte le occorrenze dei caratteri indicati nella stringa orig con i caratteri indicati nelle stesse posizioni nella stringa sost. Ad esempio, sostituisci_caratteri( "Provetta", "Pt", "Bd" ) da' come esito la stringa "Brovedda". Colloca la stringa risultante in un'area di memoria dinamica appositamente allocata e restituisce il puntatore alla memoria allocata (NULL se l'allocazione fallisce). Spetta al chiamante liberare con libera_buffer() la memoria allocata. ==============================================================================*/ char *sostituisci_caratteri( const char *str, const char *orig, const char *sost ); /*============================================================================== sostituisci_frammento() Sostituisce un frammento di l caratteri della stringa s con la stringa sost, a partire dalla posizione pos (sost puo' anche essere piu' lungo o piu' corto di l caratteri). Colloca la stringa risultante in un'area di memoria dinamica appositamente allocata e restituisce il puntatore alla memoria allocata (NULL se l'allocazione fallisce). Spetta al chiamante liberare con libera_buffer() la memoria allocata. ==============================================================================*/ char *sostituisci_frammento( const char *str, const char *sost, size_t pos, size_t l ); /*============================================================================== sostituisci_frammenti() Cerca nella stringa str le ricorrenze della stringa ptrn e le sostituisce con la stringa sost. Colloca la stringa risultante in un'area di memoria dinamica appositamente allocata e restituisce il puntatore alla memoria allocata (NULL se l'allocazione fallisce). Spetta al chiamante liberare con libera_buffer() la memoria allocata. ==============================================================================*/ char *sostituisci_frammenti( const char *str, const char *ptrn, const char *sost ); /*============================================================================== sostituisci_segnaposto() Cerca nella stringa str le ricorrenze della stringa ptrn e le sostituisce, nell'ordine, con le stringhe contenute nell'array di stringhe puntato da sost. L'array deve contenere la quantita' di stringhe specificata dal parametro qSost. Se ci sono discrepanze tra la quantita' delle ricorrenze di ptrn in str e il valore di qSost, prevale la quantita' minore. Colloca la stringa risultante in un'area di memoria dinamica appositamente allocata e restituisce il puntatore alla memoria allocata (NULL se l'allocazione fallisce). Spetta al chiamante liberare con libera_buffer() la memoria allocata. ==============================================================================*/ char *sostituisci_segnaposto( const char *str, const char *ptrn, const char **sost, size_t qSost ); /*============================================================================== libera_buffer() Riceve il puntatore ad un puntatore ad una stringa C collocata in un'area di memoria allocata dinamicamente, libera con free() quella memoria e annulla il puntatore. ==============================================================================*/ void libera_buffer( char **buffer ); #endif // UTILITA_STRINGHE_DINAMICHE_H_INCLUDED
utilita_stringhe_dinamiche.c:
#include <stdlib.h> #include <stdio.h> #include <string.h> #include "utilita_stringhe_dinamiche.h" /*============================================================================== Riceve il puntatore ad una stringa C, ne effettua una copia in un'area di memoria dinamica appositamente allocata, restituisce il puntatore alla memoria allocata (NULL se l'allocazione fallisce). Spetta al chiamante liberare con libera_buffer() la memoria allocata. ==============================================================================*/ char *duplica_stringa( const char *str ) { char *tmp = NULL; if( str ) { // verifica che il parametro s sia una stringa valida size_t l = strlen(str)+1; // +1 per includere il terminatore if( (tmp=malloc(l)) ) memcpy( tmp, str, l ); } return tmp; } /*============================================================================== Alloca la quantita' di memoria indicata da dim (dim NON include il carattere terminatore) e copia la stringa str nello spazio di memoria allocato. Se dim e' minore della lunghezza corrente della stringa, la stringa viene troncata. Se dim e' maggiore della lunghezza corrente della stringa, lo spazio eccedente viene impostato su una serie di zeri. Restituisce il puntatore alla memoria allocata (NULL se l'allocazione fallisce). Spetta al chiamante liberare con libera_buffer() la memoria allocata. ==============================================================================*/ char *dimensiona_stringa( const char *str, size_t dim ) { char *tmp = NULL; if( str ) { // verifica che il parametro s sia una stringa valida tmp = calloc( dim+1, sizeof(*tmp) ); if( tmp ) { // allocazione riuscita, copiamo size_t l = strlen( str ); strncpy( tmp, str, l<dim?l:dim ); } } return tmp; } /*============================================================================== Inserisce la stringa agg nella posizione pos della stringa s. Se pos eccede la lunghezza della stringa, l'aggiunta viene effettuata in coda alla stringa stessa. Colloca la stringa risultante in un'area di memoria dinamica appositamente allocata e restituisce il puntatore alla memoria allocata (NULL se l'allocazione fallisce). Spetta al chiamante liberare con libera_buffer() la memoria allocata. ==============================================================================*/ char *inserisci_stringa( const char *str, const char *agg, size_t pos ) { char *tmp = NULL; if( str && agg ) { size_t lStr = strlen( str ); size_t lAgg = strlen( agg ); tmp = malloc( lStr+lAgg+1 ); if( tmp ) { // allocazione riuscita, inseriamo if( pos > lStr ) pos = lStr; memcpy( tmp, str, pos ); memcpy( tmp+pos, agg, lAgg ); memcpy( tmp+pos+lAgg, str+pos, lStr-pos+1 ); } } else if( str ) tmp = duplica_stringa( str ); return tmp; } /*============================================================================== Converte in stringa il valore indicato da n, quindi lo inserisce nella posizione pos della stringa s. Se pos eccede la lunghezza della stringa, l'aggiunta viene effettuata in coda alla stringa stessa. Colloca la stringa risultante in un'area di memoria dinamica appositamente allocata e restituisce il puntatore alla memoria allocata (NULL se l'allocazione fallisce). Spetta al chiamante liberare con libera_buffer() la memoria allocata. ==============================================================================*/ char *inserisci_intero( const char *str, int n, size_t pos ) { char buff[32]; sprintf( buff, "%d", n ); return inserisci_stringa( str, buff, pos ); } /*============================================================================== Sostituisce nella stringa str tutte le occorrenze dei caratteri indicati nella stringa orig con i caratteri indicati nelle stesse posizioni nella stringa sost. Ad esempio, sostituisci_caratteri( "Provetta", "Pt", "Bd" ) da' come esito la stringa "Brovedda". Colloca la stringa risultante in un'area di memoria dinamica appositamente allocata e restituisce il puntatore alla memoria allocata (NULL se l'allocazione fallisce). Spetta al chiamante liberare con libera_buffer() la memoria allocata. ==============================================================================*/ char *sostituisci_caratteri( const char *str, const char *orig, const char *sost ) { char *tmp = NULL; if( str && orig && sost ) { size_t lStr = strlen( str ); size_t lOrig = strlen( orig ); size_t lSost = strlen( sost ); if( lStr && lOrig && lSost && lOrig==lSost ) { size_t i, j; tmp = duplica_stringa( str ); if( tmp ) { // allocazione riuscita, sostituiamo for( i=0; i<lStr; ++i ) for( j=0; j<lOrig; ++j ) if( tmp[i] == orig[j] ) tmp[i] = sost[j]; } } } else if( str ) tmp = duplica_stringa( str ); return tmp; } /*============================================================================== Sostituisce un frammento di l caratteri della stringa s con la stringa sost, a partire dalla posizione pos (sost puo' anche essere piu' lungo o piu' corto di l caratteri). Colloca la stringa risultante in un'area di memoria dinamica appositamente allocata e restituisce il puntatore alla memoria allocata (NULL se l'allocazione fallisce). Spetta al chiamante liberare con libera_buffer() la memoria allocata. ==============================================================================*/ char *sostituisci_frammento( const char *str, const char *sost, size_t pos, size_t l ) { char *tmp = NULL; if( str && sost ) { size_t lStr = strlen( str ); size_t lSost = strlen( sost ); if( pos > lStr ) pos = lStr; if( pos+l > lStr ) l = lStr-pos; tmp = malloc( (lStr-l)+lSost+1 ); if( tmp ) { // allocazione riuscita, sostituiamo memcpy( tmp, str, pos ); memcpy( tmp+pos, sost, lSost ); memcpy( tmp+pos+lSost, str+pos+l, lStr-pos-l+1 ); } } else if( str ) tmp = duplica_stringa( str ); return tmp; } /*============================================================================== Cerca nella stringa str le ricorrenze della stringa ptrn e le sostituisce con la stringa sost. Colloca la stringa risultante in un'area di memoria dinamica appositamente allocata e restituisce il puntatore alla memoria allocata (NULL se l'allocazione fallisce). Spetta al chiamante liberare con libera_buffer() la memoria allocata. ==============================================================================*/ char *sostituisci_frammenti( const char *str, const char *ptrn, const char *sost ) { char *tmp = NULL; // per il buffer dell'esito if( str && ptrn && sost ) { // verifica la validita' dei parametri // quanto e' lungo il pattern da sostituire? size_t lPtrn = strlen( ptrn ); if( lPtrn != 0 ) { // il pattern da sostituire non puo' essere vuoto // quante volte ptrn ricorre nella stringa? size_t qRic; // qRic = quantita' di ricorrenze (del pattern in str) const char *pPtrn = strstr( str, ptrn ); for( qRic=0; pPtrn; ++qRic ) pPtrn = strstr( ++pPtrn, ptrn ); if( qRic>0 ) { // il pattern deve essere presente almeno una volta // rileva la lunghezza delle parti "in gioco" size_t lStr = strlen( str ); // la lunghezza di str size_t lSost = strlen( sost ); // lunghezza delle sostituzioni // alloca il buffer per la stringa risultante dalle sostituzioni tmp = malloc( lStr - lPtrn*qRic + lSost*qRic + 1 ); if( tmp ) { // allocazione riuscita, sostituiamo const char *pOrig; // il punto di str dal quale copiare char *pDest; // punta al punto di tmp nel quale copiare size_t i; for( pOrig=str, pDest=tmp, i=0; i<=qRic; ++i ) { if( (pPtrn=strstr(pOrig,ptrn)) ) { memcpy( pDest, pOrig, pPtrn-pOrig ); pDest += pPtrn-pOrig; pOrig += pPtrn-pOrig + lPtrn; memcpy( pDest, sost, lSost ); pDest += lSost; } else memcpy( pDest, pOrig, lStr-(pOrig-str)+1 ); } } } else tmp = duplica_stringa( str ); } else tmp = duplica_stringa( str ); } else if( str ) tmp = duplica_stringa( str ); return tmp; } /*============================================================================== Cerca nella stringa str le ricorrenze della stringa ptrn e le sostituisce, nell'ordine, con le stringhe contenute nell'array di stringhe puntato da sost. L'array deve contenere la quantita' di stringhe specificata dal parametro qSost. Se ci sono discrepanze tra la quantita' delle ricorrenze di ptrn in str e il valore di qSost, prevale la quantita' minore. Colloca la stringa risultante in un'area di memoria dinamica appositamente allocata e restituisce il puntatore alla memoria allocata (NULL se l'allocazione fallisce). Spetta al chiamante liberare con libera_buffer() la memoria allocata. ==============================================================================*/ char *sostituisci_segnaposto( const char *str, const char *ptrn, const char **sost, size_t qSost ) { size_t *lSost = NULL; char *tmp = NULL; size_t i; // verifica la validita' dei parametri if( sost ) { for( i=0; i<qSost; ++i ) if( !sost[i] ) return duplica_stringa( str ); } else return duplica_stringa( str ); if( str && ptrn ) { // verifica la validita' dei parametri // quant'e' lungo il pattern da sostituire? size_t lPtrn = strlen( ptrn ); if( lPtrn != 0 ) { // il pattern da sostituire non puo' essere vuoto // quante volte ptrn ricorre nella stringa? size_t qRic; // qRic = quantita' di ricorrenze (del pattern in str) const char *pPtrn = strstr( str, ptrn ); // la posizione del pattern for( qRic=0; pPtrn; ++qRic ) pPtrn = strstr( ++pPtrn, ptrn ); if( qRic > qSost ) qRic = qSost; else qSost = qRic; // alloca un buffer per la lunghezza delle stringhe sostitutive if( (lSost=calloc(qSost,sizeof(*lSost))) == NULL ) return tmp; if( qRic>0 ) { // il pattern deve essere presente almeno una volta size_t lStr = strlen( str ); // la lunghezza di str size_t totLSost = 0; // la lunghezza totale delle sostituzioni // rileva la lunghezza d'ognuna delle parti sostitutive for( i=0; i<qSost; ++i ) { lSost[i] = strlen( sost[i] ); totLSost += lSost[i]; // aggiunge alla somma totale } // alloca il buffer per la stringa risultante dalle sostituzioni tmp = malloc( lStr - lPtrn*qRic + totLSost + 1 ); if( tmp ) { // allocazione riuscita, sostituiamo const char *pOrig; // il punto di str dal quale copiare char *pDest; // punta al punto di tmp nel quale copiare for( pOrig=str, pDest=tmp, i=0; i<=qRic; ++i ) { if( (pPtrn=strstr(pOrig,ptrn)) ) { memcpy( pDest, pOrig, pPtrn-pOrig ); pDest += pPtrn-pOrig; pOrig += pPtrn-pOrig + lPtrn; memcpy( pDest, sost[i], lSost[i] ); pDest += lSost[i]; } else memcpy( pDest, pOrig, lStr-(pOrig-str)+1 ); } } } else tmp = duplica_stringa( str ); } else tmp = duplica_stringa( str ); } else if( str ) tmp = duplica_stringa( str ); free( lSost ); return tmp; } /*============================================================================== Riceve il puntatore ad un puntatore ad una stringa C collocata in un'area di memoria allocata dinamicamente, libera con free() quella memoria e annulla il puntatore. ==============================================================================*/ void libera_buffer( char **buffer ) { if( buffer ) if( *buffer ) { free( *buffer ); *buffer = NULL; } }
Lo scopo di tanto lavorio è sempre lo stesso: passare il tempo a far qualcosa di più attivo rispetto a guardare la TV.
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.