SAMP/sscanf
Плагин sscanf от автора Y_Less. Скачать актуальную версию плагина можно из раздела ресурсов. |
Описание: данный плагин позволяет "парсить" строку, вычленяя аргументы для требуемых параметров. Работает как с текстовыми файлами, так и с введённой строкой напрямую.
Цитата |
Данная версия плагина делает всё то же, что и предыдущая, только гораздо быстрее и гибче. — Написано Y_Less [Источник: документация по плагину] |
Подсказка |
Для использования добавьте в мод подключение инклюда:#include <sscanf2> Для подключения плагина к серверу на платформе с операционной системой Windows добавляем в конфигурационный файл server.cfg следующую строчку: plugins sscanf На *nix-подобных (Ubuntu, CentOS, Linux) системах необходимо дописывать расширение файла, поэтому пишем: plugins sscanf.so |
Примечание |
Не будет ошибкой указывать расширение файлов плагинов на платформе Windows. Так тоже будет работать:plugins sscanf.dll |
Цитата |
Новый инклюд определяет старую версию плагина и выдаёт ошибку. — Написано Y_Less [Источник: документация по плагину] |
Примечание |
Следите за тем, чтобы версия плагинов и инклюдов была одинакова, иначе сервер будет указывать на ошибки несовпадения версий в окне терминала (консоли). |
Примеры использования
В общем виде код выглядит примерно так:
if(sscanf(params, "ui", giveplayerid, amount))
{
return SendClientMessage(playerid, 0xFF0000AA, "Синтаксис: /givecash [playerid/name] [amount]");
}
Однако следует отметить, что sscanf можно использовать для любой обработки текста, которую вы хотите. Например, ini-процессор может выглядеть так:
if(sscanf(szFileLine, "p<=>s[8]s[32]", szIniName, szIniValue))
{
printf("Invalid INI format line");
}
Примечание |
Существует также альтернативное имя функции sscanf, чтобы избежать путаницы со стандартным sscanf в языке "C" - unformat.
if(unformat(params, "ui", giveplayerid, amount)) { return SendClientMessage(playerid, 0xFF0000AA, "Usage: /givecash <playerid/name> <amount>"); } |
Спецификаторы
Базовые спецификаторы (примеры использования букв u, i, s и других можно увидеть в коде выше). В таблице представлен расширенный спектр поддерживаемых спецификаторов.
Спецификатор(ы) | Формат | Примеры значений |
---|---|---|
i, d | Целое число | 1, 42, -10 |
c | Символ | a, o, * |
l | Логическое (булево) | true, false |
b | Бинарное | 01001, 0b1100 |
h, x | Шестнадцатеричное | 1A, 0x23 |
o | Восьмеричное | 045,12 |
n | Десятичное | 42, 0b010, 0xAC, 045 |
f | Дробное (с плавающей точкой) | 0.7, -99.5 |
g | Дробное (стандарт IEEE[1]) | 0.7, -99.5, INFINITY, -INFINITY, NAN, NAN_E |
u | Имя игрока/id (боты или игроки) | Y_Less, 0 |
q | Имя бота/id | ShopBot, 27 |
r | Имя игрока/id | Y_Less, 42 |
m | Цвет | {FF00AA}, 0xFFFFFFFF, 444 |
[1] IEEE (Институт инженеров электротехники и электроники) — международная некоммерческая ассоциация специалистов в области техники, мировой лидер в области разработки стандартов по радиоэлектронике, электротехнике и аппаратному обеспечению вычислительных систем и сетей.
Строки
Как и раньше, спецификатор s используется для указания типа данных, извлекаемых из строки, но теперь работThe specifier s is used, as before, for strings - but they are now more advanced. As before they support collection, so doing:
sscanf("hello 27", "si", str, val);
Выдаст:
hello 27
Код:
sscanf("hello there 27", "si", str, val);
Не сработает, потому что "there" не является числом. В данном случае код должен выглядеть так:
sscanf("hello there", "s", str);
Выдаст:
hello there
Поскольку в спецификаторе после s ничего нет, выдаёт всю строку. Чтобы избежать этого (ровно как и в ситуации, когда надо вывести строку до первого пробела), просто добавьте пробел:
sscanf("hello there", "s ", str);
Will give: Выдаст:
hello
Вы также можете экранировать части строк при помощи \\
sscanf("hello\\ there 27", "si", str, val);
Выдаст:
hello there 27
Примечание |
Экранирование указывается при помощи двух обратных косых черты (бэк-слешей), поскольку 1 используется компилятором. |
Однако все вышеприведённые примеры будут выдавать предупреждения на сервере, поскольку новая версия теперь имеет размеры массивов. Приведенный выше код должен выглядеть так:
new str[32], val;
sscanf("hello\\ there 27", "s[32]i", str, val);
Как видите, спецификатор формата теперь содержит длину целевой строки, гарантируя, что ваши строки никогда не могут переполниться и вызвать проблемы. Это может быть объединено с преобразованием в процессе компиляции:
#define STR_SIZE 32
new str[STR_SIZE], val;
sscanf("hello\\ there 27", "s[" #STR_SIZE "]i", str, val);
Подсказка |
Рекомендовано использовать [*] для передачи длины строки в качестве дополнительного параметра (смотри раздел «Предоставленные длины» ниже). В этом случае, когда вы меняете размер строки, вам не нужно менять свои спецификаторы. |
Упакованные строки
Данный вид спецификаторов обозначается литерами z, Z и возвращает упакованные строки. В остальном он идентичен s и S, документация по которым была выше.
Массивы
Одним из продвинутых новых спецификаторов является a, служащий для работы с массивами. Синтаксис аналогичен синтаксису строк с добавлением, как вы увидите позже, кода разделителя (делиметра):
new arr[5];
sscanf("1 2 3 4 5", "a<i>[5]", arr);
За спецификатором a сразу следует один тип, заключенный в угловые скобки - этот тип может быть любым из основных типов, перечисленных выше. За ним, как и в случае со строками, следует размер массива. Приведенный выше код поместит числа от 1 до 5 в 5 индексов переменной массива arr.
Важное |
В связи с особенностью обработки индексов массива, для распределения параметров из строки (обычно с командными процессорами используется params) необходимо создавать отдельные переменные непосредственно перед парсингом.
if(!strcmp(cmdtext, "/slap", true)) { new targetid, reason[32]; if(sscanf(cmdtext, "ds", targetid, reason)) return SendClientMessage(playerid, -1, "Синтаксис: /slap [id] [причина]"); // действие команды new string[144]; format(string, sizeof(string), "Вас ударили по причине: %s", reason); SendClientMessage(targetid, -1, string); return 1; } |