Come prototipo ho deciso di utilizzare qualcosa del genere:
int StrReplace(char *str, int maxstr, char *pattern, char *replace);
dove str è la stringa da modificare, maxstr la dimensione allocata per tale stringa, pattern la stringa da ricercare e replace la stringa da utilizzare in sostituzione.
La String.Replace() di C# sostituisce tutte le occorrenze che trova mentre la mia funzione, per semplicità, si limita alla prima occorrenza. Per lavorare come la String.Replace() è possibile sfruttare il valore di ritorno che sarà 1 nel caso di sostituzione avvenuta o 0 se non c'è stata alcuna sostituzione (o <0 in caso di errore), permettendoci quindi di scrivere
while( StrReplace(...) == 1 ) {};
Qui di seguito presento il codice completo e le spiegazioni.
La funzione svolge il compito di cercare una sottostringa (chiamata pattern) e sostituirla con una nuova (replace).
I possibili valori di ritorno sono:
- -1 se non c'è sufficiente spazio allocato per l'eventuale sostituzione;
- 0 se la sottostringa pattern non è stata trovata;
- 1 se la sottostringa pattern è stata trovata e sostituita da replace.
char miastringa[80];
strcpy(miastringa, "Quel ramo del lago di Como");
StrReplace(miastringa,80,"Como","Garda");
printf(miastringa);
Provare per credere! Ed ecco qui l'implementazione:
int StrReplace(char *str, int maxstr, char *pattern, char *replace)
{
int i, j;
int lenstr = (int)strlen(str);
int lenpattern = (int)strlen(pattern);
int lenreplace = (int)strlen(replace);
int diff;
if ((lenstr - lenpattern + lenreplace) >= maxstr)
return -1; // not enough space
for (i = 0; i <= (lenstr - lenpattern); i++)
{
if (strncmp(&str[i], pattern, lenpattern) == 0) // if found
{
if (lenpattern == lenreplace)
{
strncpy(&str[i], replace, lenreplace);
return 1;
}
else if(lenpattern > lenreplace)
{
diff = lenpattern - lenreplace;
strncpy(&str[i], replace, lenreplace);
// compact
j = i + lenreplace;
for (;j<lenstr-diff;j++)
str[j] = str[j+diff];
str[j] = '\0';
return 1;
}
else // lensearch < lensubst
{
diff = lenreplace - lenpattern;
// expand
j = lenstr - lenpattern + lenreplace;
str[j] = '\0';
for(; j > i + lenpattern;j--)
str[j] = str[j - diff];
strncpy(&str[i], replace, lenreplace);
return 1;
}
}
}
return 0;
}
Alcune note sul funzionamento possono aiutare la comprensione.
In base alla lunghezza delle due stringhe, quella da cercare e quella da inserire, ci possono essere tre possibilità:
- se hanno la stessa lunghezza per la sostituzione ci basta una sovrascrittura;
- se la stringa da inserire è più lunga di quella esistente bisognerà copiare la nuova stringa e poi compattare la parte a destra;
- se la stringa da inserire è più lunga di quella esistente bisogna creare lo spazio espandendo la parte destra, per poi inserire la nuova sottostringa.