我需要在某些文本中替换字符串。我在stackoverflow找到了这个函数:
char *replace(const char *s, const char *old, const char *new)
{
char *ret;
int i, count = 0;
size_t newlen = strlen(new);
size_t oldlen = strlen(old);
for (i = 0; s[i] != '\0'; i++) {
if (strstr(&s[i], old) == &s[i]) {
count++;
i += oldlen - 1;
}
}
ret = malloc(i + count * (newlen - oldlen));
if (ret == NULL)
exit(EXIT_FAILURE);
i = 0;
while (*s) {
if (strstr(s, old) == s) {
strcpy(&ret[i], new);
i += newlen;
s += oldlen;
} else
ret[i++] = *s++;
}
ret[i] = '\0';
return ret;
}
此功能对我来说非常适合单次更换。但我需要更换整个数组" str2rep"到"替换"。所以我想做的事情(我只是一个初学者)
****
#define MAXTEXT 39016
int l;
int j;
char *newsms = NULL;
char text[MAXTEXT];
char *str2rep[] = {":q:",":n:"};
char *replacement[] = {"?","\n"};
strcpy((char *)text,(char *)argv[5]);
l = sizeof(str2rep) / sizeof(*str2rep);
for(j = 0; j < l; j++)
{
newsms = replace(text,(char *)str2rep[j],(char *)replacement[j]);
strcpy(text,newsms);
free(newsms);
}
textlen = strlen(text);
这个代码甚至在本地工作,如果我从单个文件构建它...但这是星号模块,所以当执行此操作时,星号将停止:
*检测到glibc * / usr / sbin / asterisk:双重免费或损坏(!prev):0x00007fa720006310 *
答案 0 :(得分:1)
的问题:
ret = malloc(i + count * (newlen - oldlen));
太小了。需要+ 1.
考虑replace("", "", "")
会发生什么。如果你的SO参考是this,那也是错误的。
混合签名/未签名的可疑结果。 count
已签名。 newlen, oldlen
未签名
我认为原始代码工作正常,但我不喜欢使用无符号数学的环绕特性,这可以避免newlen < oldlen
时发生的情况。
// i + count * (newlen - oldlen)
size_t newsize = i + 1; // + 1 for above reason
if (newlen > oldlen) newsize += count * (newlen - oldlen);
if (newlen < oldlen) newsize -= count * (oldlen - newlen);
ret = malloc(newsize);
确保足够的空间。 @hyde这里有各种方法。
// strcpy(text, newsms);
if (strlen(newsms) >= sizeof text) Handle_Error();
strcpy(text, newsms);
次要
无需演员阵容
// newsms = replace(text, (char *) str2rep[j], (char *) replacement[j]);
newsms = replace(text, str2rep[j], replacement[j]);
最好将size_t
用于i
。一个迂腐的解决方案也会使用size_t count
。
// int i;
size_t i;
答案 1 :(得分:0)
我会建议一些对我来说更清晰的替代方案,取代适当的动态字符串实现。异常处理留给读者添加的练习。 :)
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char *appendn(char *to, char *from, int length)
{
return strncat(realloc(to, strlen(to) + length + 1), from, length);
}
char *replace(char *string, char *find, char *sub)
{
char *result = calloc(1, 1);
while (1)
{
char *found = strstr(string, find);
if (!found)
break;
result = appendn(result, string, found - string);
result = appendn(result, sub, strlen(sub));
string = found + strlen(find);
}
return appendn(result, string, strlen(string));
}
int main()
{
const char text[] = "some [1] with [2] to [3] with other [2]";
char *find[] = {"[1]", "[2]", "[3]", NULL};
char *sub[] = {"text", "words", "replace"};
char *result, *s;
int i;
result = malloc(sizeof(text));
(void) strcpy(result, text);
for (i = 0; find[i]; i ++)
{
s = replace(result, find[i], sub[i]);
free(result);
result = s;
}
(void) printf("%s\n", result);
free(result);
}