C -字符数组似乎可以复制,但只在循环范围内



现在,我正试图通过编写一个函数来熟悉C,给定一个字符串,将用一个新的子字符串替换目标子字符串的所有实例。但是,我遇到了一个重新分配char*数组的问题。在我看来,似乎我能够在主循环结束时成功地将数组string重新分配到所需的新大小,然后执行strcpy以更新的字符串填充它。但是,对于以下场景,它会失败:

字符串的原始输入:"use the restroom. "然后我需要"
目标替换:"the"(不区分大小写)
期望替换值:"th "

在循环的末尾,行printf("result: %sn ",string);打印出正确的短语"use the’restroom"。然后我需要。然而,string似乎会自我重置:在while()语句中对strcasestr的调用成功,循环开始的行printf("string: %s n",string);打印原始输入字符串,循环无限地继续下去。

任何想法都将非常感激(我提前为我的调试printf语句道歉)。谢谢!

函数的代码如下:

int replaceSubstring(char *string, int strLen, char*oldSubstring,
    int oldSublen, char*newSubstring, int newSublen )
{
    printf("Starting replacen");
    char* strLoc;
    while((strLoc = strcasestr(string, oldSubstring)) != NULL )
    {
        printf("string: %s n",string);
        printf("%d",newSublen);
        char *newBuf = (char *) malloc((size_t)(strLen +
            (newSublen - oldSublen)));
        printf("got newbufn");
        int stringIndex = 0;
        int newBufIndex = 0;
        char c;
        while(true)
        {
            if(stringIndex > 500)
                break;
            if(&string[stringIndex] == strLoc)
            {
                int j;
                for(j=0; j < newSublen; j++)
                {
                    printf("new index: %d  %c --> %cn",
                        j+newBufIndex, newBuf[newBufIndex+j], newSubstring[j]);
                    newBuf[newBufIndex+j] = newSubstring[j];
                }
                stringIndex += oldSublen;
                newBufIndex += newSublen;
            }
            else
            {
                printf("old index: %d  %c --> %cn", stringIndex,
                    newBuf[newBufIndex], string[stringIndex]);
                newBuf[newBufIndex] = string[stringIndex];
                if(string[stringIndex] == '')
                    break;
                newBufIndex++;
                stringIndex++;
            }
        }
        int length = (size_t)(strLen + (newSublen - oldSublen));
        string = (char*)realloc(string,
            (size_t)(strLen + (newSublen - oldSublen)));
        strcpy(string, newBuf);
        printf("result: %sn ",string);
        free(newBuf);
    }
    printf("end result: %s ",string);
}

首先应该明确期望的行为和接口。

主题"Char array…"不清楚。您提供了strLen, oldSublennewSublen,因此看起来您确实希望只使用给定长度的大容量内存缓冲区。但是,您使用strcasestrstrcpystring[stringIndex] == '',并提到printf("result: %sn ",string);。因此,我假设您想要使用"空终止字符串",可以由调用者作为字符串字面量传递:"abc"。不需要将所有这些长度传递给函数。

看起来你正在尝试实现递归字符串替换。每次更换后都要从头开始。让我们考虑更复杂的参数集,例如,将abaaba中的aba替换为ab

情形1:单次通过输入流

Each of both old substrings can be replaced: "abaaba" => "abab"
That is how the standard sed string replacement works:
> echo "abaaba" | sed 's/aba/ab/g'
abab

情形2:考虑可能重叠的递归替换

The first replacement: "abaaba" => "ababa"
The second replacement in already replaced result: "ababa" => "abba"

注意这种情况是不安全的,例如,将"loop"替换为"loop loop"。这是一个无限循环。

假设我们要实现一个函数,该函数接受以空结束的字符串,并且像sed一样一次完成替换。

通常不能替换输入字符串(在相同的内存中)。注意realloc可能会用新的地址分配新的内存块,所以你应该把这个地址返回给调用者。

为了实现简单,可以在内存分配之前计算结果所需的空间(案例1实现)。所以不需要重新分配:

#define _GNU_SOURCE
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
char* replaceSubstring(const char* string, const char* oldSubstring,
    const char* newSubstring)
{
    size_t strLen = strlen(string);
    size_t oldSublen = strlen(oldSubstring);
    size_t newSublen = strlen(newSubstring);
    const char* strLoc = string;
    size_t replacements = 0;
    /* count number of replacements */
    while ((strLoc = strcasestr(strLoc, oldSubstring)))
    {
        strLoc += oldSublen;
        ++replacements;
    }
    /* result size: initial size + replacement diff + sizeof('') */
    size_t result_size = strLen + (newSublen - oldSublen) * replacements + 1;
    char* result = malloc(result_size);
    if (!result)
        return NULL;
    char* resCurrent = result;
    const char* strCurrent = string;
    strLoc = string;
    while ((strLoc = strcasestr(strLoc, oldSubstring)))
    {
        memcpy(resCurrent, strCurrent, strLoc - strCurrent);
        resCurrent += strLoc - strCurrent;
        memcpy(resCurrent, newSubstring, newSublen);
        resCurrent += newSublen;
        strLoc += oldSublen;
        strCurrent = strLoc;
    }
    strcpy(resCurrent, strCurrent);
    return result;
}
int main()
{
    char* res;
    res = replaceSubstring("use the restroom. Then I need", "the", "th");
    printf("%sn", res);
    free(res);
    res = replaceSubstring("abaaba", "aba", "ab");
    printf("%sn", res);
    free(res);
    return 0;
}

最新更新