Reputation: 39
Ive been trying to remove all occurrences of a substring from a given string but my code has a bug which I don't know how to resolve. When two substrings are back-to-back my code can only remove one of them.
This is my code:
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);
}
}
a quick explanation of code: I copy the string char by char into another string(new) and whenever I see the substring along the way my code continues the loop and does nothing. when a substring is passed I relocate the next substring. (I know this isn't very efficient but I'm new and don't know many ways and functions)
Upvotes: 1
Views: 798
Reputation: 144740
Your code has multiple issues:
the loop for (int i = 0; i <= strlen(str); i++)
is very inefficient as the length of str
is recomputed at each iteration of the loop. You should simply write:
for (int i = 0; str[i] != '\0'; i++)
when you skip the matched substring, the character after it is copied and i
is incremented in the loop so the next occurrence is not tested correctly.
the code to append a single character is inefficient: instead of strncat(new, &ch, 1);
you should have a pointer to the end of the destination string and write *p++ = str[i];
and set the null terminator after the end of the loop.
Here is a modified version:
#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;
}
And an alternative without library calls:
// 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] == '\0') { /* substring match */
str += i;
break;
}
if (str[i] != sub[i]) {
*p++ = *str++;
break;
}
}
} else {
*p++ = *str++;
}
}
*p = '\0';
return new;
}
Upvotes: 1
Reputation: 43278
The problem is the loop keeps advancing. When you remove a substring, you need to subtract one from the loop index i
so you search the same position again.
Upvotes: 1