用其他子字符串替换字符串的子字符串时出现分段错误
我有字符串“ {"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[] = "{"1":"[4,11,14,19,20,18,27]"}";
printf("%s\n", replace(""", "\\\"", string));
printf("%s\n", replace("\"[" , "\"", string));
printf("%s\n", replace("]\\" , "\\", string));
printf("%s\n", replace("{" , "\"{", string));
printf("%s\n", replace("}" , "}\"", string));
return 0;
}
我收到最后两次替换调用的错误。我的操作员是 {\"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 有关,但无法理解。如果有人能帮助我,那就太好了。提前致谢。
I have string " {"1":"[4,11,14,19,20,18,27]"} ". I want to change it into
"{\"1\":\"4,11,14,19,20,18,27\"}".
Below is my code:
#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[] = "{"1":"[4,11,14,19,20,18,27]"}";
printf("%s\n", replace(""", "\\\"", string));
printf("%s\n", replace("\"[" , "\"", string));
printf("%s\n", replace("]\\" , "\\", string));
printf("%s\n", replace("{" , "\"{", string));
printf("%s\n", replace("}" , "}\"", string));
return 0;
}
I get the error for the last two replace calls. My o/p is {\"1\":\"[4,11,14,19,20,18,27]\"}
{\"1\":\"4,11,14,19,20,18,27]\"}
{\"1\":\"4,11,14,19,20,18,27\"}
Segmentation fault
I tried doing gdb, but not able to find the root cause of error. it is somehow concerned with memcopy, but not able to understand. If anyone can help me, it would be great. Thanks in advance.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
最后两个替换“{}”包含其自身。这会导致原始字符串在同一位置重新扫描,重新匹配+重新替换。于无穷。 ptr+=newlen 避免了这种情况。
The last two substitutions "{}" contain themselves. This causes the original string to be rescanned at the same place, rematched+ resubstututed. At infinitum. The ptr+=newlen avoids this.
您的替换字符串比输入长,但是当您分配
string
时,它只有输入大小加上 NUL 终止符的空间。当您尝试扩展它时,您会溢出缓冲区,系统会关闭您(尽管它可能会稍微超出一点,例如将分配四舍五入到下一个 4 的倍数或可能是 8)。 ,您(可能)想要计算出字符串可以增长的最大量,分配那么大的字符串,并将其用于
编辑结果:例如,考虑您的最后一个替换,更改
} 到
}"
。这会使您找到的子字符串的长度加倍。作为一个非常简单的最坏情况估计,我们假设整个输入完全由}
组成。在这种情况下,结果将是输入的两倍,因此我们需要为结果分配strlen(input)*2+1
字节,在您的情况下,至少是最后四个替换。是互斥的(例如,输入不能是
{
和}
以及[
和]
同时),因此将长度加倍一次就足以覆盖他们所有人。Your replacement string is longer than the input, but when you allocate
string
, it has only space for the input size plus NUL terminator. When you try to expand it, you overrun the buffer, and the system shuts you down (though it might let you by with a small overrun, such as rounding the allocation up to the next multiple of 4 or maybe 8.To fix the problem, you (probably) want to figure out the maximum amount by which your string could grow, allocate that large of a string, and use it for the result.
Edit: for example, consider your last replacement, changing
}
to}"
. This doubles the length of the substring you find. As a really simple worst-case estimate, let's assume the entire input consists entirely of}
. In this case, the result would be twice as long as the input, so we'd need to allocatestrlen(input)*2+1
bytes for the result.In your case, the last four replacements (at least) are mutually exclusive (e.g., an input can't be a
{
and a}
and a[
and a]
simultaneously) so doubling the length once will be enough to cover all of them.您的
replace
假设缓冲区足够大以容纳结果。您需要分配足够大的缓冲区,以使其能够容纳扩展的结果。Your
replace
assumes that the buffer is big enough to hold the result. You need to allocate the buffer so big that it can hold the result of expansion.你的操作顺序是错误的。您应该首先为替换字符串腾出位置,然后插入替换字符串。 (给予足够的空间)。另外,您可以提前计算 strlen(),因为它们不会改变。 (除非它们只使用一次)
Your order of operations is wrong. You should first make place for the replacement string, and than insert the replacement. (given enough space). Also, you could calculate the strlen()s in advance, since they do not change. (except if they are only used once)
如果 withthat 比这个长,那么你的 memcpy 就会覆盖替换后的字符串的一部分。在这种情况下,您必须在 memcpy 之前执行 memmove 。
If withthat is longer than this, then your memcpy is overwriting part of the string that goes after the replacement. You would have to do the memmove before memcpy in this case.