PDA

Просмотр полной версии : [Вопрос] Форматирование данных



Wolfgang
13.10.2020, 23:39
Приветствую! Хотелось уточнить, как лучше обрабатывать данные перед и в момент форматирования. Рационально ли привязывать данные к отдельной переменной, массиву или константе(наблюдал подобное в гейммодах и стандартных скриптах сампа от самп тим). Приведу пример для понимания:


stock MyFunc(playerid)
{
new MFCaption[] = "Caption";
new MFInfo[] = "Your nick: %s";
new MFButton1[] = "Button1";
new MFButton2[] = "Button2";
new MFEdit[sizeof(MFInfo)+(MAX_PLAYER_NAME-2)];
GetPlayerName(playerid, MFEdit, sizeof(MFEdit));
format(MFEdit, sizeof(MFEdit), MFInfo, MFEdit);
ShowPlayerDialog(playerid, 0, 0, MFCaption, MFEdit, MFButton1, MFButton2);
return 1;
}

P.S.: Код накидал с помощью телефона за несколько минут, он не оптимизирован и необходим чисто для примера. Хотелось бы узнать мнение Daniel_Cortez и DeimoS.

Shaolinka
14.10.2020, 01:07
Приветствую! Хотелось уточнить, как лучше обрабатывать данные перед и в момент форматирования. Рационально ли привязывать данные к отдельной переменной, массиву или константе(наблюдал подобное в гейммодах и стандартных скриптах сампа от самп тим). Приведу пример для понимания:


stock MyFunc(playerid)
{
new MFCaption[] = "Caption";
new MFInfo[] = "Your nick: %s";
new MFButton1[] = "Button1";
new MFButton2[] = "Button2";
new MFEdit[sizeof(MFInfo)+(MAX_PLAYER_NAME-2)];
GetPlayerName(playerid, MFEdit, sizeof(MFEdit));
format(MFEdit, sizeof(MFEdit), MFInfo, MFEdit);
ShowPlayerDialog(playerid, 0, 0, MFCaption, MFEdit, MFButton1, MFButton2);
return 1;
}

P.S.: Код накидал с помощью телефона за несколько минут, он не оптимизирован и необходим чисто для примера. Хотелось бы узнать мнение Daniel_Cortez и DeimoS.

Обычный текст можно можно без записи в массив/константу. Форматированный желательно в переменную(click (http://pro-pawn.ru/showthread.php?13388-%D0%9F%D0%BE%D0%B4%D1%81%D1%87%D1%91%D1%82-%D1%80%D0%B0%D0%B7%D0%BC%D0%B5%D1%80%D0%B0-%D1%84%D0%BE%D1%80%D0%BC%D0%B0%D1%82%D0%B8%D1%80%D1%83%D0%B5%D0%BC%D0%BE%D0%B9-%D1%81%D1%82%D1%80%D0%BE%D0%BA%D0%B8))

Если же текста довольно много, рекомендуется создать массив(имя фракций тому пример).

https://i.imgur.com/BMqhIl6.png
Создай отдельно массив для ника и текста, а то в массив MFEdit изначально записывается имя игрока, потом же ты пытаешься записать в тот же массив иные данные. Если попытаешься отпринтить, то должно вывести нечто подобное: получаемыйник + Your Nick: получаемый ник

DeimoS
14.10.2020, 08:45
Я не использую и не советую использовать данный вариант подсчёта длинны текста (https://pro-pawn.ru/showthread.php?13388-%D0%9F%D0%BE%D0%B4%D1%81%D1%87%D1%91%D1%82-%D1%80%D0%B0%D0%B7%D0%BC%D0%B5%D1%80%D0%B0-%D1%84%D0%BE%D1%80%D0%BC%D0%B0%D1%82%D0%B8%D1%80%D1%83%D0%B5%D0%BC%D0%BE%D0%B9-%D1%81%D1%82%D1%80%D0%BE%D0%BA%D0%B8). Почему - писал там же (https://pro-pawn.ru/showthread.php?13388-%D0%9F%D0%BE%D0%B4%D1%81%D1%87%D1%91%D1%82-%D1%80%D0%B0%D0%B7%D0%BC%D0%B5%D1%80%D0%B0-%D1%84%D0%BE%D1%80%D0%BC%D0%B0%D1%82%D0%B8%D1%80%D1%83%D0%B5%D0%BC%D0%BE%D0%B9-%D1%81%D1%82%D1%80%D0%BE%D0%BA%D0%B8&p=84685&viewfull=1#post84685). Если вкратце, то в любых ситуациях данный вариант подсчёта лишь раздувает код за счёт лишних строк, не прибавляя, при этом, какого-либо удобства.

Гораздо удобнее и эффективнее начать использовать тот же Sublime Text 3, в котором, при выделении текста, показывается количество символов в нём. Собственно, после этого просто просматриваешь строку и прямо на ходу отнимаешь от того значения, которое выдал редактор, все спецификаторы и спец-символы, получая длину строки без спецификаторов. А уже дальше так же составляешь формулу, вписывая и прибавляя значение для каждого спецификатора. Что-то по типу такого:

https://i.imgur.com/zppgFRc.png
Так как в конце строки стоит спецификатор - его можно не выделять, чтоб сразу не учитывать его при подсчёте. В итоге, отнимаем оставшиеся 3 спецификатора (51-6 = 45) и записываем это значение в размер массива.

Далее начинаем составлять формулу:
1) ID игрока не может быть длиннее 999, так что можно указать цифру "3", но лучше для этого значения создать макрос/константу, а-ля
const MAX_PLAYERS_LEN = 3;
на случай, если вдруг однажды количество слотов изменится.

2) Для ника игрока есть макрос MAX_PLAYER_NAME

3) Для уровня игрока можно указать значение "11", так как 11 - это то количество символов, которое может быть в минимально возможном значении, записанном в 4 байта: -2147483648.

