#include <stdio.h>
size_t s_length(const char* s);
void s_copy(char* d, const char* s, size_t n);
void s_move(char* d, const char* s, size_t n);
char* s_replace(char* s, const char* old,
const char* ns, size_t maxsize){
const char* p2;
size_t n1, n2, n3, i;
char* p1, *t = s;
n1 = s_length(old);
n2 = s_length(ns) + 1;
n3 = s_length(s) + 1;
i = 0;
while(*s && (i < 9)){
p1 = s;
p2 = old;
while(*p2 && (*p2 == *p1)){
++p1;
++p2;
}
if(! *p2){
if(n2 > n1){
//защита от переполнение выходного буфера
if((n3 + (n2 - n1)) >= maxsize)
break;
s_move(s + (n2 - n1), s, n3 - (size_t)(s - t));
n3 += n2 - n1;
} else {
s_copy(s, s + (n1 - n2), n3 - (size_t)(s - t));
n3 -= n1 - n2;
}
s_copy(s, ns, n2);
s += n2 - 1;
*s++ = (char)(i + '1');
++i;
continue;
}
++s;
}
return t;
}
int main(void){
char s[64] = "ПОЛИЛИ_ЛИЛИЮ";
puts(s_replace
(s
, "ЛИ", "СТО", sizeof(s
) - 1)); return 0;
}
size_t s_length(const char* s){
const char* t = s;
while(*s)
++s;
return (size_t)(s - t);
}
void s_copy(char* d, const char* s, size_t n){
size_t i;
for(i = 0; i < n; ++i)
*d++ = *s++;
}
void s_move(char* d, const char* s, size_t n){
size_t i;
d += (n - 1);
s += (n - 1);
for(i = n; i > 0; --i)
*d-- = *s--;
}
CiNpbmNsdWRlIDxzdGRpby5oPgpzaXplX3Qgc19sZW5ndGgoY29uc3QgY2hhciogcyk7CnZvaWQgICBzX2NvcHkoY2hhciogZCwgY29uc3QgY2hhciogcywgc2l6ZV90IG4pOwp2b2lkICAgc19tb3ZlKGNoYXIqIGQsIGNvbnN0IGNoYXIqIHMsIHNpemVfdCBuKTsKCgpjaGFyKiBzX3JlcGxhY2UoY2hhciogcywgY29uc3QgY2hhciogb2xkLCAKCSAgICAgICAgICAgIGNvbnN0IGNoYXIqIG5zLCBzaXplX3QgbWF4c2l6ZSl7Cgljb25zdCBjaGFyKiBwMjsKCXNpemVfdCBuMSwgbjIsIG4zLCBpOwoJY2hhciogIHAxLCAqdCA9IHM7CgoJbjEgPSBzX2xlbmd0aChvbGQpOwoJbjIgPSBzX2xlbmd0aChucykgKyAxOwoJbjMgPSBzX2xlbmd0aChzKSArIDE7CglpICA9IDA7CgoJd2hpbGUoKnMgJiYgKGkgPCA5KSl7CgkJcDEgPSBzOwoJCXAyID0gb2xkOwoJCXdoaWxlKCpwMiAmJiAoKnAyID09ICpwMSkpewoJCQkrK3AxOwoJCQkrK3AyOwoJCX0KCgkJaWYoISAqcDIpewoJCQlpZihuMiA+IG4xKXsKCgkJCQkvL9C30LDRidC40YLQsCDQvtGCINC/0LXRgNC10L/QvtC70L3QtdC90LjQtSDQstGL0YXQvtC00L3QvtCz0L4g0LHRg9GE0LXRgNCwCgkJCQlpZigobjMgKyAobjIgLSBuMSkpID49IG1heHNpemUpCgkJCQkJYnJlYWs7CgoJCQkJc19tb3ZlKHMgKyAobjIgLSBuMSksIHMsIG4zIC0gKHNpemVfdCkocyAtIHQpKTsKCQkJCW4zICs9IG4yIC0gbjE7CgkJCX0gZWxzZSB7CgkJCQlzX2NvcHkocywgcyArIChuMSAtIG4yKSwgbjMgLSAoc2l6ZV90KShzIC0gdCkpOwoJCQkJbjMgLT0gbjEgLSBuMjsKCQkJfQoKCQkJc19jb3B5KHMsIG5zLCBuMik7CgkJCXMgICArPSBuMiAtIDE7CgkJCSpzKysgPSAoY2hhcikoaSArICcxJyk7CgkJCSsraTsKCQkJY29udGludWU7CgkJfQoJCSsrczsKCX0KCXJldHVybiB0Owp9CgoKaW50IG1haW4odm9pZCl7CgljaGFyIHNbNjRdID0gItCf0J7Qm9CY0JvQmF/Qm9CY0JvQmNCuIjsKCXB1dHMocyk7CglwdXRzKHNfcmVwbGFjZShzLCAi0JvQmCIsICLQodCi0J4iLCBzaXplb2YocykgLSAxKSk7CglyZXR1cm4gMDsKfQoKCnNpemVfdCBzX2xlbmd0aChjb25zdCBjaGFyKiBzKXsKCWNvbnN0IGNoYXIqIHQgPSBzOwoJd2hpbGUoKnMpCgkJKytzOwoJcmV0dXJuIChzaXplX3QpKHMgLSB0KTsKfQoKdm9pZCBzX2NvcHkoY2hhciogZCwgY29uc3QgY2hhciogcywgc2l6ZV90IG4pewoJc2l6ZV90IGk7Cglmb3IoaSA9IDA7IGkgPCBuOyArK2kpCgkJKmQrKyA9ICpzKys7Cn0KCnZvaWQgc19tb3ZlKGNoYXIqIGQsIGNvbnN0IGNoYXIqIHMsIHNpemVfdCBuKXsKCXNpemVfdCBpOwoJZCArPSAobiAtIDEpOwoJcyArPSAobiAtIDEpOwoJZm9yKGkgPSBuOyBpID4gMDsgLS1pKQoJCSpkLS0gPSAqcy0tOwp9Cg==