Die folgende Replace Funktion führt eine einfache Stringersetzung durch, für Anwendungsfälle bei denen keine zeit- und rechenintensiven regulären Ausdrücke benötigt werden.
Ausgabe:
C:
#include <stdio.h>
#include <stdlib.h> // Replace
#include <string.h> // Replace
/** \brief Sucht alle Vorkommen eines Teilstrings und ersetzt sie.
* \param str Ursprünglicher String.
* \param search Der zu suchende und zu ersetzende Teilstring.
* \param repl Der String, der den gesuchten Teilstring ersetzt. (darf NULL sein)
* \param pLen Pointer auf eine Variable vom Typ size_t, die die neue Länge zugewiesen bekommt. (darf NULL sein)
* \return Allokierter Puffer, der den geänderten String enthält.
* NULL wird zurückgegeben, wenn die Speicherallokation fehlgeschlagen ist
* oder wenn NULL an einen der ersten beiden Parameter übergeben wurde
* oder wenn search die Länge 0 hat. */
char *Replace(const char *const str, const char *const search, const char *const repl, size_t *const pLen)
{
if (pLen)
*pLen = 0U;
if (!str || !search)
return NULL;
const size_t searchLen = strlen(search);
if (!searchLen)
return NULL;
const size_t strLen = strlen(str),
replLen = repl ? strlen(repl) : (size_t)0U;
size_t currentLen = 0,
capacity = ((strLen > replLen ? strLen : replLen) << 1) + 512U; // Aus Performancegründen werden mehr als 512 Bytes vorab allokiert.
char *buf = NULL, *bufIt = NULL;
if (!(buf = bufIt = (char*)malloc(capacity)))
return NULL;
const char *strIt = str;
for (const char *found = NULL; (found = strstr(strIt, search));)
{
const size_t difLen = (size_t)(found - strIt);
if (currentLen + difLen + replLen + 1U > capacity)
{
char *tmp = (char*)realloc(buf, (capacity <<= 1));
if (!tmp)
{
free(buf);
return NULL;
}
buf = tmp;
bufIt = buf + currentLen;
}
bufIt = strcpy(strncpy(bufIt, strIt, difLen) + difLen, repl ? repl : "") + replLen;
strIt = found + searchLen;
currentLen += difLen + replLen;
}
const size_t total = currentLen + (size_t)(str + strLen - strIt) + 1U;
if (total > capacity)
{
char *tmp = realloc(buf, total);
if (!tmp)
{
free(buf);
return NULL;
}
buf = tmp;
bufIt = buf + currentLen;
}
strcpy(bufIt, strIt);
if (pLen)
*pLen = total - 1U;
return buf;
}
int main(void)
{
size_t length = 0;
const char str[] = "xxx aaa xxx bbb xxx ccc xxx";
char *updated = Replace(str, "xxx", "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ", &length); // Ersetzung von "xxx".
if (!updated) return 1;
printf("String:\n\"%s\"\nLaenge:\n%u\n\n", updated, (unsigned)length);
free(updated);
updated = Replace(str, "xxx", NULL, &length); // Eliminierung von "xxx".
if (!updated) return 1;
printf("String:\n\"%s\"\nLaenge:\n%u\n\n", updated, (unsigned)length);
free(updated);
updated = Replace(str, "foo", "bar", &length); // "foo" wird nicht gefunden, der zurückgegebene String ist somit eine Kopie des Originals.
if (!updated) return 1;
printf("String:\n\"%s\"\nLaenge:\n%u\n\n", updated, (unsigned)length);
free(updated);
return 0;
}
Ausgabe:
Code:
String:
"ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ aaa ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ bbb ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ ccc ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ"
Laenge:
135
String:
" aaa bbb ccc "
Laenge:
15
String:
"xxx aaa xxx bbb xxx ccc xxx"
Laenge:
27