Welche Funktion soll einen Teilstring aus einem String in C ersetzen?

Lesezeit: 7 Minuten

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>.

  • Ich bezweifle, dass Sie dies auf veränderliche Weise tun können

    – Benutzer44511

    23. April 2009 um 0:50 Uhr

Benutzeravatar von jmucchiello
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 von int für beliebige Objekt-/String-Größen und Indizes in sie hinein. Auch, was ist der Zweck von strcpy(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 mit for (count = 1; ins = strstr(ins + rep_len, rep); ++count) {}dann tmp 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

Benutzeravatar von Brian R. Bondy
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 replacedann 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

Benutzeravatar von rampion
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);
}

1422030cookie-checkWelche Funktion soll einen Teilstring aus einem String in C ersetzen?

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy