Angenommen (char *
) string möchte ich alle Vorkommen einer Teilzeichenfolge finden und sie durch eine alternative Zeichenfolge ersetzen. Ich sehe keine einfache Funktion, die dies in erreicht <string.h>
.
Welche Funktion soll einen Teilstring aus einem String in C ersetzen?
jmucchiello
Der Optimierer sollte die meisten lokalen Variablen eliminieren. Der tmp-Zeiger ist da, um sicherzustellen, dass strcpy den String nicht durchlaufen muss, um die Null zu finden. tmp zeigt nach jedem Aufruf auf das Ergebnisende. (Sehen Der Algorithmus von Shlemiel dem Maler warum strcpy nervig sein kann.)
// You must free the result if result is non-NULL.
char *str_replace(char *orig, char *rep, char *with) {
char *result; // the return string
char *ins; // the next insert point
char *tmp; // varies
int len_rep; // length of rep (the string to remove)
int len_with; // length of with (the string to replace rep with)
int len_front; // distance between rep and end of last rep
int count; // number of replacements
// sanity checks and initialization
if (!orig || !rep)
return NULL;
len_rep = strlen(rep);
if (len_rep == 0)
return NULL; // empty rep causes infinite loop during count
if (!with)
with = "";
len_with = strlen(with);
// count the number of replacements needed
ins = orig;
for (count = 0; tmp = strstr(ins, rep); ++count) {
ins = tmp + len_rep;
}
tmp = result = malloc(strlen(orig) + (len_with - len_rep) * count + 1);
if (!result)
return NULL;
// first time through the loop, all the variable are set correctly
// from here on,
// tmp points to the end of the result string
// ins points to the next occurrence of rep in orig
// orig points to the remainder of orig after "end of rep"
while (count--) {
ins = strstr(orig, rep);
len_front = ins - orig;
tmp = strncpy(tmp, orig, len_front) + len_front;
tmp = strcpy(tmp, with) + len_with;
orig += len_front + len_rep; // move to next "end of rep"
}
strcpy(tmp, orig);
return result;
}
-
@jmucchiello: verwenden
size_t
Anstatt vonint
für beliebige Objekt-/String-Größen und Indizes in sie hinein. Auch, was ist der Zweck vonstrcpy(tmp, orig);
ganz am Ende? Es scheint falsch.– Alexey Frunze
1. Dezember 2011 um 14:18 Uhr
-
@Alex, das letzte strcpy(tmp,orig) kopiert den letzten Teil der Zeichenfolge an das Ziel. Bsp.: replace(“abab”,”a”,”c”) am Ende der Schleife, Ergebnis enthält “cbc” und orig zeigt auf das letzte “b” in “abab”. Das letzte strcpy hängt das „b“ an, sodass die zurückgegebene Zeichenfolge „cbcb“ ist. Wenn nichts mehr zu kopieren ist, sollte orig auf die ASCIIZ der Eingabezeichenfolge zeigen.
– Jmucchiello
4. Dezember 2011 um 0:07 Uhr
-
Vereinfachung: Sie können das zuerst ersetzen
for
Schleife mitfor (count = 1; ins = strstr(ins + rep_len, rep); ++count) {}
danntmp
wird nur zum Schreiben verwendet.– Rapunzel
9. März 2013 um 1:28 Uhr
-
char *done = replace(“abcdefghijkl”, “bc”, “yz”); Sachen machen(); frei (erledigt);
– Jmucchiello
16. Mai 2013 um 19:23 Uhr
-
Seien Sie gewarnt, dass diese Funktion NULL zurückgibt, wenn es keine zu ersetzenden Vorkommen gibt ( if (!(ins = strstr(orig, rep))) return NULL; ). Sie können nicht einfach die Ausgabe verwenden, Sie müssen prüfen, ob die Ausgabe NULL ist, und wenn ja, verwenden Sie die ursprüngliche Zeichenfolge (kopieren Sie nicht einfach den Zeiger auf die Ergebniszeichenfolge, da free(result) dann die ursprüngliche Zeichenfolge freigibt). Die Verwendung ist einfacher, wenn die Eingabezeichenfolge nur in die Ausgabezeichenfolge kopiert wird, wenn nichts zu ersetzen ist.
– Nachteil
17. Mai 2013 um 16:35 Uhr
Dies ist in der Standard-C-Bibliothek nicht vorgesehen, da Sie bei nur einem char* den der Zeichenfolge zugewiesenen Speicher nicht erhöhen können, wenn die Ersatzzeichenfolge länger als die zu ersetzende Zeichenfolge ist.
Sie können dies einfacher mit std::string tun, aber selbst dort wird es keine einzelne Funktion für Sie tun.
-
Diese Frage bezieht sich auf C, nicht auf C++.
– Geremia
8. August 2016 um 16:53 Uhr
-
1/ strlen(char*)+1 ist nicht unbedingt gleich der Speichergröße. 2/ Es gibt viele N-Versionen von String-Funktionen, die einen zusätzlichen Parameter für die Puffergröße erhalten, also gibt es keinen Grund, warum es kein snreplace() geben könnte. 3/ Es könnte eine In-Place-Replace- und keine In-Place-Replace-Funktion geben. 4/ Wie funktioniert sprintf deiner Meinung nach? Es hat ein char*-Argument und muss die Speicherzuweisung nicht erhöhen, also kein Grund, warum ein Ersetzen nicht auch funktionieren könnte … (obwohl C ein schlechtes “String” -Design hat und die Puffergröße immer übergeben werden sollte mit dem Zeiger => snprintf)
– Steven Funke
12. März 2019 um 17:43 Uhr
Es gibt keinen.
Sie müssten Ihre eigenen mit so etwas wie rollen Strstr und strcat oder strcpy.
-
Wo werden Fansammlungen häufig verwendeter Funktionen gespeichert? Sicherlich gibt es dafür schon eine Bibliothek….
– Schrittmacher
3. Januar 2015 um 7:30 Uhr
-
strcat()
ist ein schlechter Vorschlag.– Iharob Al Asimi
3. Oktober 2015 um 14:39 Uhr
Brian R. Bondy
Sie könnten Ihre eigene Ersetzungsfunktion erstellen, indem Sie strstr verwenden, um die Teilzeichenfolgen zu finden, und strncpy, um Teile in einen neuen Puffer zu kopieren.
Es sei denn, was Sie wollen replace_with
ist die gleiche Länge wie das, was Sie wollen replace
dann ist es wahrscheinlich am besten, einen neuen Puffer zu verwenden, um die neue Zeichenfolge zu kopieren.
Da Zeichenfolgen in C nicht dynamisch wachsen können, funktioniert die Substitution im Allgemeinen nicht. Daher müssen Sie Platz für eine neue Zeichenfolge zuweisen, die genügend Platz für Ihre Ersetzung bietet, und dann die Teile des Originals plus die Ersetzung in die neue Zeichenfolge kopieren. Um die Teile zu kopieren, die Sie verwenden würden streng.
-
Die Puffergröße könnte größer sein als die Strlen, die Ersetzungszeichenfolge könnte kleiner als die ersetzte Zeichenfolge sein … daher müssen Sie keinen Speicher zuweisen, um eine Ersetzung durchzuführen. (Auch auf Mikrocontrollern haben Sie möglicherweise keinen unendlichen Speicher, und Sie müssen möglicherweise eine Ersetzung an Ort und Stelle durchführen. Alles in einen neuen Puffer kopieren ist möglicherweise nicht die richtige Lösung für alle …)
– Steven Funke
12. März 2019 um 17:49 Uhr
Rapunzel
Hier ist ein Beispielcode, der es tut.
#include <string.h>
#include <stdlib.h>
char * replace(
char const * const original,
char const * const pattern,
char const * const replacement
) {
size_t const replen = strlen(replacement);
size_t const patlen = strlen(pattern);
size_t const orilen = strlen(original);
size_t patcnt = 0;
const char * oriptr;
const char * patloc;
// find how many times the pattern occurs in the original string
for (oriptr = original; patloc = strstr(oriptr, pattern); oriptr = patloc + patlen)
{
patcnt++;
}
{
// allocate memory for the new string
size_t const retlen = orilen + patcnt * (replen - patlen);
char * const returned = (char *) malloc( sizeof(char) * (retlen + 1) );
if (returned != NULL)
{
// copy the original string,
// replacing all the instances of the pattern
char * retptr = returned;
for (oriptr = original; patloc = strstr(oriptr, pattern); oriptr = patloc + patlen)
{
size_t const skplen = patloc - oriptr;
// copy the section until the occurence of the pattern
strncpy(retptr, oriptr, skplen);
retptr += skplen;
// copy the replacement
strncpy(retptr, replacement, replen);
retptr += replen;
}
// copy the rest of the string.
strcpy(retptr, oriptr);
}
return returned;
}
}
#include <stdio.h>
int main(int argc, char * argv[])
{
if (argc != 4)
{
fprintf(stderr,"usage: %s <original text> <pattern> <replacement>\n", argv[0]);
exit(-1);
}
else
{
char * const newstr = replace(argv[1], argv[2], argv[3]);
if (newstr)
{
printf("%s\n", newstr);
free(newstr);
}
else
{
fprintf(stderr,"allocation error\n");
exit(-2);
}
}
return 0;
}
-
Die Puffergröße könnte größer sein als die Strlen, die Ersetzungszeichenfolge könnte kleiner als die ersetzte Zeichenfolge sein … daher müssen Sie keinen Speicher zuweisen, um eine Ersetzung durchzuführen. (Auch auf Mikrocontrollern haben Sie möglicherweise keinen unendlichen Speicher, und Sie müssen möglicherweise eine Ersetzung an Ort und Stelle durchführen. Alles in einen neuen Puffer kopieren ist möglicherweise nicht die richtige Lösung für alle …)
– Steven Funke
12. März 2019 um 17:49 Uhr
// Here is the code for unicode strings!
int mystrstr(wchar_t *txt1,wchar_t *txt2)
{
wchar_t *posstr=wcsstr(txt1,txt2);
if(posstr!=NULL)
{
return (posstr-txt1);
}else
{
return -1;
}
}
// assume: supplied buff is enough to hold generated text
void StringReplace(wchar_t *buff,wchar_t *txt1,wchar_t *txt2)
{
wchar_t *tmp;
wchar_t *nextStr;
int pos;
tmp=wcsdup(buff);
pos=mystrstr(tmp,txt1);
if(pos!=-1)
{
buff[0]=0;
wcsncpy(buff,tmp,pos);
buff[pos]=0;
wcscat(buff,txt2);
nextStr=tmp+pos+wcslen(txt1);
while(wcslen(nextStr)!=0)
{
pos=mystrstr(nextStr,txt1);
if(pos==-1)
{
wcscat(buff,nextStr);
break;
}
wcsncat(buff,nextStr,pos);
wcscat(buff,txt2);
nextStr=nextStr+pos+wcslen(txt1);
}
}
free(tmp);
}
Ich bezweifle, dass Sie dies auf veränderliche Weise tun können
– Benutzer44511
23. April 2009 um 0:50 Uhr