Автор: Y_Less
Перевод: Pa4enka
Для начала работы с плагином достаточно добавить эту строку в мод (прим. после a_samp) :
#include < sscanf2 >
Файлы с расширениям .dll [Windows], .so[Linux] в папку plugins, а .inc в pawno/include; [/indent]
В server.cfg пропишите следующее: plugins sscanf
Основной код выглядит следующим образом:
if(sscanf(params, "ui", giveplayerid, amount)) return SendClientMessage(playerid, 0xFF0000AA, !"Используй: /givecash <playerid> <кол-во>");
Вместе с тем следует отметить, что sscanf может быть использован для любой обработки текста. Например, ini-процессор может выглядеть следующим образом:
if(sscanf(szFileLine, "p<=>s[8]s[32]", szIniName, szIniValue))
print("Invalid INI format line");
Существует также альтернативное имя функции, чтобы избежать путаницы со стандартным sscanf:
if (unformat(params, "ui", giveplayerid, amount)) return SendClientMessage(playerid, 0xFF0000AA, !"Используй: /givecash <playerid> <кол-во>");
СПЕЦИФИКАТОРЫ
1. Базовые
Таблица [Показать]
2. Строки
Спецификатор "s" используется, как и раньше, для строк - но теперь они более продвинутые.
sscanf("hello 27", "si", str, val);
Результат : hello и 27
Используем:
sscanf("hello there 27", "si", str, val);
Результат: неудача т.к «there» не целое число.
Используем:
sscanf("hello there", "s", str);
Результат: hello there
Используем:
sscanf("hello there", "s ", str);
// прим.: после s пробел
Результат: hello
Вы также можете избежать части строки с "\\" - обратите внимание, что два обратных слэша используется компилятором как один:
sscanf("hello\\ there 27", "si", str, val);
Результат:
hello there 27
Обратите внимание, что эти примеры будут выдавать предупреждения в консоль сервера, так как новая версия имеет нововведения. Теперь нужно обязательно указывать размер массива:
new
str[32],
val;
sscanf("hello\\ there 27", "s[32]i", str, val);
Как вы можете видеть - спецификатор формата теперь содержит длину строки.
Ветка 2.10.*: Теперь вы можете воспользоваться именными константами для объявления длинны строки.
#define STR_SIZE 32
new str[STR_SIZE], val;
sscanf("hello\\ there 27", "s[" #STR_SIZE "]i", str, val);
3. Запакованные строки
z и Z возвращают упакованные строки. В остальном они идентичны s и S.
4. Массивы
new arr[5];
sscanf("1 2 3 4 5", "a<i>[5]", arr);
После “a” спецификатора в <> указывается тип спецификатора(смотри «Спецификаторы»). Приведенный выше код заполнит цифрами массив "arr".
Массивы могут быть объединены со строками, указав размер строки в тип массива:
a<s[10]>[12]
«На выходе» получим массив из 12 строк, каждая длиной до 10 символов (9 + NULL).
5. Энум [прим. Enum]
Это, возможно, наиболее мощное дополнением к sscanf. Обновления дает возможность определить структуру перечисления в пределах спецификатора строки и считывать любые данные прямо в него.
enum E_DATA
{
E_DATA_C,
Float:E_DATA_X,
E_DATA_NAME[32],
E_DATA_Z
}
main
{
new var[E_DATA];
sscanf("1 12.0 Bob c", "e<ifs[32]c>", var);
}
е - начало "перечислений" <- Запуск спецификации структуры перечислении i - Целое число, соответствует E_DATA_C f - Float, соответствует E_DATA_X s [32] - строка 32 ячейки, соответствует E_DATA_NAME c - символ, соответствует E_DATA_Z > - Конец спецификации перечислений
Большинство, но не все, спецификаторы могут быть использованы внутри перечислений (в частности, массивов).
6. Динамическая длинна (ветка 2.10.*)
И строки, и массивы имеют длину, обычно указываемую в строке с помощью (скажем) s [32]. Однако у этой системы есть некоторые крайние ограничения - в первую очередь макросы. Этот код работать не будет:
#define LEN 32 sscanf(params, "s[LEN]", str);
Этот код будет работать:
#define LEN 32 sscanf(params, "s["#LEN"]", str);
Но этот код даже не компилируется:
#define LEN (32) sscanf(params, "s["#LEN"]", str);
Этот код будет работать, но это мягко говоря неудобно:
sscanf(params, "s[(32)]", str);
Этот код будет компилироваться, но тоже не будет работать:
#define LEN 8*4 sscanf(params, "s["#LEN"]", str);
По этой причине вы можете передавать длины строк и массивов в качестве дополнительных параметров, используя * для длины:
#define LEN 8*4 sscanf(params, "s[*]", LEN, str);
Длины отображаются ДО пункта назначения, сначала массивы, затем строки:
new int, arr[5][10], str[32]; sscanf(params, "ia<s[*]>[*]s[*]", int, sizeof (arr), sizeof (arr[]), arr, 32, str);
То же самое относится к строкам в перечислениях:
enum E_EXAMPLE
{
Float:FLOAT,
STR_1[32],
STR_2[64],
INT,
}
new dest[E_EXAMPLE];
sscanf(params, "e<fs[*]s[*]i>", _:STR_1 - _:FLOAT, 64, dest);
И для массивов пользователей:
new ids[3], i; sscanf(params, "u[*]", sizeof (ids), ids);
Данное нововведения позволяет вам передавать переменную длину, если вы не хотите использовать всю строку, и использовать всю мощь препроцессора для генерации длин во время компиляции. Он также обходит ошибку компилятора в строковую форму с использованием скобок в строках. Теперь также используется * для всех строк и массивов, поэтому точно так же будет полностью использовать препроцессор.
7. Quiet
Два новых спецификатора"{" и "}" - строки, которые считываются и проверяются, но не сохраняются. Например:
sscanf("42 -100", "{i}i", var);
Очевидно, что есть два числа и два "i", но только одна переменная возврата. В итоге, первый “i" не сохранится, но повлияет на возвращаемое значение. Приведенный выше код будет равен: "var" -100".
8. Поисковые запросы
Строки, заключенные в одиночные кавычки (') проверяются на наличие в основной строке:
sscanf("10 11 woo 12", "i'woo'i", var0, var1);
Результат:
10 12
Вы можете достичь того же эффекта с:
sscanf("10 11 woo 12", "i{is[1000]}i", var0, var1);
9. Enums (ветка 2.10.*)
Функция, аналогичная quiet, которая позволяет вам пропустить перезапись определенных частей перечисления:
e<ii-i-ii>
Здесь "-" является "минусом" и сообщает sscanf, что там есть элемент перечисления, но ничего не делать, поэтому, если у вас есть:
enum E
{
E_A,
E_B,
E_C,
E_D,
E_E
}
И вы хотели обновить только первые два и последнее поля и оставить все остальные нетронутыми, вы можете использовать этот спецификатор выше. Таким образом, sscanf знает, как пропускать память и сколько памяти пропускать. Обратите внимание, что это ничего не читает, поэтому вы также можете объединить это с quiet:
e<ii-i-i{ii}i>
Это прочитает два значения и сохранит их, пропустит две ячейки памяти, прочитает два значения и НЕ сохранит их, а затем прочитает и сохранит последнее значение. Таким образом, вы можете записать все значения для каждого слота в перечислении, но использовать только 3 из них. Обратите внимание, что то же самое и с E - если вы это сделаете:
E<ii-i-ii>
Вы должны указать ТОЛЬКО ТРИ значения по умолчанию, а не все пять:
E<ii-i-ii>(11, 22, 55)
10. Разделители
В предыдущей версии была эта функция. Но сейчас она изменила свой синтаксис. Раньше было:
sscanf("1,2,3", "p,iii", var0, var1, var2);
Сейчас:
sscanf("1,2,3", "p<,>iii", var0, var1, var2);
Старая версия разделителей будет доступна, но плагин сообщит вам, что нужно изменить ваш код согласно новому синтаксису.
Ветка 2.10.*: Теперь вы можете использовать необязательные разделители с помощью P (верхний регистр p для соответствия другим необязательным спецификаторам). Они не являются обязательными в том смысле, что вы указываете несколько разделителей, и любой из них может использоваться для завершения следующего символа:
sscanf("(4, 5, 6, 7)", "P<(),>{s[2]}iiii", a, b, c, d);
Здесь используется quiet, чтобы игнорировать все, что находится перед первым (, а затем использовать несколько разделителей для завершения всего текста. Пример:
sscanf("42, 43; 44@", "P<,;@>a<i>[3]", arr);
11. Необязательные спецификаторы
КАЖДЫЙ спецификатор формата (то есть, все, за исключением ''{} и р) теперь имеет дополнительный спецификатор, который пишется с заглавной буквы.
sscanf("", "I(12)", var);
В "()" s (круглые скобки) содержат значения по умолчанию для дополнительного целого числа и, как основная строка не содержит никаких данных, значение "вар" становится "12".
12. Пользователи («Users»)
"u", "q" и "R" спецификаторы поиска пользователя по имени или ID. Метод этого поиска изменился в последних версиях "sscanf".
Кроме того, "U", "Q" и "R", могут взять имя или идентификатор в качестве значения по умолчанию, и sscanf не будет пытаться определить, является ли этот ID online.
Раньше:
sscanf(params, "U(Y_Less)", id);
if (id == INVALID_PLAYER_ID)
{
// Y_Less или введенный игрок не подключен.
}
Сейчас:
sscanf(params, "U(-1)", id);
if (id == -1)
{
// Ни один игрок не был введен.
}
else if (id == INVALID_PLAYER_ID)
{
// Введенный игрок не подключен.
}
Теперь пользователи могут при необходимости возвращать массив пользователей, а не только один. Этот массив представляет собой список совпадающих идентификаторов, а затем "INVALID_PLAYER_ID". Например, на сервере играют:
Ники игроков [Показать]
Код:
new ids[3], i;
if (sscanf("Le", "?<MATCH_NAME_PARTIAL=1>u[3]", ids)) print("Ошибка");
for (i = 0; ids[i] != INVALID_PLAYER_ID; ++i)
{
if (ids[i] == cellmin)
{
print("Слишком много совпадений");
break;
}
printf("id = %d", ids[i]);
}
if (i == 0) print("Совпадений не найдено")
Выведет:
id = 0 id = 1 Слишком много совпадений
Ищем «Les», получим:
id = 0 ; id = 1
И поиск без использования "MATCH_NAME_PARTIAL" даст:
Совпадений не найдено
12. Пользовательские спецификаторы
Последняя версия sscanf добавляет новый "К" спецификатор, чтобы позволить вам создавать свои собственные спецификаторы в PAWN:
SSCANF:playerstate(string[])
{
if ('0' <= string[0] <= '9')
{
new
ret = strval(string);
if (0 <= ret <= 9)
{
return ret;
}
}
else if (!strcmp(string, "PLAYER_STATE_NONE")) return 0;
else if (!strcmp(string, "PLAYER_STATE_ONFOOT")) return 1;
else if (!strcmp(string, "PLAYER_STATE_DRIVER")) return 2;
else if (!strcmp(string, "PLAYER_STATE_PASSENGER")) return 3;
else if (!strcmp(string, "PLAYER_STATE_WASTED")) return 7;
else if (!strcmp(string, "PLAYER_STATE_SPAWNED")) return 8;
else if (!strcmp(string, "PLAYER_STATE_SPECTATING")) return 9;
}
Код выше добавит "playerstate" спецификатор, что позволяет сделать следующее:
sscanf(params, "uk<playerstate>", playerid, state);
Эта система поддерживает дополнительные пользовательские спецификаторы без дополнительного кода PAWN:
sscanf(params, "uK<playerstate>(PLAYER_STATE_NONE)", playerid, state);
ОПЦИИ
1. OLD_DEFAULT_NAME:
Поведение "U", "Q" и "R" были изменены, чтобы принять любое количество по умолчанию, вместо подключенного игрока.
2. MATCH_NAME_PARTIAL:
В настоящее время sscanf будет искать игроков по имени, и будет ВСЕГДА искать игрока, имя которого начинается с указанной строки. Если у вас есть, скажем, "[CLAN] Y_Less", и кто-то типа "Y_Less", sscanf не найдет "[CLAN] Y_Less", потому что имя не начинается с указанным именем.
3. CELLMIN_ON_MATCHES:
Вне зависимости от значения "MATCH_NAME_PARTIAL", первый найденный игрок всегда будет показан, так что если вы делаете поиск для "_" на сервере RP, вы можете получить практически любого человека. Для того, чтобы обнаружить более чем одного игрока, то sscanf возвращает идентификатор "cellmin":
sscanf(params, "?<CELLMIN_ON_MATCHES=1>U(-1)", id);
if (id == -1)
{
// ничего не ввели
}
else if (id == cellmin)
{
// найдено несколько игроков
}
else if (id == INVALID_PLAYER_ID)
{
// Игрок не подключен
}
else
{
// Найден 1(!) игрок
}
4. SSCANF_QUIET:
Не выводить какие-либо ошибки на консоль. На самом деле не рекомендуется, если вы не знаете, что ваш код является стабильным.
ОШИБКИ И ПРЕДУПРЕЖДЕНИЯ
Ошибки и предупреждения [Показать]
Специально для Pawn-Wiki.Ru!
Распространение без разрешения автора строго запрещено!
Оригинальная документация | Автор: Y_Less
extract | Автор: m1n1vv
Скачать последний релиз 2.8.*:
sscanf-2.8.3.zip
[55,14К]Скачать последний релиз 2.10.*:
sscanf-2.10.2.zip
[70,46К]
Сообщение отредактировал Romzes: 17 марта 2023 - 02:57
Причина редактирования: fix таблицы
Вход
Регистрация
Помощь













