Una delle caratteristiche del linguaggio C è il numero limitato di funzioni offerte dalla libreria di base, specie per quanto riguarda la gestione delle stringhe. In altri articoli abbiamo già creato delle nostre funzioni e piano piano stiamo creando la nostra propria libreria. In questo articolo vediamo una semplice funzione per la rimozione di caratteri da una stringa.

wooden cubes 540 360

Piano piano stiamo creando la nostra libreria per la gestione delle stringhe; qui abbiamo già visto come implementare un Trim() per rimuovere gli spazi iniziali e finali mentre qui abbiamo creato una funzione per la sostituzione di stringhe. In questo articolo il nostro obiettivo è scrivere una funzione per la rimozione di specifici caratteri da una stringa.

Supponiamo che si voglia creare un file il cui nome dipenda dal contenuto di una stringa: potremmo voler eliminare subito i caratteri non validi per un nome di file (ad es. '\', ':' ...) per limitare al massimo le possibilità di errore.

Ci troviamo di fronte alla necessità di avere una funzione che ricevuto in input una stringa proceda a modificarla eliminando i caratteri non ammessi; tale funzione potrebbe avere il seguente prototipo:

char *RemoveChars(char *str, char *charstoremove)  

Il puntatore str conterrà il puntatore alla stringa mentre la stringa charstoremove conterrà l'elenco dei caratteri da eliminare; da notare che la funzione ritorna un char *, che sarà la stessa stringa che ci è stata passata, in modo da permettere di utilizzare la funzione come meglio si crede.

Da notare il nome della funzione in inglese: questo non è per darsi un tono ma, come per altre situazioni, è una questione di praticità ed immediatezza.
Provate a cercare su internet "RimuoviCaratteri" e poi cercate "RemoveChars": noterete che con il nome inglese trovate molti più risultati pertinenti e probabilmente troverete questa stessa funzione implementata in altri linguaggi. Con questo non voglio dire che l'inglese sia meglio dell'italiano: faccio solo notare che la maggior parte dei linguaggi possiede delle keyword che provengono dall'inglese e pure le librerie di funzioni solitamente adottano tale lingua.

Ma veniamo all'implementazione: confesso che dopo una mia prima implementazione sono andato a cercare su internet soluzioni alternative e ho trovato questa discussione interessante https://stackoverflow.com/questions/5457608/how-to-remove-the-character-at-a-given-index-from-a-string-in-c. Seguendo queste indicazioni ho trovato che l'implementazione migliore è la seguente:

  • utilizzo due puntatori (src e dst) che inizialmente puntano entrambi alla stringa da lavorare
  • eseguo un ciclo su tutta la stringa usando il puntatore src
  • ad ogni passata di ciclo il puntatore dst avanza come il puntatore src; se però src punta ad un carattere da rimuovere allora dst rimane fermo e non avanza (in questo modo si ottiene la rimozione del carattere)
  • il valore puntato da src viene copiato nel valore puntato da dst solo se questi due puntatori contengono due indirizzi diversi, infatti:
    • se contengono lo stesso indirizzo vuol dire che non abbiamo ancora rimosso caratteri, quindi non c'è bisogno di modificare ancora la stringa
    • se hanno un indirizzo diverso vuol dire che src è "più avanti" di dst e perciò dobbiamo "compattare" la stringa.

Da notare che per controllare se il carattere è da rimuovere utilizziamo la funzione strchr() che, dato un carattere e una stringa, ci dice se quel carattere è presente nella stringa.

 Ecco quindi l'implementazione:

//------------------------------------------------------------------------------------- 
// RemoveChars() 
// 
// tratta la stringa passata eliminando i caratteri specificati 
//------------------------------------------------------------------------------------- 
char *RemoveChars(char *str, char *charstoremove) 
{ 
	char *src = str; 
	char *dst = str; 
 
	while (*src) 
	{ 
		if (src != dst)					// se src e dst non coincidono più 
			*dst = *src;				// aggiorniamo la destinazione 
 
		if (!strchr(charstoremove, *dst))		// se il carattere non è fra quelli da eliminare 
			dst++;					// avanziamo con la destinazione 
 
		src++; 
	} 
	*dst = '\0'; 
 
	return str; 
} 

Spero che tale funzione possa risultarvi utile e che l'implementazione possa aiutarvi se state imparando il linguaggio C o se state creando appunto una vostra libreria di funzioni.

E come sempre... Buon divertimento!