Я собираюсь игнорировать код, который удаляет <>
и просто сосредоточиться на ядре вопроса.
Если вы не знаете заранее длину строки и замены, то у вас есть несколько вариантов:
- Подсчитайте количество матчей первого и использовать, чтобы отработать пространство requried
- используйте
realloc
в цикле, чтобы изменить объем памяти, выделенной
- Start с умной догадкой в размере, а затем использовать перераспределить в соответствии с требованиями
- использования фиксированных буферов размера и просто ошибкой, если мы бежим
Первый - это самый простой способ, который вы хотите использовать, зависит от ваших требований к производительности (четыре быстрее всего стоят за счет увеличения объема памяти, если вы хорошо разбираетесь в максимальном размере строки, три, вероятно, следующий быстрый, если у вас есть хорошее представление о среднем числе матчей).
Реализация простейший метод только требует две петли, один, чтобы найти спички, то один, чтобы сделать замену:
char *strreplace(char *src, char* find, char *repl)
{
char *target; // Will store our new string
char *final; // Will use to store the pointer of the final string
char *str = src; // Will use for searching
int matches = 0;
// First count the matches (if strlen(repl) <= strlen(word)
// you could skip this and just allocate strlen(src)
while (str = strstr(str, find)) {
matches ++;
str++;
}
target = malloc(1 + strlen(src) +
(sizeof(char) * (matches *
(strlen(repl) - strlen(find))
)));
if (target == NULL) {
return src; // Or NULL, or whatever to indicate an error
}
final = target;
// Now copy everything
str = src;
while (str = strstr(str, find)) {
// Copy string before the match
if (str > src) {
strncpy(target, src, (str - src));
target += (str - src);
src += (str - src);
}
// Copy replacement
strncpy(target, repl, strlen(repl));
// Move pointers
str++; // Move past the match in our searching pointer
src += strlen(find); // Move past the string in our src
target += strlen(repl); // Move past the replacement in our target
}
// Finally copy the rest of the string, if there's some left
if (*src) {
strncpy(target, src, strlen(src));
}
return final;
}
Я думаю, что я мог бы использовать слишком много указателей там, у меня есть ощущение, что есть упрощение, которое может быть сделано для кода замены, но я не вижу его в данный момент.
Вы можете считать, что и адаптировать его делать то, что вы хотите, некоторые тесты (чтобы попытаться охватить случаи угловые):
printf("%s\n", strreplace("testtesttest1234", "test", "foo"));
printf("%s\n", strreplace("testtesttest1234", "test", "foobar"));
printf("%s\n", strreplace("somethingtestsomethingteasesttest", "test", "foobar"));
Выходы:
foofoofoo1234
foobarfoobarfoobar1234
somethingfoobarsomethingteasestfoobar
Это потому, что вы этого не сделаете петля. –
да, я знаю, но я не знаю, как добавить цикл, чтобы не повлиять на malloc. Должен ли я использовать realloc или smth? –
Размер 'malloc'd не должен быть точного размера. Вы можете просто игнорировать все после того, как вы «переместите» строку слева (для замены) и добавьте нулевой символ. –