Welke functie is om een ​​substring van een reeks in C te vervangen?

Een (char *) reeks, wil ik alle voorkomens van een substring vinden en vervangen door een alternatieve tekenreeks. Ik zie geen enkele eenvoudige functie die dit bereikt in <string.h>.


Antwoord 1, Autoriteit 100%

De optimizer zou de meeste lokale variabelen moeten elimineren. De TMP-aanwijzer is er om ervoor te zorgen dat StrCpy niet hoeft te lopen om de touw te lopen om de nul te vinden. TMP wijst naar het einde van het resultaat na elke oproep. (Zie Shlemiel het algoritme van de schilder voor waarom strCpy zich vervelend kan zijn.)

// 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;
}

Antwoord 2, autoriteit 17%

Dit is niet voorzien in de standaard C-bibliotheek, omdat je, met alleen een char*, het geheugen dat aan de string is toegewezen niet kunt vergroten als de vervangende string langer is dan de string die wordt vervangen.

Je kunt dit gemakkelijker doen met std::string, maar zelfs daar zal geen enkele functie het voor je doen.


Antwoord 3, autoriteit 13%

Er is er geen.

Je zou je eigen moeten rollen met iets als strstren strcat of strcpy.


Antwoord 4, autoriteit 12%

Je zou je eigen vervangfunctie kunnen bouwen met strstr om de substrings te vinden en strncpy om in delen naar een nieuwe buffer te kopiëren.

Tenzij wat u wilt replace_witheven lang is als wat u wilt replace, dan is het waarschijnlijk het beste om een nieuwe buffer te gebruiken om de nieuwe tekenreeks naar te kopiëren .


Antwoord 5, autoriteit 10%

Aangezien strings in C niet dynamisch kunnen groeien, zal vervanging over het algemeen niet werken. Daarom moet u ruimte toewijzen voor een nieuwe string die voldoende ruimte heeft voor uw vervanging en vervolgens de delen van het origineel plus de vervanging naar de nieuwe string kopiëren. Om de delen te kopiëren, gebruikt u strncpy.


Antwoord 6, autoriteit 9%

Hier is een voorbeeldcode die dit doet.

#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;
}

Antwoord 7, autoriteit 5%

// 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);
}

Antwoord 8, autoriteit 4%

De repl_str()-functie op creativeandcritical.net is snel en betrouwbaar. Op die pagina is ook een brede tekenreeksvariant, repl_wcs(), die kan worden gebruikt met Unicode-strings inclusief die gecodeerd in UTF-8, via helperfuncties – democode is gelinkt vanaf de pagina. Late volledige openbaarmaking: ik ben de auteur van die pagina en de functies erop.


Antwoord 9, autoriteit 3%

Ik vind het grootste deel van de voorgestelde functies moeilijk te begrijpen – dus ik bedacht hier:

static char *dull_replace(const char *in, const char *pattern, const char *by)
{
    size_t outsize = strlen(in) + 1;
    // TODO maybe avoid reallocing by counting the non-overlapping occurences of pattern
    char *res = malloc(outsize);
    // use this to iterate over the output
    size_t resoffset = 0;
    char *needle;
    while (needle = strstr(in, pattern)) {
        // copy everything up to the pattern
        memcpy(res + resoffset, in, needle - in);
        resoffset += needle - in;
        // skip the pattern in the input-string
        in = needle + strlen(pattern);
        // adjust space for replacement
        outsize = outsize - strlen(pattern) + strlen(by);
        res = realloc(res, outsize);
        // copy the pattern
        memcpy(res + resoffset, by, strlen(by));
        resoffset += strlen(by);
    }
    // copy the remaining input
    strcpy(res + resoffset, in);
    return res;
}

Uitgang moet vrij zijn


Antwoord 10, Autoriteit 2%

U kunt deze functie gebruiken (de opmerkingen verklaren hoe het werkt):

void strreplace(char *string, const char *find, const char *replaceWith){
    if(strstr(string, replaceWith) != NULL){
        char *temporaryString = malloc(strlen(strstr(string, find) + strlen(find)) + 1);
        strcpy(temporaryString, strstr(string, find) + strlen(find));    //Create a string with what's after the replaced part
        *strstr(string, find) = '\0';    //Take away the part to replace and the part after it in the initial string
        strcat(string, replaceWith);    //Concat the first part of the string with the part to replace with
        strcat(string, temporaryString);    //Concat the first part of the string with the part after the replaced part
        free(temporaryString);    //Free the memory to avoid memory leaks
    }
}

Antwoord 11

