string.cpp
static cell AMX_NATIVE_CALL replace(AMX *amx, cell *params) /* 4 param */
{
cell *text = get_amxaddr(amx, params[1]);
cell len = params[2];
cell *what = get_amxaddr(amx, params[3]);
cell *with = get_amxaddr(amx, params[4]);
cell *textptr = text;
int withLen = amxstring_len(with);
int whatLen = amxstring_len(what);
int textLen = amxstring_len(text);
if (whatLen > textLen)
return 0;
if (whatLen < 1)
{
LogError(amx, AMX_ERR_NATIVE, "No search string specified.");
return 0;
}
if (textLen - whatLen + withLen > len)
{
LogError(amx, AMX_ERR_NATIVE, "replace() buffer not big enough (%d>=%d)", (textLen - whatLen + withLen), len);
return 0;
}
cell browsed = 0;
while (*text && (browsed <= (textLen-whatLen)))
{
if (*text == *what)
{
if (fastcellcmp(text, what, whatLen))
{
cell *saveptr = text + whatLen;
cell restlen = textLen - (browsed + whatLen);
textptr = text + withLen;
memmove(textptr, saveptr, (restlen + 1) * sizeof(cell));
memcpy(text, with, withLen * sizeof(cell));
return (textLen - whatLen + withLen);
}
}
text++;
browsed++;
}
return 0;
}
Przyjrzyj się funkcji i zastanów, dlaczego błąd występuje.
btw. Istnieje stock replace_all, który w tym wypadku wydaje się być lepszym rozwiązaniem.
string.inc
/* Replaces a contained string iteratively.
* This ensures that no infinite replacements will take place by
* intelligently moving to the next string position each iteration.
*/
stock replace_all(string[], len, const what[], const with[])
{
new pos = 0;
if ((pos = contain(string, what)) == -1)
{
return 0;
}
new total = 0;
new with_len = strlen(with);
new diff = strlen(what) - with_len;
new total_len = strlen(string);
new temp_pos = 0;
while (replace(string[pos], len - pos, what, with) != 0)
{
total++;
/* jump to position after replacement */
pos += with_len;
/* update cached length of string */
total_len -= diff;
/* will the next call be operating on the last character? */
if (pos >= total_len)
{
break;
}
/* find the next position from our offset */
temp_pos = contain(string[pos], what);
/* if it's invalid, we're done */
if (temp_pos == -1)
{
break;
}
/* otherwise, reposition and update counters */
pos += temp_pos;
}
return total;
}