What is the function to replace string in C?

2018-12-31 17:51发布

Given a (char *) string, I want to find all occurrence of a substring and replace it with an alternate string. I do not see any simple function that achieves this in <string.h>

标签: c string
18条回答
春风洒进眼中
2楼-- · 2018-12-31 18:31

a fix to fann95's response, using in-place modification of the string, and assuming the buffer pointed to by line is large enough to hold the resulting string.

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);
}
查看更多
倾城一夜雪
3楼-- · 2018-12-31 18:31
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;
}
查看更多
与风俱净
4楼-- · 2018-12-31 18:32

Here is the one that I created based on these requirements:

  1. Replace the pattern regardless of whether is was long or shorter.

  2. Not use any malloc (explicit or implicit) to intrinsically avoid memory leaks.

  3. Replace any number of occurrences of pattern.

  4. Tolerate the replace string having a substring equal to the search string.

  5. Does not have to check that the Line array is sufficient in size to hold the replacement. e.g. This does not work unless the caller knows that line is of sufficient size to hold the new string.

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

Any suggestions for improving this code are cheerfully accepted. Just post the comment and I will test it.

查看更多
心情的温度
5楼-- · 2018-12-31 18:32
/*замена символа в строке*/
char* replace_char(char* str, char in, char out) {
    char * p = str;

    while(p != '\0') {
        if(*p == in)
            *p == out;
        ++p;
    }

    return str;
}
查看更多
回忆,回不去的记忆
6楼-- · 2018-12-31 18:32

You can use this function (the comments explain how it works):

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
    }
}
查看更多
冷夜・残月
7楼-- · 2018-12-31 18:32
// Replace every occurence of a in str with b

void strrepl(char *str, const char *a, const char *b) {
    for (char *cursor = str; (cursor = strstr(cursor, a)) != NULL;){
        memmove(cursor + strlen(b), cursor + strlen(a), strlen(cursor) - strlen(a) + 1);
        for (int i = 0; b[i] != '\0'; i++)
            cursor[i] = b[i];
        cursor += strlen(b);
    }
}

This is possibly the best you could do:

  • just 8 lines
  • just 1 temp pointer
  • in-place modification
  • works with arbitrary sized a and b char*
  • works for deletion

if you don't want in-place modification, or you have to work with a const char*, this is another version of the same function that returns a new char* with modifications done. (don't forget to free the return value as strdup() is doing a malloc behind the scene)

char* astrrepl(const char *str, const char *a, const char *b) {
    char* strd = strdup(str);
    for (char *cursor = strd; (cursor = strstr(cursor, a)) != NULL;){
        memmove(cursor + strlen(b), cursor + strlen(a), strlen(cursor) - strlen(a) + 1);
        for (int i = 0; b[i] != '\0'; i++)
            cursor[i] = b[i];
        cursor += strlen(b);
    }
    return strd;
}

Sample code :

int main(int argc, char const *argv[])
{
    char *a = strdup("Hello This Is Jack");
    char *b = astrrepl(a, " ", "~~~");
    printf("Out of place modification : %s\n", b);

    strrepl(a, "Jack", "Fourchette");
    printf("In place modification     : %s\n", a);
    return 0;
}

Output:

Out of place modification : Hello~~~This~~~Is~~~Jack
In place modification     : Hello This Is Fourchette
查看更多
登录 后发表回答