Dit is degene die ik heb gemaakt op basis van deze vereisten:

  1. Vervang het patroon, ongeacht of het lang of korter was.

  2. Gebruik geen malloc (expliciet of impliciet) om intrinsiek geheugenlekken te voorkomen.

  3. Vervang een willekeurig aantal keren dat het patroon voorkomt.

  4. Tolereer dat de vervangtekenreeks een subtekenreeks heeft die gelijk is aan de zoekreeks.

  5. Hoeft niet te controleren of de Line-array groot genoeg is om de vervanging te bevatten. bijv. Dit werkt niet tenzij de beller weet dat de lijn groot genoeg is om de nieuwe string te bevatten.

/* returns number of strings replaced.
*/
int replacestr(char *line, const char *search, const char *replace)
{
   int count;
   char *sp; // start of pattern
   //printf("replacestr(%s, %s, %s)\n", line, search, replace);
   if ((sp = strstr(line, search)) == NULL) {
      return(0);
   }
   count = 1;
   int sLen = strlen(search);
   int rLen = strlen(replace);
   if (sLen > rLen) {
      // move from right to left
      char *src = sp + sLen;
      char *dst = sp + rLen;
      while((*dst = *src) != '\0') { dst++; src++; }
   } else if (sLen < rLen) {
      // move from left to right
      int tLen = strlen(sp) - sLen;
      char *stop = sp + rLen;
      char *src = sp + sLen + tLen;
      char *dst = sp + rLen + tLen;
      while(dst >= stop) { *dst = *src; dst--; src--; }
   }
   memcpy(sp, replace, rLen);
   count += replacestr(sp + rLen, search, replace);
   return(count);
}

Suggesties voor het verbeteren van deze code worden met plezier aanvaard. Plaats gewoon de reactie en ik zal het testen.


Antwoord 12

een oplossing voor het antwoord van fann95, met behulp van in-place wijziging van de string, en ervan uitgaande dat de buffer waarnaar door de regel wordt verwezen groot genoeg is om de resulterende string te bevatten.

static void replacestr(char *line, const char *search, const char *replace)
{
     char *sp;
     if ((sp = strstr(line, search)) == NULL) {
         return;
     }
     int search_len = strlen(search);
     int replace_len = strlen(replace);
     int tail_len = strlen(sp+search_len);
     memmove(sp+replace_len,sp+search_len,tail_len+1);
     memcpy(sp, replace, replace_len);
}

Antwoord 13

Deze functie werkt alleen als je string extra ruimte heeft voor een nieuwe lengte

void replace_str(char *str,char *org,char *rep)
{
    char *ToRep = strstr(str,org);
    char *Rest = (char*)malloc(strlen(ToRep));
    strcpy(Rest,((ToRep)+strlen(org)));
    strcpy(ToRep,rep);
    strcat(ToRep,Rest);
    free(Rest);
}

Dit vervangt alleen het eerste exemplaar


Antwoord 14

Hier komt de mijne, maak ze allemaal char*, wat het bellen makkelijker maakt…

char *strrpc(char *str,char *oldstr,char *newstr){
    char bstr[strlen(str)];
    memset(bstr,0,sizeof(bstr));
    int i;
    for(i = 0;i < strlen(str);i++){
        if(!strncmp(str+i,oldstr,strlen(oldstr))){
            strcat(bstr,newstr);
            i += strlen(oldstr) - 1;
        }else{
                strncat(bstr,str + i,1);
            }
    }
    strcpy(str,bstr);
    return str;
}

Antwoord 15

U kunt strrep() gebruiken

char* strrep ( const char * cadena,
const char * strf,
const char * str
)

strrep (tekenreeks vervangen). Vervangt ‘strf’ door ‘strr’ in ‘cadena’ en retourneert de nieuwe string. Je moet de geretourneerde string in je code vrijmaken nadat je strrep hebt gebruikt.

Parameters
cadena De string met de tekst.
strf De tekst die moet worden gevonden.
strr De vervangende tekst.

Retourneren
De tekst bijgewerkt met de vervanging.

Het project is te vinden op https://github.com/ipserc/strrep


Antwoord 16

Daar ga je….dit is de functie om elk voorkomen van char xte vervangen door char ybinnen tekenreeks str

char *zStrrep(char *str, char x, char y){
    char *tmp=str;
    while(*tmp)
        if(*tmp == x)
            *tmp++ = y; /* assign first, then incement */
        else
            *tmp++;
    *tmp='\0';
    return str;
}

Een voorbeeld van gebruik kan zijn

 Exmaple Usage
        char s[]="this is a trial string to test the function.";
        char x=' ', y='_';
        printf("%s\n",zStrrep(s,x,y));
  Example Output
        this_is_a_trial_string_to_test_the_function.

