PDA

Просмотр полной версии : [Вопрос] Как сделать поиск разделителя для команды /todo



gangzone.ini
21.11.2019, 15:05
Возник вопрос по созданию команды /todo , с выводом текста



CMD:todo(playerid, params[])
{
if(sscanf(params, "p<*>s[128]s[64]", params[0], params[1])) return SendClientMessage(playerid, COLOR_WHITE, !" Введите: /todo [текст] * [действие]");
// else if(sscanf(params, "%s'*'%s", params[0], params[1])) return SendClientMessage(playerid, COLOR_GREY, !"Используейте символ '*' для разделения. Пример: /todo привет * протянул руку");

totalstring[0] = EOS;
format(totalstring, sizeof(totalstring), " %s {C2A2DA}- сказал(а) %s, %s", params[0], pInfo[playerid][pName], params[1]);
SendActionMessage(playerid, 0xC8C8C8FF, totalstring, 15.0);
return true;
}


Если с проверкой sscanf(params, "%s'*'%s", params[0], params[1] - ничего не происходит
Если без проверки , /todo *a b текст проходит , а нужно /todo a * b , как так сделать ?
Так же , текст не корректно выводиться , например /todo a*b , выводит "ab * b"

DeimoS
21.11.2019, 16:15
Во-первых, твоя команда не будет работать, ибо второй параметр, куда ты записываешь действие, перезапишет первый параметр, куда ты записываешь текст. "params" - это одномерный массив. И когда ты указываешь "params[1]" - это означает, что запись текста в массив начнётся с первой ячейки, а не то, что вдруг появится какой-то отдельный массив и в него запишется текст.

Во-вторых, проще сделать так:
CMD:todo(playerid, params[])
{
new find_pos = strfind(params, "*");
if(find_pos == -1)
return SendClientMessage(playerid, COLOR_WHITE, !" Введите: /todo [текст] * [действие]");
params[find_pos] = '\0';

format(totalstring, sizeof(totalstring),
" %s {C2A2DA}- сказал(а) %s, %s", params, pInfo[playerid][pName], params[find_pos+1]);
SendActionMessage(playerid, 0xC8C8C8FF, totalstring, 15.0);
return true;
}
Ибо и никакие дополнительные массивы вводить не нужно, и возиться с настройками sscanf

gangzone.ini
21.11.2019, 16:21
Во-первых, твоя команда не будет работать, ибо второй параметр, куда ты записываешь действие, перезапишет первый параметр, куда ты записываешь текст. "params" - это одномерный массив. И когда ты указываешь "params[1]" - это означает, что запись текста в массив начнётся с первой ячейки, а не то, что вдруг появится какой-то отдельный массив и в него запишется текст.

Во-вторых, проще сделать так:
CMD:todo(playerid, params[])
{
new find_pos = strfind(params, "*");
if(find_pos == -1)
return SendClientMessage(playerid, COLOR_WHITE, !" Введите: /todo [текст] * [действие]");
params[find_pos] = '\0';

format(totalstring, sizeof(totalstring),
" %s {C2A2DA}- сказал(а) %s, %s", params, pInfo[playerid][pName], params[find_pos+1]);
SendActionMessage(playerid, 0xC8C8C8FF, totalstring, 15.0);
return true;
}
Ибо и никакие дополнительные массивы вводить не нужно, и возиться с настройками sscanf

В любом месте можно поставить *
/todo * a a

DeimoS
21.11.2019, 16:28
В любом месте можно поставить *
/todo * a a

Ну так проверяй размер текста в params и params[find_pos+1].

CMD:todo(playerid, params[])
{
new find_pos = strfind(params, "*");
if(find_pos == -1)
return SendClientMessage(playerid, COLOR_WHITE, !" Введите: /todo [текст] * [действие]");
params[find_pos] = '\0';
if(!strlen(params) || !strlen(params[find_pos+1]))
return SendClientMessage(playerid, COLOR_WHITE, !" Введите: /todo [текст] * [действие]");

format(totalstring, sizeof(totalstring),
" %s {C2A2DA}- сказал(а) %s, %s", params, pInfo[playerid][pName], params[find_pos+1]);
SendActionMessage(playerid, 0xC8C8C8FF, totalstring, 15.0);
return true;
}

SteveStage
21.11.2019, 16:41
Лично я использую такую конструкцию:

CMD:todo(playerid, params[])
{

new
text[21],
action[31];

if(sscanf(params, "p<*>s[21]s[31]", text, action))
return SCM(playerid, COLOR_YELLOW, !"Образец отыгровки фразы с действием: /todo [phrase]*[action]");
if(text[20] != EOS)
return SCM(playerid, COLOR_YELLOW, !"Максимальная длина реплики в отыгровке фразы с действием: 20 символов!");
if(action[30] != EOS)
return SCM(playerid, COLOR_YELLOW, !"Максимальная длина действия в отыгровке фразы с действием: 30 символов!");
if(strlen(text) < 2)
return SCM(playerid, COLOR_YELLOW, !"Минимальная длина отыгровки фразы в отыгровке фразы с действием: 2 символа!");
if(strlen(action) < 2)
return SCM(playerid, COLOR_YELLOW, !"Минимальная длина отыгровки действия в отыгровке фразы с действием: 2 символа!");

static const
fmt_str[] = "'%s' - сказал%s %s, %s";

new
str[sizeof(fmt_str)-6+MAX_PLAYER_NAME+30+20+1+1];

format(str, sizeof(str), fmt_str, text, (player[playerid][pSex] == 1) ? ("") : ("а"), GetName(playerid), action);
ProxDetector(playerid, 20.0, COLOR_ACTION, str);
SetPlayerChatBubble(playerid, str, COLOR_ACTION, 20.0, 4000);
return true;
}

Не знаю насчет оптимизации, но багов с выводом текста не обнаружено

Также такой вариант (многовато переменных)

CMD:todo(playerid, params[])
{
new
text[21],
space[2],
action[31];
if(sscanf(params, "s[21]s[2]s[31]", text, space, action))
return SCM(playerid, COLOR_YELLOW, !"Образец отыгровки фразы с действием: /todo [phrase] * [action]");
if(!strcmp(text, "*") || !strcmp(action, "*") || strcmp(space, "*"))
return SCM(playerid, COLOR_YELLOW, !"Образец отыгровки фразы с действием: /todo [phrase] * [action]");
if(text[20] != EOS)
return SCM(playerid, COLOR_YELLOW, !"Максимальная длина реплики в /todo: 20 символов!");
if(action[30] != EOS)
return SCM(playerid, COLOR_YELLOW, !"Максимальная длина действия в /todo: 30 символов!");
if(strlen(text) < 2)
return SCM(playerid, COLOR_YELLOW, !"Минимальная длина фразы в /todo: 2 символа!");
if(strlen(action) < 2)
return SCM(playerid, COLOR_YELLOW, !"Минимальная длина действия в /todo: 2 символа!");

static const
fmt_str[] = "'%s' - сказал%s %s, %s";
new
str[sizeof(fmt_str)-6+MAX_PLAYER_NAME+30+20+1+1];
format(str, sizeof(str), fmt_str, text, (player[playerid][pSex] == 1) ? ("") : ("а"), GetName(playerid), action);

ProxDetector(playerid, 20.0, COLOR_ACTION, str);
SetPlayerChatBubble(playerid, str, COLOR_ACTION, 20.0, 4000);
return true;
}

P.S. У последнего варианта есть баг - во фразе и действии нельзя ставить пробелы, иначе способ разделения фразы, действия и * пробелами собъется

Решение к багу 2 варианта - убрать массив space, удалить эту проверку

if(!strcmp(text, "*") || !strcmp(action, "*") || strcmp(space, "*"))
return SCM(playerid, COLOR_YELLOW, !"Образец отыгровки фразы с действием: /todo [phrase] * [action]");

И заменить

if(sscanf(params, "s[21]s[2]s[31]", text, space, action))
return SCM(playerid, COLOR_YELLOW, !"Образец отыгровки фразы с действием: /todo [phrase] * [action]");

на

if(sscanf(params, "s[21]'*'s[31]", text, action))
return SCM(playerid, COLOR_YELLOW, !"Образец отыгровки фразы с действием: /todo [phrase] * [action]");

DeimoS
21.11.2019, 20:17
Я выше уже дал рабочий вариант, который, к тому же, проще и оптимизированнее твоего)
Судя по благодарности под моим постом, автор темы получил ответ на свой вопрос, поэтому закрываю тему.