Ошибка сегментации при замене подстрок строки другой подстрокой - PullRequest
0 голосов
/ 21 октября 2011

У меня есть строка "{" 1 ":" [4,11,14,19,20,18,27] "}".Я хочу изменить его на "{\" 1 \ ": \" 4,11,14,19,20,18,27 \ "}".

Ниже мой код:

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

char *replace (char *this, char *withthat, char *inthis) {
    char *where = inthis;

    while ((where = strstr(where, this))) {
        memcpy(where, withthat, strlen(withthat));
        memmove(where+strlen(withthat),where+strlen(this), strlen(where+strlen(this))+1);
    }
    return inthis;
}

int main(void) {
    char string[] = "{&quot;1&quot;:&quot;[4,11,14,19,20,18,27]&quot;}";
    printf("%s\n", replace("&quot;", "\\\"", string));
    printf("%s\n", replace("\"[" , "\"", string));
    printf("%s\n", replace("]\\" , "\\", string));
    printf("%s\n", replace("{" , "\"{", string));
    printf("%s\n", replace("}" , "}\"", string));
    return 0;
}

Я получаю ошибку за последние два вызова замены.Мой o / p - {\ "1 \": \ "[4,11,14,19,20,18,27] \"} {\ "1 \": \ "4,11,14,19,20, 18,27] \ "} {\" 1 \ ": \" 4,11,14,19,20,18,27 \ "} Ошибка сегментации

Я пытался выполнить GDB, но не смогнайти основную причину ошибки.это как-то связано с memcopy, но не в состоянии понять.Если кто-нибудь может мне помочь, было бы здорово.Заранее спасибо.

Ответы [ 5 ]

1 голос
/ 21 октября 2011
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

char *replace (char *old, char *new, char *buff) {
    char *ptr;
    size_t oldlen = strlen(old);
    size_t newlen = strlen(new);

    for(ptr=buff; ptr = strstr(ptr, old); ptr += newlen) {
        memmove(ptr+newlen, ptr+oldlen, strlen(ptr+oldlen)+1);
        memcpy(ptr, new, newlen);
    }
    return buff;
}

int main(void) {
    char string[1234] = "{&quot;1&quot;:&quot;[4,11,14,19,20,18,27]&quot;}";
    printf("%s\n", replace("&quot;", "\\\"", string));
    printf("%s\n", replace("\"[" , "\"", string));
    printf("%s\n", replace("]\\" , "\\", string));
    printf("%s\n", replace("{" , "\"{", string));
    printf("%s\n", replace("}" , "}\"", string));

    return 0;
}

Последние две замены "{}" содержат себя. Это приводит к повторному сканированию исходной строки в том же месте с повторным сопоставлением + повторной заменой. В бесконечности. Ptr + = newlen избегает этого.

1 голос
/ 21 октября 2011

Ваша замещающая строка длиннее входной, но когда вы выделяете string, в ней есть только место для размера ввода плюс терминатор NUL.Когда вы пытаетесь расширить его, вы переполняете буфер, и система отключает вас (хотя это может позволить вам с небольшим переполнением, таким как округление выделения до следующего кратного 4 или, может быть, 8.

Чтобы решить эту проблему, вы (вероятно) хотите выяснить максимальную величину, на которую может вырасти ваша строка, выделить этот большой размер строки и использовать ее для результата.

Редактировать: например,рассмотрим вашу последнюю замену, изменив } на }". Это удваивает длину найденной подстроки. В качестве действительно простой оценки наихудшего случая, давайте предположим, что весь ввод целиком состоит из }. В этом случаерезультат будет вдвое длиннее входного, поэтому нам нужно выделить strlen(input)*2+1 байт для результата.

В вашем случае последние четыре замены (как минимум) являются взаимоисключающими (например,входные данные не могут быть { и } и [ и ] одновременно), поэтому удвоения длины будет достаточно, чтобы охватить все из них.

0 голосов
/ 21 октября 2011

Если withthat длиннее, чем этот, то ваш memcpy перезаписывает часть строки, которая идет после замены. В этом случае вам придется сделать memmove перед memcpy.

0 голосов
/ 21 октября 2011

Ваш порядок действий неправильный.Вы должны сначала освободить место для строки замены, и , чем вставить замену.(дано достаточно места).Кроме того, вы можете рассчитать strlen () заранее, так как они не меняются.(кроме случаев, когда они используются только один раз)

0 голосов
/ 21 октября 2011

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

...