Рекурсивная строка C заменяет - PullRequest
3 голосов
/ 02 июля 2011

Я довольно новичок в программировании на C, раньше использовал C ++ только с классом String, но мне интересно, как бы я сделал рекурсивную замену строки другой строкой.

Myкод такой, но он, кажется, не работает правильно, и я не могу точно определить, где он не работает.Он отлично работает на одной замене, но более чем на одной и не работает.

#include <stdio.h>
#include <string.h>

char *replace_str(char *str, char *orig, char *rep)
{
    int current_index = 0;
    static char buffer[10000];

    if (!strstr(str, orig))  // Is 'orig' even in 'str'?
    {
        return str;
    }

    while (1)
    {        
        char *p;

        if (!(p = strstr(str + current_index, orig)))  // Is 'orig' even in 'str'?
        {
            return buffer;
        }

        strncpy(buffer, str, p-str); // Copy characters from 'str' start to 'orig' st$
        buffer[p-str] = '\0';

        sprintf(buffer+(p-str), "%s%s", rep, p+strlen(orig));


        printf("%d -> %s\n", current_index, buffer);

        current_index = (p - str) + strlen(rep);

        str = buffer;
    }

    return buffer;
}

int main(void)
{
    puts(replace_str("hello world world", "world", "world2"));

    return 0;
}

В этом примере он печатает:

 0 -> hello world2 world
12 -> hello world2 world22
hello world2 world22

Ответы [ 3 ]

5 голосов
/ 02 июля 2011

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

О вашем коде.Во-первых, лучше, чтобы вызывающая сторона предоставляла свой буфер dest вместо наличия статического буфера в функции.Тогда вы не проверяете переполнение буфера.

Ваш

    strncpy(buffer, str, p-str); // Copy characters from 'str' start to 'orig' st$

будет копировать из A в A, за исключением первой итерации.Это не хорошо, буфер не должен перекрываться.Вместо этого используйте memmove.

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

В какой-то момент вы перезаписываете ввод (когда strи буфер указывает на то же самое) потеря информации, так как ваше заменяющее слово длиннее оригинала, подлежащего замене, поэтому вы не сохраняете «следующий оригинальный символ».(Если вы попытаетесь использовать «work» вместо «world2», это должно сработать) ...

Таким образом, ваш current_index должен индексировать исходную строку str (и вы никогда не будете выполнять str = buffer), и выдобавит к вашему внутреннему буферу нужную вам часть (до появления «world», если найден, затем добавьте «world2», обновите current_index по длине «world» и продолжите).

Я бы сделал(пытаясь сохранить исходную идею, более или менее)

#include <stdio.h>
#include <string.h>

char *replace_str(char *str, const char *orig, const char *rep)
{
    size_t buf_index = 0;
    static char buffer[10000];

    if (!strstr(str, orig))  // Is 'orig' even in 'str'?
    {
        return str;
    }

    buffer[0] = 0;
    for(;;)
    {        
        char *p;

        if (!(p = strstr(str, orig)))  
        {
           strcpy(buffer + buf_index, str);
           return buffer;
        }
        strncpy(buffer + buf_index, str, p - str);
        strcpy(buffer + buf_index + (p - str), rep);
        buf_index += (p-str) + strlen(rep);
        str = p + strlen(orig);
    }
    return buffer;
}

int main(void)
{
    puts(replace_str("hello world world world", "wor", "world2"));
    return 0;
}
2 голосов
/ 02 июля 2011

Проблема str = buffer;. Вы эффективно меняете исходный указатель, и это портит ваш код.

Используйте приведенный ниже код перед началом цикла while

 char bk[100]
 strcpy(bk,str);

и замените все вхождения str в цикле while на bk. Это будет работать.

0 голосов
/ 29 февраля 2012

используйте эту рекурсивную функцию rplcStr (), она закодирована как простая замена c ++.

string rplcStr(string x, string y, string z){
// Done by Raafat Maurice in 29 Feb 2012
// this function will replace all string (y) found in string (x) by the string (z).
        if (x.find(y.c_str(),0) != -1 ) {
            return (rplcStr (x.substr(0,  x.find(y.c_str(),0) ) + z + x.substr( x.find(y.c_str(),0) + y.size()  ) ,y,z));
        }
        else {
            return (x);
        }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...