PDA

Просмотр полной версии : [CMD] Из двоичной системы счисления в десятичную



m1n1vv
25.07.2016, 00:04
Скрипт переводит числа из двоичной системы счисления в десятичную. Если в переменной sub будет не бинарное число, то скрипт прекратит работу с оповещением об ошибке.

CMD:binary(playerid, params[])
{
if (isnull(params))
return SendClientMessage(playerid, 0xAA3333AA, !"[Подсказка]: /b [двоичный код]");

static const
str[] = "Result: %i";

new
string[sizeof(str) + 11 - 2],
result;

Binary(params, result);

if (!result)
return SendClientMessage(playerid, -1, !"Error");

format(string, sizeof(string), str, result);
SendClientMessage(playerid, -1, string);

return 1;
}

stock Binary(const sub[], &result)
{
static
n,
i,
c;

result = i = 0;
n = strlen(sub);

while ((c = sub[i++]))
{
switch (c)
{
case 48, 49:
{
result += (c == 49) ? (1 << n - i) : (0);
}
default:
{
return 0;
}
}
}

return result;
}

Daniel_Cortez
25.07.2016, 02:14
Во-первых, в чём смысл команды? Просто вывести игроку, какое число он ввёл?
Если фишка в самой функции Binary, а не в команде, то и тему следовало создавать в разделе для функций.
UPD: Сначала по префиксу подумал, что тема находится в разделе "Команды", но только сейчас заметил, что на самом деле она в разделе "Скрипты", с префиксом "[CMD]", а показывается в ней работа функции. Логика, прощай.

Во-вторых, вы так любите велосипеды? Для считывания двоичного числа из строки давно существует sscanf2.


CMD:binary(playerid, params[])
{
extract params -> new bin:x; else // new x; if (sscanf(params, "b", x))
return SendClientMessage(playerid, -1, !"Использование: /binary [число в двоичной системе]");
static const fmt_str[] = "Вы ввели число %d.";
new string[sizeof(fmt_str) - 2 + 11];
format(string, sizeof(string), fmt_str, x);
return SendClientMessage(playerid, -1, string);
}

И только не нужно оправдываться, что ваша реализация сделана специально, "чтобы не подключать плагин ради одной задачи".
На дворе 2016 год и sscanf2 используется почти повсеместно, кроме лишь некоторых "гипотетических" модов, которые не используют команд и не работают со строками.
Я называю их "гипотетическими" потому, что обычно такие моды либо имеют неудобный пользовательский интерфейс (на одних лишь текстдравах и диалогах далеко не уедешь), либо они недалеки от простого "hello world", либо их создатели - нездоровые люди, одержимые идеей отказа от всех плагинов.
(Но я всё же надеюсь, что вы просто не знали о спецификаторе "b", ибо то оправдание в случае со sscanf2 выглядело бы очень глупо.)

В-третьих, вы сами не находите странным, что функция, предназначенная для преобразования из строки в число, показывает игрокам сообщения?
Реализация алгоритма должна быть изолирована от взаимодействия с пользователем. Как говорится, компот отдельно, мухи отдельно. Очевидно же.

m1n1vv
25.07.2016, 02:58
Если размышлять замкнуто, то да.
Не раз видел, что люди не используют sscanf2. Расизм? Я использовал cmd с sscanf, чтобы просто показать стока. Это можно было расписать и на команду и диалог, но у меня на это времени нет.
Вот это я не понял. Выводит всего 2 сообщения, о конечном результате или ошибке.

VVWVV
25.07.2016, 03:13
3. Вот это я не понял. Выводит всего 2 сообщения, о конечном результате или ошибке.




Реализация алгоритма должна быть изолирована от взаимодействия с пользователем.


Алгоритм - функция; Пользователь - вывод сообщений.

Вы могли сделать так:



CMD:b(playerid, params[])
{
if (isnull(params))
return SendClientMessage(playerid, 0xAA3333AA, !"[Подсказка]: /b [двоичный код]");

new result = Binary(params);
if (result)
{
new str[32 /* магия... */];
format(str, sizeof str, "%d", result);
SendClientMessage(playerid, -1, str);
}
else SendClientMessage(playerid, -1, !"Error");

return 1;
}




stock
Binary(playerid, sub[])
{
new
result;

for (new i = 0, n = strlen(sub) - 1; i <= n; i++)
{
switch (sub[i])
{
case '0', '1':
{
result += (sub[i] == '1') ? (1 << n - i) : (0);
}
default:
{
return 0;
}
}
}

return result;
}

Daniel_Cortez
25.07.2016, 07:03
Если размышлять замкнуто, то да.
Итак, тема создана в одном разделе, помечена, как будто находится в другом, а говорится в ней о третьем.
"Размышлять замкнуто"? Ок, если я не увидел в вашей теме некий "скрытый смысл", то, быть может, вы сами введёте в курс дела?



Не раз видел, что люди не используют sscanf2. Расизм?
Забыл ещё упомянуть про RLS (коих будет больше, чем всех остальных перечисленных вместе взятых) и им подобные примеры устаревшего кода. Усугубляет ситуацию ещё и то, что начинающие учатся на таком старомодном коде, а потом сами же усложняют себе жизнь отказом от современных решений, которые и удобнее (как в написании, так и в плане чтения кода), и производительнее прежних. И да, такой отказ можно классифицировать как болезнь: синдром утёнка.
sscanf2 - это своего рода швейцарский нож, только для скриптинга. Если знать, как им пользоваться, то ему найдётся применение в любом моде (кроме уже упомянутых мной выше хелловорлдов).
Разумеется, без sscanf2 можно обойтись, но во многих случаях это будет в ущерб читаемости и эффективности работы кода.



