PDA

Просмотр полной версии : [Урок] Упрощаем работу с длинным текстом.



Flime
22.08.2014, 23:31
Здравствуйте!

Не редко я был свидетелем вот таких кодов:



static const _n[][] =
{
"1\n",//0
"2\n",//1
"3\n",//2
"4\n",//3
"5"//4
}
format(string, sizeof(string),"%s%s%s%s%s%s", _n[0],_n[1],_n[2],_n[3],_n[5]);
ShowPlayerDialog(playerid, 1, DIALOG_STYLE_LIST, "Текст", string, "Закрыть", "");


Данный код является не читабельным (по крайне мере, для меня.)
Приходится постоянно считать количество "%s".
Обращаться с данным кодом тяжело, когда большое количество строк.

Как это исправить?

1) Данный метод подходит, когда есть некоторые переменные, которые нужно внедрить в текст.



new string[62];
format(string, sizeof(string), "1. %d",kills);
format(string, sizeof(string), "%s\n2. %d",string,kills);
format(string, sizeof(string), "%s\n3. %d",string,kills);
format(string, sizeof(string), "%s\n4. %d",string,kills);
format(string, sizeof(string), "%s\n5. %d",string,kills);
ShowPlayerDialog(playerid, 1, DIALOG_STYLE_LIST, "Текст", string, "Закрыть", "");

2) Можно воспользоваться циклом.

Данный метод подходит для вывода большого текста, где нету переменных, которые нужно вставлять в текст. (Пример: Привила сервера.)



static const _n[5][] =
{
"1",//0
"2",//1
"3",//2
"4",//3
"5"//4
}
new string[5];
for(new j; j < 5; j++) format(string, sizeof(string),"%s%s\n", string, n[j]);
ShowPlayerDialog(playerid, 1, DIALOG_STYLE_LIST, "Текст", string, "Закрыть", "");


3) В этом методе при выводе диалога игроку будет показано содержимое всех строк. В секции данных эти строки располагаются непосредственно друг за другом и можно "сцепить" их, заменив символ конца строки в long_string на любой другой символ (в даном случае - перенос строки).
При этом не нужно будет перед каждым использованием выделять место в стеке и соединять их - всё уже сделано.
Пример:

Ко всем new добавляем:


new
long_string[] =
"Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.\n"\
"Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.",
long_string_1[] =
"Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur.\n"\
"Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.";


В OnGameModeInit добавляем:



long_string[sizeof(long_string)-1] = '\n';
long_string_1[sizeof(long_string_1)-1] = '\0';


В место, куда нужно:

ShowPlayerDialog(playerid, 0, DIALOG_TYPE_MSGBOX, "Текст", long_string, "Закрыть", "");

Тем самым мы сделали код более понятным. С ним проще обращаться.

Помощь: Tracker1, Daniel_Cortez

Копирование данной статьи без разрешения автора запрещено!

DeimoS
22.08.2014, 23:44
Таким способом можно любые строки скреплять. Не обязательно те, куда не надо ничего выводить. Скажу даже большее: с помощью format можно записывать в массивы нужные вам значения (имена/пароли и т.п). Это очевидно, но для многих это будет открытием

Daniel_Cortez
23.08.2014, 02:17
А теперь позвольте показать вам небольшой фокус:


new
long_string[] =
"Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.\n"\
"Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.",
long_string_1[] =
"Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur.\n"\
"Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.";


public OnGameModeInit()
{
long_string[sizeof(long_string)-1] = '\n';
long_string_1[sizeof(long_string_1)-1] = '\0';
}


CMD:loremipsum(playerid, params[])
return ShowPlayerDialog(playerid, 0, DIALOG_TYPE_MSGBOX, "??", long_string, "Close", "");

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

Avertus
13.11.2014, 20:20
Ну и в продолжение темы приведу вполне работоспособный и красивый вариант:


