问题
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.
回答1:
#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] = "{"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;
}
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.
回答2:
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 allocate strlen(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.
回答3:
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.
回答4:
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)
回答5:
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.
来源:https://stackoverflow.com/questions/7843622/segmentation-error-while-replacing-substrings-of-a-string-with-other-substring