Просмотр полной версии : [Урок] Упрощаем работу с длинным текстом.
Здравствуйте!
Не редко я был свидетелем вот таких кодов:
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
Копирование данной статьи без разрешения автора запрещено!
Таким способом можно любые строки скреплять. Не обязательно те, куда не надо ничего выводить. Скажу даже большее: с помощью 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 на любой другой символ (в даном случае - перенос строки).
При этом не нужно будет перед каждым использованием выделять место в стеке и соединять их - всё уже сделано.
Ну и в продолжение темы приведу вполне работоспособный и красивый вариант:
#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 файл.
Ну и в продолжение темы приведу вполне работоспособный и красивый вариант:
#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 файл.
И компилятор, в лучшем случае, просто зависнет...
И компилятор, в лучшем случае, просто зависнет...
Вовсе нет. Я то протестировал вначале прежде чем писать. Правда только на русифицированном компиляторе (http://pro-pawn.ru/showthread.php?3586-Русифицированный-компилятор-Pawn). Сейчас попробую на стандартном.
Вовсе нет. Я то протестировал вначале прежде чем писать. Правда только на русифицированном компиляторе (http://pro-pawn.ru/showthread.php?3586-Русифицированный-компилятор-Pawn). Сейчас попробую на стандартном.
Вот именно, в стандартном компиляторе максимальная длина строки 511 символов. Если будут задекларированы большие строки в макросах, то будут проблемы. Как по мне, данный вариант некое "извращение", если его можно так назвать. Если создавать для каждых строк макросы, не думаю, что это будет удобно самому разработчику ( не всегда ). Если нужно будет изменить текст быстрым способом, так клавиши CTRL + F никто не отменял.
Вот именно, в стандартном компиляторе максимальная длина строки 511 символов..
Ну да, попробовал стандартным, повесился. А жаль. =(
Ну да, попробовал стандартным, повесился. А жаль. =(
Ты только теперь процесс убить не забудь ;) А то так и будет висеть до перезагрузки и жрать ресурсы системы
Подскажите, почему не открывается диалог с текстом?
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;
}
Daniel_Cortez
15.11.2014, 20:32
Подскажите, почему не открывается диалог с текстом?
http://wiki.sa-mp.com/wiki/ShowPlayerDialog
Max dialogid is 32767.
long_string[sizeof(long_string)-1] = '\n';
long_string_1[sizeof(long_string_1)-1] = '\0';
Для чего нужно таким способом добавлять конец строки и перенос? Если это не использовать, что случится?
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" да и не будут строки скреплены.
Не скомпилируется код, точнее выдаст "warning 203 symbol is never used long_string_1" да и не будут строки скреплены.
Эм... Вы о чём? Данная ошибка возникает (предупреждение) из-за того, что нигде не используется. В первом случае мы заменяем знак конца строки на знак перехода строки на новую, что, соответственно, говорит о сцепке двух строк. Во-втором случае мы ставим знак конца строки.
Эм... Вы о чём? Данная ошибка возникает (предупреждение) из-за того, что нигде не используется. В первом случае мы заменяем знак конца строки на знак перехода строки на новую, что, соответственно, говорит о сцепке двух строк. Во-втором случае мы ставим знак конца строки.
Это я про то, что если не использовать
long_string_1[sizeof(long_string_1)-1] = '\0';
То вы даст warning.... и строки не скрепятся.
п.с. при скреплении последующие использование как long_string вместо long_string и long_string_1 след. long_string_1 не где не используется отсюда предупреждение и строки не скрепляются.
Это я про то, что если не использовать
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
Конечно, вы же её не используете... А строки все равно скрепятся, ибо стоит знак перехода на новую строку.
Не скрепляются, проверено в игре.
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, возможно, следующие слова будут для тебя шоком, но прими их и постарайся со временем их осознать. Слушай. После объявления массива/переменной ее надо использовать, ибо зачем тогда объявлять? :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-й странице.
Что обозначает - 1 здесь? [sizeof(long_string)-1]
Что обозначает - 1 здесь? [sizeof(long_string)-1]
Так как все строки в памяти разделяются символом '\0' (символ конца строки), и sizeof возвращает размера массива (вместе с этим нулевым символом), то нужно вычитать единицу, дабы не засчитывался этот спец-символ.
Powered by vBulletin® Version 4.2.0 Copyright © 2024 vBulletin Solutions, Inc. All rights reserved. Перевод: zCarot