Что такое функция для замены строки в C? - PullRequest
81 голосов
/ 23 апреля 2009

Учитывая строку (char *), я хочу найти все вхождения подстроки и заменить ее альтернативной строкой. Я не вижу какой-либо простой функции, которая достигает этого в

Ответы [ 18 ]

1 голос
/ 05 июля 2016

Вы можете использовать эту функцию (комментарии объясняют, как она работает):

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
    }
}
1 голос
/ 02 августа 2015

Вот тот, который я создал на основе этих требований:

  1. Замена шаблона независимо от того, был ли он длинным или коротким.

  2. Не использовать malloc (явный или неявный) для искоренения утечек памяти.

  3. Заменить любое количество вхождений шаблона.

  4. Допустимая строка замены, имеющая подстроку, равную строке поиска.

  5. Не нужно проверять, достаточен ли размер массива Line для хранения замены. например Это не работает, если вызывающий не знает, что строка имеет достаточный размер для хранения новой строки.

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

Любые предложения по улучшению этого кода приветствуются. Просто оставьте комментарий, и я протестирую его.

0 голосов
/ 01 апреля 2019

Здесь мое, оно автономное и универсальное, а также эффективное, оно увеличивает или уменьшает буферы по мере необходимости в каждой рекурсии

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);
        }
    }
}
0 голосов
/ 18 ноября 2018

Эта функция работает только в том случае, если в строке есть дополнительное место для новой длины

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

Это только заменяет первое вхождение

0 голосов
/ 16 октября 2017
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;
}
0 голосов
/ 18 февраля 2016

Вот, пожалуйста ... эта функция заменяет каждое вхождение char x на char y в символьной строке 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;
}

Пример использования может быть

  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.

Функция из строковой библиотеки, которую я поддерживаю на Github , вы можете посмотреть другие доступные функции или даже внести свой вклад в код :)

https://github.com/fnoyanisi/zString

EDIT: @siride прав, функция выше заменяет только символы. Только что написал этот, который заменяет строки символов.

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

А ниже вывод

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'
0 голосов
/ 05 ноября 2015

исправление ответа fann95, использующее модификацию строки на месте и предполагающее, что буфер, на который указывает строка, достаточно велик для хранения результирующей строки.

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);
}
0 голосов
/ 22 декабря 2014
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;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...