De functie komt uit een stringbibliotheek die ik op Github onderhoud, je bent meer dan welkom om een kijk naar andere beschikbare functies of draag zelfs bij aan de code 🙂

https://github.com/fnoyanisi/zString

BEWERKEN:
@siride heeft gelijk, de functie hierboven vervangt alleen tekens. Ik heb net deze geschreven, die tekenreeksen vervangt.

#include <stdio.h>
#include <stdlib.h>
/* replace every occurance of string x with string y */
char *zstring_replace_str(char *str, const char *x, const char *y){
    char *tmp_str = str, *tmp_x = x, *dummy_ptr = tmp_x, *tmp_y = y;
    int len_str=0, len_y=0, len_x=0;
    /* string length */
    for(; *tmp_y; ++len_y, ++tmp_y)
        ;
    for(; *tmp_str; ++len_str, ++tmp_str)
        ;
    for(; *tmp_x; ++len_x, ++tmp_x)
        ;
    /* Bounds check */
    if (len_y >= len_str)
        return str;
    /* reset tmp pointers */
    tmp_y = y;
    tmp_x = x;
    for (tmp_str = str ; *tmp_str; ++tmp_str)
        if(*tmp_str == *tmp_x) {
            /* save tmp_str */
            for (dummy_ptr=tmp_str; *dummy_ptr == *tmp_x; ++tmp_x, ++dummy_ptr)
                if (*(tmp_x+1) == '\0' && ((dummy_ptr-str+len_y) < len_str)){
                /* Reached end of x, we got something to replace then!
                * Copy y only if there is enough room for it
                */
                    for(tmp_y=y; *tmp_y; ++tmp_y, ++tmp_str)
                        *tmp_str = *tmp_y;
            }
        /* reset tmp_x */
        tmp_x = x;
        }
    return str;
}
int main()
{
    char s[]="Free software is a matter of liberty, not price.\n"
             "To understand the concept, you should think of 'free' \n"
             "as in 'free speech', not as in 'free beer'";
    printf("%s\n\n",s);
    printf("%s\n",zstring_replace_str(s,"ree","XYZ"));
    return 0;
}

En hieronder is de uitvoer

Free software is a matter of liberty, not price.
To understand the concept, you should think of 'free' 
as in 'free speech', not as in 'free beer'
FXYZ software is a matter of liberty, not price.
To understand the concept, you should think of 'fXYZ' 
as in 'fXYZ speech', not as in 'fXYZ beer'

Antwoord 17

/*замена символа в строке*/
char* replace_char(char* str, char in, char out) {
    char * p = str;
    while(p != '\0') {
        if(*p == in)
            *p == out;
        ++p;
    }
    return str;
}

Antwoord 18

DWORD ReplaceString(__inout PCHAR source, __in DWORD dwSourceLen, __in const char* pszTextToReplace, __in const char* pszReplaceWith)
{
    DWORD dwRC = NO_ERROR;
    PCHAR foundSeq = NULL;
    PCHAR restOfString = NULL;
    PCHAR searchStart = source;
    size_t szReplStrcLen = strlen(pszReplaceWith), szRestOfStringLen = 0, sztextToReplaceLen = strlen(pszTextToReplace), remainingSpace = 0, dwSpaceRequired = 0;
    if (strcmp(pszTextToReplace, "") == 0)
        dwRC = ERROR_INVALID_PARAMETER;
    else if (strcmp(pszTextToReplace, pszReplaceWith) != 0)
    {
        do
        {
            foundSeq = strstr(searchStart, pszTextToReplace);
            if (foundSeq)
            {
                szRestOfStringLen = (strlen(foundSeq) - sztextToReplaceLen) + 1;
                remainingSpace = dwSourceLen - (foundSeq - source);
                dwSpaceRequired = szReplStrcLen + (szRestOfStringLen);
                if (dwSpaceRequired > remainingSpace)
                {
                    dwRC = ERROR_MORE_DATA;
                }
                else
                {
                    restOfString = CMNUTIL_calloc(szRestOfStringLen, sizeof(CHAR));
                    strcpy_s(restOfString, szRestOfStringLen, foundSeq + sztextToReplaceLen);
                    strcpy_s(foundSeq, remainingSpace, pszReplaceWith);
                    strcat_s(foundSeq, remainingSpace, restOfString);
                }
                CMNUTIL_free(restOfString);
                searchStart = foundSeq + szReplStrcLen; //search in the remaining str. (avoid loops when replWith contains textToRepl 
            }
        } while (foundSeq && dwRC == NO_ERROR);
    }
    return dwRC;
}

Antwoord 19

