现在,我正在尝试通过编写一个函数来熟悉 C,该函数给定一个字符串,将用新的子字符串替换目标子字符串的所有实例。但是,我在重新分配 char* 数组时遇到了问题。在我看来,似乎我能够在主循环末尾成功地将数组string
重新分配到所需的新大小,然后执行strcpy
用更新的字符串填充它。但是,在以下情况下它会失败:
字符串的原始输入:“使用洗手间。然后我需要”
要替换的目标:“the”(不区分大小写)
期望的替换值:“th'”
在循环结束时,行 printf("result: %s\n ",string);
打印出正确的短语“use th'restroom.Then I need”。然而,string
似乎随后重置了自己:while()
语句中对 strcasestr
的调用成功了, Loop printf("string: %s\n",string);
打印原始输入字符串,并且循环无限期地继续。
任何想法将不胜感激(我为我的调试 printf
语句提前道歉)。谢谢!
该函数的代码如下:
int replaceSubstring(char *string, int strLen, char*oldSubstring,
int oldSublen, char*newSubstring, int newSublen )
{
printf("Starting replace\n");
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 newbuf\n");
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 --> %c\n",
j+newBufIndex, newBuf[newBufIndex+j], newSubstring[j]);
newBuf[newBufIndex+j] = newSubstring[j];
}
stringIndex += oldSublen;
newBufIndex += newSublen;
}
else
{
printf("old index: %d %c --> %c\n", stringIndex,
newBuf[newBufIndex], string[stringIndex]);
newBuf[newBufIndex] = string[stringIndex];
if(string[stringIndex] == '\0')
break;
newBufIndex++;
stringIndex++;
}
}
int length = (size_t)(strLen + (newSublen - oldSublen));
string = (char*)realloc(string,
(size_t)(strLen + (newSublen - oldSublen)));
strcpy(string, newBuf);
printf("result: %s\n ",string);
free(newBuf);
}
printf("end result: %s ",string);
}
最佳答案
首先应该澄清任务所需的行为和界面。
主题“Char array...”不清楚。
您提供了 strLen
、oldSublen
newSublen
,因此看来您确实只想使用给定长度的批量内存缓冲区。
但是,您使用 strcasestr
、strcpy
和 string[stringIndex] == '\0'
并提及 printf("result: %s\n ",字符串);
。
因此,我假设您希望使用“空终止字符串”,该字符串可以由调用者作为字符串文字传递:“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”替换为“looploop”。这是一个无限循环。
假设我们想要实现一个函数,它接受以 null 结尾的字符串,并且像 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('\0') */
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("%s\n", res);
free(res);
res = replaceSubstring("abaaba", "aba", "ab");
printf("%s\n", res);
free(res);
return 0;
}
关于C - 字符数组似乎可以复制,但仅限于循环范围内,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32813374/