Вот это я не понял. Выводит всего 2 сообщения, о конечном результате или ошибке.
Вы там что-то говорили о "замкнутом мышлении"? Ладно, очередной спор всё равно ни к чему не приведёт, поэтому просто попробую помочь.
Если название функции гласит о том, что функция преобразует строку в число, то она должна выполнять эту и только эту задачу.
Что, если вам потребуется, чтобы функция не показывала никаких сообщений об ошибке? Будете передавать неправильный ID игрока, чтобы функция SendClientMessage работала вхолостую? Оно и ежу понятно, что это дурной тон.

Если нужно взаимодействовать с пользователем, это должно быть в коде, вызывающем ту функцию, т.е. в данном случае, за это должен отвечать обработчик команды.
При ошибке ввода можно сделать так, чтобы функция вернула 0, но этим можно создать неопределённость, поскольку 0 - это правильное число, которое может ввести пользователь. Отрицательные числа тоже правильные: допустим, игрок ввёл число из 32 двоичных разрядов - в этом случае самый старший разряд будет отвечать за знак.
Логично было бы сделать отдельный аргумент, передаваемый по ссылке, в который функция записывала бы статус успеха.


stock BinaryToInt(const str[], &bool:success)
{
success = false;
new result;
result = 0;
// ...
if (...) // Если что-то пошло не так
return 0; // В success уже записано false, просто выходим из функции
// ...
success = true;
return result;
}

Использовать эту функцию следует так:


new bool:success;
new x = BinaryToInt(params, success);
if (!success)
return SendClientMessage(playerid, -1, ...);

Правда, это не очень удобно, ведь нужно временно сохранить получившееся число в переменной, чтобы проверить успех работы функции.
Лучшим решением будет заставить функцию возвращать статус успеха напрямую, а само число - через один из аргументов.


stock bool:BinaryToInt(const str[], &result)
{
result = 0;
// ...
if (...) // Если что-то пошло не так
return false;
// ...
success = true;
return true;
}

Использование:


new x;
if (!BinaryToInt(params, x))
return SendClientMessage(playerid, -1, ...);

Намного удобнее. Функция выполняет только строго то, что должна, и нет никаких неопределённостей по поводу правильности ввода.

BadPawn
25.07.2016, 09:34
что означает символ перед result в шапке функции:


stock bool:BinaryToInt(const str[], &result)


&result

DeimoS
25.07.2016, 10:23
что означает символ перед result в шапке функции:


stock bool:BinaryToInt(const str[], &result)


&result

Вот тут, в самом конце, я давал описание:
[Урок] Всё о Stock (http://pro-pawn.ru/showthread.php?6570-%D0%92%D1%81%D1%91-%D0%BE-Stock)

m1n1vv
25.07.2016, 13:42
stock bool:BinaryToInt(const str[], &result)
{
result = 0;
// ...
if (...) // Если что-то пошло не так
return false;
// ...
success = true;
return true;
}
А откуда тут взялось success?


&result
Но куда оно вернет?

DeimoS
25.07.2016, 14:38
stock bool:BinaryToInt(const str[], &result)
{
result = 0;
// ...
if (...) // Если что-то пошло не так
return false;
// ...
success = true;
return true;
}
А откуда тут взялось success?

Явно обычная опечатка же. Можно было понять





&result
Но куда оно вернет?

В переменную, которую ты укажешь при вызове?

m1n1vv
18.10.2016, 19:03
Daniel_Cortez, давно хотел написать... Не забывай о максимальном количестве цифр в числе. sscanf это не переведет в десятичную систему:

1010110111001011010

DeimoS
18.10.2016, 20:20
Daniel_Cortez, давно хотел написать... Не забывай о максимальном количестве цифр в числе. sscanf это не переведет в десятичную систему:

1010110111001011010

Как и твоя, например, это

1001010100000010111110001111111111
Имхо, если взялся создавать "универсальный" (не знаю как ещё назвать) конвертер, стоит возвращать строку. Тогда можно действительно любое число перевести

m1n1vv
18.10.2016, 23:26
Как и твоя, например, это

1001010100000010111110001111111111
Имхо, если взялся создавать "универсальный" (не знаю как ещё назвать) конвертер, стоит возвращать строку. Тогда можно действительно любое число перевести

Убери 3 символа и сможет. У меня более работоспособней, так-как может перевести код длиннее. Число с количеством цифр больше 10 не выведешь. О значении и сам знаешь ).

Daniel_Cortez
19.10.2016, 18:10
Daniel_Cortez, давно хотел написать... Не забывай о максимальном количестве цифр в числе. sscanf это не переведет в десятичную систему:

1010110111001011010


#include <a_samp>
#include "../include/sscanf2.inc"

main()
{
static const binary_str[] = "1010110111001011010";
// Считывание числа
extract binary_str -> new bin:x; else // new x; if(sscanf(binary_str,"b",x))
printf("Failed to read the number");
printf("%s -> %d", binary_str, x);
// Проверка
new output[sizeof(binary_str)];
format(output, sizeof(output), "%b", x);
printf(
"%d -> %s - %s",
x, output,
(0 == strcmp(binary_str, output)) ? ("ok") : ("test failed")
);
}



1010110111001011010 -> 355930
355930 -> 1010110111001011010 - ok
Number of vehicle models: 0

...

vovandolg
19.10.2016, 19:10
И куда этот код пригодится?))
Работу хакера на РП придумать разве что и присунуть код для красоты)