char *replace(const char*instring, const char *old_part, const char *new_part)
{
#ifndef EXPECTED_REPLACEMENTS
    #define EXPECTED_REPLACEMENTS 100
#endif
    if(!instring || !old_part || !new_part)
    {
        return (char*)NULL;
    }
    size_t instring_len=strlen(instring);
    size_t new_len=strlen(new_part);
    size_t old_len=strlen(old_part);
    if(instring_len<old_len || old_len==0)
    {
        return (char*)NULL;
    }
    const char *in=instring;
    const char *found=NULL;
    size_t count=0;
    size_t out=0;
    size_t ax=0;
    char *outstring=NULL;
    if(new_len> old_len )
    {
        size_t Diff=EXPECTED_REPLACEMENTS*(new_len-old_len);
        size_t outstring_len=instring_len + Diff;
        outstring =(char*) malloc(outstring_len); 
        if(!outstring){
            return (char*)NULL;
        }
        while((found = strstr(in, old_part))!=NULL)
        {
            if(count==EXPECTED_REPLACEMENTS)
            {
                outstring_len+=Diff;
                if((outstring=realloc(outstring,outstring_len))==NULL)
                {
                     return (char*)NULL;
                }
                count=0;
            }
            ax=found-in;
            strncpy(outstring+out,in,ax);
            out+=ax;
            strncpy(outstring+out,new_part,new_len);
            out+=new_len;
            in=found+old_len;
            count++;
        }
    }
    else
    {
        outstring =(char*) malloc(instring_len);
        if(!outstring){
            return (char*)NULL;
        }
        while((found = strstr(in, old_part))!=NULL)
        {
            ax=found-in;
            strncpy(outstring+out,in,ax);
            out+=ax;
            strncpy(outstring+out,new_part,new_len);
            out+=new_len;
            in=found+old_len;
        }
    }
    ax=(instring+instring_len)-in;
    strncpy(outstring+out,in,ax);
    out+=ax;
    outstring[out]='\0';
    return outstring;
}

Antwoord 20

Hier gaat de mijne, het is zelfstandig en veelzijdig, evenals efficiënt, het groeit of krimpt buffers zoals nodig in elke recursie

void strreplace(char *src, char *str, char *rep)
{
    char *p = strstr(src, str);
    if (p)
    {
        int len = strlen(src)+strlen(rep)-strlen(str);
        char r[len];
        memset(r, 0, len);
        if ( p >= src ){
            strncpy(r, src, p-src);
            r[p-src]='\0';
            strncat(r, rep, strlen(rep));
            strncat(r, p+strlen(str), p+strlen(str)-src+strlen(src));
            strcpy(src, r);
            strreplace(p+strlen(rep), str, rep);
        }
    }
}

Antwoord 21

Gebruik alleen strlen van string.h

Sorry voor mijn Engels

char * str_replace(char * text,char * rep, char * repw){//text -> to replace in it | rep -> replace | repw -> replace with
    int replen = strlen(rep),repwlen = strlen(repw),count;//some constant variables
    for(int i=0;i<strlen(text);i++){//search for the first character from rep in text
        if(text[i] == rep[0]){//if it found it
            count = 1;//start searching from the next character to avoid repetition
            for(int j=1;j<replen;j++){
                if(text[i+j] == rep[j]){//see if the next character in text is the same as the next in the rep if not break
                    count++;
                }else{
                    break;
                }
            }
            if(count == replen){//if count equals to the lenght of the rep then we found the word that we want to replace in the text
                if(replen < repwlen){
                    for(int l = strlen(text);l>i;l--){//cuz repwlen greater than replen we need to shift characters to the right to make space for the replacement to fit
                        text[l+repwlen-replen] = text[l];//shift by repwlen-replen
                    }
                }
                if(replen > repwlen){
                    for(int l=i+replen-repwlen;l<strlen(text);l++){//cuz replen greater than repwlen we need to shift the characters to the left
                        text[l-(replen-repwlen)] = text[l];//shift by replen-repwlen
                    }
                    text[strlen(text)-(replen-repwlen)] = '\0';//get rid of the last unwanted characters
                }
                for(int l=0;l<repwlen;l++){//replace rep with repwlen
                    text[i+l] = repw[l];
                }
                if(replen != repwlen){
                    i+=repwlen-1;//pass to the next character | try text "y" ,rep "y",repw "yy" without this line to understand
                }
            }
        }
    }
    return text;
}

als je wilt dat strlen-code string.h niet aanroept

int strlen(char * string){//use this code to avoid calling string.h
    int lenght = 0;
    while(string[lenght] != '\0'){
        lenght++;
    }
    return lenght;
}

Other episodes