#define s1 "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n"
#define s2 "BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB\n"
#define s3 "CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC\n"
#define s4 "DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD\n"
#define s5 "EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE\n"
#define s6 "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF\n"
#define s7 "GGGGGGGGGGGGGGGGGGGGGGGGGGGGGGG\n"
#define s9 "HHHHHHHHHHHHHHHHHHHHHHHHHHHHHHH\n"
#define s8 "IIIIIIIIIIIIIIIIIIIIIIIIIIIIIII\n"
#define s0 "JJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJ\n"
// #define ss (s1 s2 s3 s4 s5 s6 s7 s8 s9 s0 s0 s0 s0 s0 s0 s0 s0 s0 s0) если используется в одном метсе

new const ss[] = s1 s2 s3 s4 s5 s6 s7 s8 s9 s0 s0 s0 s0 s0 s0 s0 s0 s0 s0;

Если текст используется более чем в одном месте, то его стоит сохранить в массив, дабы не «раздувать» amx файл.

DeimoS
13.11.2014, 20:27
Ну и в продолжение темы приведу вполне работоспособный и красивый вариант:


#define s1 "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n"
#define s2 "BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB\n"
#define s3 "CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC\n"
#define s4 "DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD\n"
#define s5 "EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE\n"
#define s6 "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF\n"
#define s7 "GGGGGGGGGGGGGGGGGGGGGGGGGGGGGGG\n"
#define s9 "HHHHHHHHHHHHHHHHHHHHHHHHHHHHHHH\n"
#define s8 "IIIIIIIIIIIIIIIIIIIIIIIIIIIIIII\n"
#define s0 "JJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJ\n"
// #define ss (s1 s2 s3 s4 s5 s6 s7 s8 s9 s0 s0 s0 s0 s0 s0 s0 s0 s0 s0) если используется в одном метсе

new const ss[] = s1 s2 s3 s4 s5 s6 s7 s8 s9 s0 s0 s0 s0 s0 s0 s0 s0 s0 s0;

Если текст используется более чем в одном месте, то его стоит сохранить в массив, дабы не «раздувать» amx файл.

И компилятор, в лучшем случае, просто зависнет...

Avertus
13.11.2014, 21:25
И компилятор, в лучшем случае, просто зависнет...

