C 中没有预定义的函数可以从 C 字符串中删除给定的子字符串,但您可以使用 strstr 和 memmove 编写一个函数。请注意,如果您在适当位置删除子字符串,则不能使用 memcpy 或 strcpy,因为如果源数组和目标数组重叠,它们的行为未定义。
代码如下:
#include <string.h>
char *strremove(char *str, const char *sub) {
size_t len = strlen(sub);
if (len > 0) {
char *p = str;
while ((p = strstr(p, sub)) != NULL) {
memmove(p, p + len, strlen(p + len) + 1);
}
}
return str;
}
请注意,结果字符串可能包含子字符串,就像您的示例中的情况一样。
Netherwire 提出了优化建议:
char *strremove(char *str, const char *sub) {
size_t len = strlen(sub);
if (len > 0) {
char *p = str;
size_t size = 0;
while ((p = strstr(p, sub)) != NULL) {
size = (size == 0) ? (p - str) + strlen(p + len) + 1 : size - len;
memmove(p, p + len, size - (p - str));
}
}
return str;
}
进一步磨练代码,我想出了一个使用 2 指方法的更高效的版本:仅在第一次匹配之后开始在匹配之间复制片段:
char *strremove(char *str, const char *sub) {
char *p, *q, *r;
if (*sub && (q = r = strstr(str, sub)) != NULL) {
size_t len = strlen(sub);
while ((r = strstr(p = r + len, sub)) != NULL) {
memmove(q, p, r - p);
q += r - p;
}
memmove(q, p, strlen(p) + 1);
}
return str;
}
这是相同的方法,没有对memmove 进行任何调用:
char *strremove(char *str, const char *sub) {
char *p, *q, *r;
if (*sub && (q = r = strstr(str, sub)) != NULL) {
size_t len = strlen(sub);
while ((r = strstr(p = r + len, sub)) != NULL) {
while (p < r)
*q++ = *p++;
}
while ((*q++ = *p++) != '\0')
continue;
}
return str;
}