4) Для скина можно так же указать "3", так как максимальный ID скина - 311. Но и тут лучше обзавестись макросом/константой, как и в случае с ID игрока.

5) Осталось ко всей этой формуле прибавить единицу, дабы в строке было место для хранения нуль-символа.

В итоге получится такой код:
new string[45+MAX_PLAYERS_LEN+11+MAX_SKIN_LEN+1];
format(string, sizeof(string), "Ник игрока с ID %d - %s. Уровень игрока: %d. Скин: %d", playerid, player_name, player_level, player_skin);
SendClientMessage(playerid, -1, string);

То бишь, на выходе получается та же самая формула (при составлении которой ты делаешь то же самое, что и в варианте Daniel Cortez), только, при этом, у тебя не будет лишней строки в коде. Ну и в комментариях к той статье (на которые я оставлял ссылку выше) я описывал ситуацию, когда, чем строка длиннее, тем сложнее будет изменять формулу для ситуаций с использованием варианта от Daniel Cortez.

punkochel
14.10.2020, 09:44
DeimoS конечно времени потратил на пост)
Статья на данную тему есть здесь: https://pro-pawn.ru/showthread.php?13388-%D0%9F%D0%BE%D0%B4%D1%81%D1%87%D1%91%D1%82-%D1%80%D0%B0%D0%B7%D0%BC%D0%B5%D1%80%D0%B0-%D1%84%D0%BE%D1%80%D0%BC%D0%B0%D1%82%D0%B8%D1%80%D1%83%D0%B5%D0%BC%D0%BE%D0%B9-%D1%81%D1%82%D1%80%D0%BE%D0%BA%D0%B8

DeimoS
14.10.2020, 11:42
DeimoS конечно времени потратил на пост)
Статья на данную тему есть здесь: https://pro-pawn.ru/showthread.php?13388-%D0%9F%D0%BE%D0%B4%D1%81%D1%87%D1%91%D1%82-%D1%80%D0%B0%D0%B7%D0%BC%D0%B5%D1%80%D0%B0-%D1%84%D0%BE%D1%80%D0%BC%D0%B0%D1%82%D0%B8%D1%80%D1%83%D0%B5%D0%BC%D0%BE%D0%B9-%D1%81%D1%82%D1%80%D0%BE%D0%BA%D0%B8

Эмм, я, если что, на эту статью и ссылаюсь, а так же объясняю почему я считаю, что использовать такой метод не стоит. Стоило сначала прочитать что я писал, прежде чем отвечать :)

Wolfgang
14.10.2020, 16:47
А что думаешь насчёт подобного хранения данных(текста)?:


new MFCaption[] = "Caption";
new MFButton1[] = "Button1";
new MFButton2[] = "Button2";
ShowPlayerDialog(playerid, 0, 0, MFCaption, MFEdit, MFButton1, MFButton2);

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

SteveStage
14.10.2020, 19:41
А что думаешь насчёт подобного хранения данных(текста)?:


new MFCaption[] = "Caption";
new MFButton1[] = "Button1";
new MFButton2[] = "Button2";
ShowPlayerDialog(playerid, 0, 0, MFCaption, MFEdit, MFButton1, MFButton2);

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

Зачем выделять в стеке 3 массива, когда можно передать их как аргументы нативной функции?

execution
14.10.2020, 20:27
Зачем выделять в стеке 3 массива, когда можно передать их как аргументы нативной функции?
Память под эти самые аргументы из не откуда берётся?

DeimoS
15.10.2020, 13:10
А что думаешь насчёт подобного хранения данных(текста)?:


new MFCaption[] = "Caption";
new MFButton1[] = "Button1";
new MFButton2[] = "Button2";
ShowPlayerDialog(playerid, 0, 0, MFCaption, MFEdit, MFButton1, MFButton2);

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

А зачем оно надо? Твой текст, который ты собираешься записывать в локальные переменные, всё равно будет хранится в глобальном сегменте данных. То бишь, ты, по сути, сначала записываешь текст в сегмент данных (при старте сервера), а при вызове этого кода будешь копировать текст в стек. Если и делать подобное, то только так:


static const MFCaption[] = "Caption";
static const MFButton1[] = "Button1";
static const MFButton2[] = "Button2";
ShowPlayerDialog(playerid, 0, DIALOG_STYLE_MSGBOX, MFCaption, MFEdit, MFButton1, MFButton2);

Создавая не локальные переменные, а глобальные. Избавившись тем самым от лишнего копирования данных из глобального сегмента данных в стек.

Хотя лично я в этом не вижу ничего удобного. Наоборот это только захламляет код лишними строками и усложнит его редактирование, если ты вдруг решишь между ShowPlayerDialog и переменными вставить какой-либо ещё код.
Уж лучше просто переносами и табуляцией отделять параметры друг от друга:
ShowPlayerDialog(playerid, 0, DIALOG_STYLE_MSGBOX, "Caption",
"{FFFFFF}\
Строка 1\n\
Строка 2\n\
\n\
Строка 3\n\
",
"Button_1", "Button_2");

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

DeimoS
15.10.2020, 13:13
Память под эти самые аргументы из не откуда берётся?

От того, что он выделит память под локальные переменные, память под хранение данных о вызове функции выделяться не перестанет. Так что он прав, хоть и выразился не очень внятно.