Вовсе нет. Я то протестировал вначале прежде чем писать. Правда только на русифицированном компиляторе (http://pro-pawn.ru/showthread.php?3586-Русифицированный-компилятор-Pawn). Сейчас попробую на стандартном.

L0ndl3m
13.11.2014, 21:35
Вовсе нет. Я то протестировал вначале прежде чем писать. Правда только на русифицированном компиляторе (http://pro-pawn.ru/showthread.php?3586-Русифицированный-компилятор-Pawn). Сейчас попробую на стандартном.
Вот именно, в стандартном компиляторе максимальная длина строки 511 символов. Если будут задекларированы большие строки в макросах, то будут проблемы. Как по мне, данный вариант некое "извращение", если его можно так назвать. Если создавать для каждых строк макросы, не думаю, что это будет удобно самому разработчику ( не всегда ). Если нужно будет изменить текст быстрым способом, так клавиши CTRL + F никто не отменял.

Avertus
13.11.2014, 21:42
Вот именно, в стандартном компиляторе максимальная длина строки 511 символов..

Ну да, попробовал стандартным, повесился. А жаль. =(

DeimoS
13.11.2014, 22:37
Ну да, попробовал стандартным, повесился. А жаль. =(

Ты только теперь процесс убить не забудь ;) А то так и будет висеть до перезагрузки и жрать ресурсы системы

codeo
15.11.2014, 19:31
Подскажите, почему не открывается диалог с текстом?


new _n[11][520]=
{
"{FF6600}1. {0099FF}текст",
"{FF6600}1. {0099FF}текст",
"{FF6600}1. {0099FF}текст",
"{FF6600}1. {0099FF}текст",
"{FF6600}1. {0099FF}текст",
"{FF6600}1. {0099FF}текст",
"{FF6600}1. {0099FF}текст",
"{FF6600}1. {0099FF}текст",
"{FF6600}1. {0099FF}текст",
"{FF6600}1. {0099FF}текст",
"{FF6600}1. {0099FF}текст"
};




CMD:prav( playerid, params[ ] )
{
new string[520];
for(new j; j < 11;j++ ) format(string, sizeof(string),"%s%s\n", string, _n[j]);
ShowPlayerDialog(playerid, 564564, DIALOG_STYLE_MSGBOX, "{008080}Правила", string, "Выбрать", "Отмена");
return 1;
}

DeimoS
15.11.2014, 19:33
ID слишком большой, не?

codeo
15.11.2014, 19:38
Точно, спасибо

Daniel_Cortez
15.11.2014, 20:32
Подскажите, почему не открывается диалог с текстом?
http://wiki.sa-mp.com/wiki/ShowPlayerDialog

Max dialogid is 32767.

Avertus
03.12.2014, 09:56
long_string[sizeof(long_string)-1] = '\n';
long_string_1[sizeof(long_string_1)-1] = '\0';

Для чего нужно таким способом добавлять конец строки и перенос? Если это не использовать, что случится?

seriu
22.01.2016, 22:21
long_string[sizeof(long_string)-1] = '\n';
long_string_1[sizeof(long_string_1)-1] = '\0';

Для чего нужно таким способом добавлять конец строки и перенос? Если это не использовать, что случится?
Не скомпилируется код, точнее выдаст "warning 203 symbol is never used long_string_1" да и не будут строки скреплены.

VVWVV
22.01.2016, 22:31
Не скомпилируется код, точнее выдаст "warning 203 symbol is never used long_string_1" да и не будут строки скреплены.

Эм... Вы о чём? Данная ошибка возникает (предупреждение) из-за того, что нигде не используется. В первом случае мы заменяем знак конца строки на знак перехода строки на новую, что, соответственно, говорит о сцепке двух строк. Во-втором случае мы ставим знак конца строки.

seriu
22.01.2016, 22:45
Эм... Вы о чём? Данная ошибка возникает (предупреждение) из-за того, что нигде не используется. В первом случае мы заменяем знак конца строки на знак перехода строки на новую, что, соответственно, говорит о сцепке двух строк. Во-втором случае мы ставим знак конца строки.

Это я про то, что если не использовать

long_string_1[sizeof(long_string_1)-1] = '\0';
То вы даст warning.... и строки не скрепятся.
п.с. при скреплении последующие использование как long_string вместо long_string и long_string_1 след. long_string_1 не где не используется отсюда предупреждение и строки не скрепляются.

VVWVV
22.01.2016, 22:53
Это я про то, что если не использовать

long_string_1[sizeof(long_string_1)-1] = '\0';
То вы даст warning.... и строки не скрепятся.
п.с. при скреплении последующие использование как long_string вместо long_string и long_string_1 след. long_string_1 не где не используется отсюда предупреждение и строки не скрепляются.

Конечно, вы же её не используете... А строки все равно скрепятся, ибо стоит знак перехода на новую строку.

Daniel_Cortez
22.01.2016, 22:58
Это я про то, что если не использовать

long_string_1[sizeof(long_string_1)-1] = '\0';
То вы даст warning.... и строки не скрепятся.
п.с. при скреплении последующие использование как long_string вместо long_string и long_string_1 след. long_string_1 не где не используется отсюда предупреждение и строки не скрепляются.

#pragma unused long_string_1

seriu
22.01.2016, 23:41
Конечно, вы же её не используете... А строки все равно скрепятся, ибо стоит знак перехода на новую строку.

Не скрепляются, проверено в игре.
p.s DC

#pragma unused только избавит от предупреждения, строки не скрепятся.




п.с проверял на моде с нуля с 4. значениями

пример кода

static
long_string[] = "очень большой текст",
long_string1[] = "ну уж очень большой текст",
long_string2[] = "ну большой, но не больше 500 символов",
long_string3[] = "меньше чем все остальные остаток от long_string2";



//Работает:

public OnGameModeInit()
{
long_string[sizeof(long_string)-1] = '\n';
long_string1[sizeof(long_string1)-1] = '\n';
long_string2[sizeof(long_string2)-1] = '\n';
long_string3[sizeof(long_string3)-1] = '\0';
}

//Не работает:

public OnGameModeInit()
{
long_string[sizeof(long_string)-1] = '\n';
long_string1[sizeof(long_string1)-1] = '\n';
long_string2[sizeof(long_string2)-1] = '\n';
//long_string3[sizeof(long_string3)-1] = '\0';
}

//Не работает:

public OnGameModeInit()
{
long_string[sizeof(long_string)-1] = '\n';
long_string1[sizeof(long_string1)-1] = '\n';
long_string2[sizeof(long_string2)-1] = '\n';
//long_string3[sizeof(long_string3)-1] = '\0';
#pragma unused long_string3
}

п.с после long_string3 больше нету масивов.

Desulaid
23.01.2016, 02:17
seriu, возможно, следующие слова будут для тебя шоком, но прими их и постарайся со временем их осознать. Слушай. После объявления массива/переменной ее надо использовать, ибо зачем тогда объявлять? :dntknw:

http://i.imgur.com/gFldD11.png

seriu
23.01.2016, 02:37
seriu, возможно, следующие слова будут для тебя шоком, но прими их и постарайся со временем их осознать. Слушай. После объявления массива/переменной ее надо использовать, ибо зачем тогда объявлять? :dntknw:


http://i.imgur.com/2YFMYAT.jpg

Untonyst, Возможно для тебя это будет чудом, но когда делаешь так:

public OnGameModeInit()
{
long_string[sizeof(long_string)-1] = '\n';
long_string1[sizeof(long_string1)-1] = '\n';
long_string2[sizeof(long_string2)-1] = '\n';
long_string3[sizeof(long_string3)-1] = '\0';
}

Далее мы используем только так

printf("%s",long_string);

т.е long_string1,long_string2,long_string3 мы НЕЕЕЕЕ используем.

Daniel_Cortez
23.01.2016, 08:55
http://i.imgur.com/2YFMYAT.jpg

Untonyst, Возможно для тебя это будет чудом, но когда делаешь так:

public OnGameModeInit()
{
long_string[sizeof(long_string)-1] = '\n';
long_string1[sizeof(long_string1)-1] = '\n';
long_string2[sizeof(long_string2)-1] = '\n';
long_string3[sizeof(long_string3)-1] = '\0';
}

Далее мы используем только так

printf("%s",long_string);

т.е long_string1,long_string2,long_string3 мы НЕЕЕЕЕ используем.
long_string1 и long_string2 таки используются из-за присвоения им значений и будут скрепляться.
Тем не менее, я проверил: если не использовать последний массив (long_string3) (как было подмечено, достаточно записать тот же '\0' в конец строки), то этот массив использоваться не будет, компилятор уберёт его содержимое из секции данных.
После объединения строк и выводе long_string в лучшем случае после long_string2 ничего не выведется, в худшем - выведется каша из случайных символов или произойдёт краш.
Как оказалось, трюк с #pragma unused не работает и компилятор удаляет строку, что есть странно, т.к. если использовать эту директиву на локальном массиве, то компилятор не уберёт его и под него будет выделено место в стеке.
Похоже, что этот трюк с #pragma unused работает только на локальных массивах. Спасибо, что заметили ошибку.
UPD: Обновил пример кода в посте на 1-й странице.

denis01
18.05.2016, 08:20
Что обозначает - 1 здесь? [sizeof(long_string)-1]

L0ndl3m
18.05.2016, 18:36
Что обозначает - 1 здесь? [sizeof(long_string)-1]
Так как все строки в памяти разделяются символом '\0' (символ конца строки), и sizeof возвращает размера массива (вместе с этим нулевым символом), то нужно вычитать единицу, дабы не засчитывался этот спец-символ.