shape1
shape2
shape3
shape4
shape7
shape8

Используем функцию sscanf


noname_idk

Гуру
Пользователь
19.07.2015
4 046
7
787
0
Скриптер
Введение. Основная информация.

Доброе время суток, участники форума. Достаточно часто пользуюсь функцией sscanf. Почему? Она удобна и практична. Причем использовать ее можно не только в командах, но и, например, при загрузке чего-либо из базы данных, как это делаю я. Допустим, есть система автомобилей. Дабы не создавать два столбца для каждого из двух возможных цветов транспортного средства, можно создать один, в который записывать значение вида "цвет_1, цвет_2". Записать-то запишем, через format:

format(строка, размер строки, "%d,%d", цвет_1, цвет_2);

Но вот получить из этой строки два значения уже будет проблематично. Приходит нам на помощь sscanf2.



Скачать sscanf2. Все инструкции по подключению изложены в той же теме.
Итак, функция имеет следующие аргументы:

sscanf(откуда, "<разделитель>типы извлекаемых данных", куда_1, куда_2, ...);

По поводу разделителей. Собственно, это тот символ, которым Вы разделяете введенные данные. Например, если аргументы записаны через запятую, тогда разделитель будет таким: <,>, если вертикальная палочка, <|>, если тире, <->, если пробел, < >. Если у Вас разделителем выступает пробел, тогда < > можно и вовсе не писать.

Что касается типов извлекаемых данных... Есть всего 4 типа: 



  • i, d - целые числа (например, "1", "-10", "120");
  • s[размер] - строка (например, "Форум", "Да", "PW");
  • f - дробные числа (например, "17.575", "-47.8", "100.99");
  • u - ID игрока или часть имени (например, "0", "1", "Vasya_Pet", "Vasya_Petrov");

Пример 1.

Вернемся к начальному примеру использования sscanf. В переменную string записаны два цвета: color1 и color2 через запятую. Нам нужно каждый из них увеличить на единицу (инкрементировать). Для этого сначала нужно получить каждый цвет из строки, а затем увеличивать их на единицу. Поскольку цвета имеют целочисленный тип данных, создаем две переменные типа integer:

new color1, color2;

Извлекаем оба цвета, записанных через запятую, из переменной string:

sscanf(string, "p<,>dd", color1, color2);

Опять же, так как цвета имеют целочисленный тип, то используем d в обеих случаях. Далее все просто, записываем обратно в строку string при помощи format две увеличенные на единицу переменные:

format(string, sizeof(string), "%d, %d", color1+1, color2+1);

Но лучше сделать так, если хотите создать меньшую нагрузку на систему:

format(string, sizeof(string), "%d, %d", color1++, color2++);

Пример 2.

Извлечем из переменной string три аргумента: UNIX время выдачи бана часа, UNIX время истечения бана чата и причину выдачи. Они записаны через пробел. UNIX время в обеих случаях приобретает целочисленный тип данных, а вот причина - строковый.  Следовательно, выглядеть будет так: dds[100]. 100 я указал для примера. Допустим, максимальная длина причины не должна превышать 100 символов. В целом это будет выглядеть так:

new argument1, argument2, argument3[100];
sscanf(string, "dds[100]", argument1, argument2, argument3);

Пример 3.

Создаем команду телепортации по указанным координатам. Допустим, координаты записаны через запятую в переменной string. В этом случае наш sscanf примет следующий вид:

new Float:x, Float:y, Float:z;
sscanf(string, "p<,>fff", x, y, z);

Пример 4.

Ситуация посложнее. В переменную записаны дата и время какого-либо события: "2017-05-25 22:00". Сначала нужно извлечь три аргумента целочисленного типа, записанных через тире, а затем два аргумента целочисленных типов, записанных через двоеточие:

new argument1, argument2, argument3, argument4, argument5;
sscanf(string, "p<->dddp<:>dd", argument1, argument2, argument3, argument4, argument5);

Ну и тогда в argument1 попадет 2017, в argument 2 - 05, в argument3 - 25, в argument 4 - 22, в аргумент 5 - 00.

Будет полезно при использовании данной функции в командах:

sscanf возвращает значение 0. Это значит, что для проверки, удалось ли найти все указанные аргументы нужно писать:

if(sscanf(string, "типы данных", argument1, ... argumentn)) return SendClientMessage(playerid, 0xFF0000FF, "Аргументы не найдены.");

и, соответственно,

if(!sscanf(string, "типы данных", argument1, ... argumentn)) return SendClientMessage(playerid, 0xFF0000FF, "Аргументы найдены.");

Пример команды /goto. Можно вводить координаты, можно вводить ID игрока, а можно просто ничего не вводить и телепортироваться на заданные кодом координаты:

CMD:goto(playerid, params[])
{
if(!strlen(params))//Если пользователь вообще ничего не ввел, телепортируем его по координатам, указанным ниже
return SetPlayerPos(playerid, ваша_координата_х, ваша_координата_y, ваша_координата_z);
new Float:x, Float:y, Float:z;//Создаем три новые переменные дробного типа, куда впоследствии запишем координаты игроков
if(!sscanf(params, "u", params[0]))//Если пользователь ввел одно целое число, скорее всего являющееся идом игрока:
{
if(params[0] == INVALID_PLAYER_ID)//Проверяем, в сети ли игрок
return SendClientMessage(playerid, 0xFF0000FF, "Указанный вами игрок не в сети");
GetPlayerPos(params[0], x, y, z);//Получаем позицию указанного игрока
SetPlayerPos(playerid, x, y, z);//Изменяем позицию нашу на позицию указанного игрока
return true;
}
if(!sscanf(params, "p<,>fff", x, y, z)//Проверяем, найдены ли три координаты дробного типа, записанные через запятую, в строке
return SetPlayerPos(playerid, x, y, z);//Если найдены, телепортируем на них игрока
return true;
}

Собственно это все. Автор: я, @Elrmrnt-Kritik.

 
Последнее редактирование модератором: