删除C中字符串的所有子字符串
removing all sub strings of a string in C
我一直在尝试从给定字符串中删除所有出现的子字符串,但我的代码有一个我不知道如何解决的错误。当两个子字符串背靠背时,我的代码只能删除其中一个。
这是我的代码:
void removeSub(char *str, char *sub, char *new) {
int len = strlen(sub);
char *subp = strstr(str, sub);
int position = subp - str;
for (int i = 0; i <= strlen(str); i++) {
if (i >= position && i < position + len) {
continue;
}
if (i == position + len - 1) {
// update position
subp = strstr(str + i - 1, sub);
position = subp - str;
}
char ch = str[i];
strncat(new, &ch, 1);
}
}
代码的快速解释:我将字符串一个字符一个字符地复制到另一个字符串(新)中,每当我沿途看到子字符串时,我的代码就会继续循环,什么也不做。传递子字符串时,我重新定位下一个子字符串。 (我知道这不是很有效,但我是新手,不知道很多方法和功能)
问题是循环不断前进。当你删除一个子字符串时,你需要从循环索引中减去一个 i
所以你再次搜索相同的位置。
您的代码有多个问题:
循环 for (int i = 0; i <= strlen(str); i++)
的效率非常低,因为 str
的长度在循环的每次迭代中都会重新计算。你应该简单地写:
for (int i = 0; str[i] != '[=10=]'; i++)
当您跳过匹配的子字符串时,它后面的字符被复制并且 i
在循环中递增,因此无法正确测试下一个匹配项。
附加单个字符的代码效率低下:您应该有一个指向目标字符串末尾的指针,而不是 strncat(new, &ch, 1);
并写入 *p++ = str[i];
并设置 null循环结束后的终止符。
这是修改后的版本:
#include <string.h>
// remove all occurrences of sub in str into destination buffer new
// return a pointer to the destination string
char *removeSub(cont char *str, const char *sub, char *new) {
char *p = new;
size_t len = strlen(sub);
if (len > 0) {
const char *subp;
while ((subp = strstr(str, sub)) != NULL) {
memcpy(p, str, sub - str);
p += sub - str;
str = sub + len;
}
}
strcpy(p, str);
return new;
}
还有一个没有库调用的替代方案:
// remove all occurrences of sub in str into destination buffer new
// return a pointer to the destination string
char *removeSub(cont char *str, const char *sub, char *new) {
char *p = new;
while (*str) {
if (*str == *sub) { /* potential substring match */
for (size_t i = 1;; i++) {
if (sub[i] == '[=12=]') { /* substring match */
str += i;
break;
}
if (str[i] != sub[i]) {
*p++ = *str++;
break;
}
}
} else {
*p++ = *str++;
}
}
*p = '[=12=]';
return new;
}
我一直在尝试从给定字符串中删除所有出现的子字符串,但我的代码有一个我不知道如何解决的错误。当两个子字符串背靠背时,我的代码只能删除其中一个。
这是我的代码:
void removeSub(char *str, char *sub, char *new) {
int len = strlen(sub);
char *subp = strstr(str, sub);
int position = subp - str;
for (int i = 0; i <= strlen(str); i++) {
if (i >= position && i < position + len) {
continue;
}
if (i == position + len - 1) {
// update position
subp = strstr(str + i - 1, sub);
position = subp - str;
}
char ch = str[i];
strncat(new, &ch, 1);
}
}
代码的快速解释:我将字符串一个字符一个字符地复制到另一个字符串(新)中,每当我沿途看到子字符串时,我的代码就会继续循环,什么也不做。传递子字符串时,我重新定位下一个子字符串。 (我知道这不是很有效,但我是新手,不知道很多方法和功能)
问题是循环不断前进。当你删除一个子字符串时,你需要从循环索引中减去一个 i
所以你再次搜索相同的位置。
您的代码有多个问题:
循环
for (int i = 0; i <= strlen(str); i++)
的效率非常低,因为str
的长度在循环的每次迭代中都会重新计算。你应该简单地写:for (int i = 0; str[i] != '[=10=]'; i++)
当您跳过匹配的子字符串时,它后面的字符被复制并且
i
在循环中递增,因此无法正确测试下一个匹配项。附加单个字符的代码效率低下:您应该有一个指向目标字符串末尾的指针,而不是
strncat(new, &ch, 1);
并写入*p++ = str[i];
并设置 null循环结束后的终止符。
这是修改后的版本:
#include <string.h>
// remove all occurrences of sub in str into destination buffer new
// return a pointer to the destination string
char *removeSub(cont char *str, const char *sub, char *new) {
char *p = new;
size_t len = strlen(sub);
if (len > 0) {
const char *subp;
while ((subp = strstr(str, sub)) != NULL) {
memcpy(p, str, sub - str);
p += sub - str;
str = sub + len;
}
}
strcpy(p, str);
return new;
}
还有一个没有库调用的替代方案:
// remove all occurrences of sub in str into destination buffer new
// return a pointer to the destination string
char *removeSub(cont char *str, const char *sub, char *new) {
char *p = new;
while (*str) {
if (*str == *sub) { /* potential substring match */
for (size_t i = 1;; i++) {
if (sub[i] == '[=12=]') { /* substring match */
str += i;
break;
}
if (str[i] != sub[i]) {
*p++ = *str++;
break;
}
}
} else {
*p++ = *str++;
}
}
*p = '[=12=]';
return new;
}