Начну я, пожалуй, с того, что есть в языке cJASS прекрасная библиотека под названием printf. Подробно я ее описывать не буду, если интересно - почитаете официальный мануал. Хороша она тем, что все вызовы ее функций (кроме B2S) подставляются прямо в код, и на выходе получается самая обыкновенная строка. По производительности абсолютно не уступает стандартному методу работы со строками, однако для ее корректной работы форматирующая строка должна быть константной, т. е. известной на стадии компиляции. И здесь мы плавно подходим к моей системе.
Функция (вернее, набор функций) Format выполняет ту же работу - подставляет переданные значения в форматирующую строку. Важным отличием является то, что она работает в момент исполнения кода, а не в момент компиляции, что позволяет передавать любую строку в качестве форматной. Например, это может использоваться для поддержки мультиязычности. Язык переключает каждый игрок только для себя.
У printf синтаксис (как и название) взят из языка C, Format же частично использует обозначения C#:
Код
call BJDebugMsg(Format("Это форматная строка, в которую будут подставлены: логическая {0}, целочисленная {1} и ID handle'а {2}.", FmtB(true) + FmtI(100500) + FmtH(GetTriggerUnit())))
Сначала в Format передается строка, а затем - аргументы, пропущенные через соответствующие преобразующие функции и разделенные знаком '+'. Вот список этих функций:
Вы также можете использовать параметры несколько раз или не использовать вовсе. Если в фигурных скобках указано неверное число, они будут выведены как есть:
Второго аргумента здесь нет, минус первого быть просто не может, "test" вообще не является номером, так что вывод будет составлять "{2}{-1}{test}123".
Если же Вам нужно принудительно вывести фигурные скобки с числом (ну, вдруг кому понадобится), поставьте перед ними значок акцента ("`{1}"). Для выведения самого акцента его нужно удвоить (``).
После каждого изменения имен игроков необходимо вызывать функцию Format_UpdatePlayerNames(). Если же они изменяются в самом начале игры, установите константу AUTO_INITIALIZE_NAMES в значение false.
Напоследок расскажу о "подарочном наборе" функций. В библиотеку входит открытая функция IsZero(string), позволяющая узнать, является ли данная строка корректным представлением числа ноль (строки "00", "-0", "-----0", "---000" являются). Функции FmtDisplay(string format, ...) и FmtDisplayTimed(real time, string format, ...) выводят форматированную строку на экран локальному игроку. Также есть FmtDebug - аналог BJDebugMsg.
constant function FmtB takes boolean b returns string if b then return "true`~" endif return "false`~" endfunction
constant function FmtBI takes boolean b returns string if b then return "1`~" endif return "0`~" endfunction
function FmtI takes integer i returns string return I2S(i) + "`~" endfunction
function FmtHex takes integer i returns string local string result = "`~" local boolean neg = i < 0 local integer m if neg then set i = -i endif loop set m = i - i / 0x10 * 0x10 if m < 8 then if m < 4 then if m < 2 then if m == 0 then set result = "0" + result else set result = "1" + result endif elseif m == 2 then set result = "2" + result else set result = "3" + result endif elseif m < 6 then if m == 4 then set result = "4" + result else set result = "5" + result endif elseif m == 6 then set result = "6" + result else set result = "7" + result endif elseif m < 12 then if m < 10 then if m == 8 then set result = "8" + result else set result = "9" + result endif elseif m == 10 then set result = "A" + result else set result = "B" + result endif elseif m < 14 then if m == 12 then set result = "C" + result else set result = "D" + result endif elseif m == 14 then set result = "E" + result else set result = "F" + result endif set i = i / 0x10 exitwhen i == 0 endloop if neg then return "-0x" + result endif return "0x" + result endfunction
function FmtR takes real r returns string return R2S(r) + "`~" endfunction
function FmtRound takes real r returns string return I2S(R2I(r)) + "`~" endfunction
function FmtRW takes real r, integer width, integer precision returns string return R2SW(r, width, precision) + "`~" endfunction
function FmtS takes string s returns string local integer i = StringLength(s) local string result = "`~" local string ch if i > 0 then loop set ch = SubString(s, i - 1, i) if ch == "`" then set result = "``" + result else set result = ch + result endif exitwhen i == 1 set i = i - 1 endloop endif return result endfunction
function FmtH takes handle h returns string return FmtHex(GetHandleId(h)) endfunction
function FmtP takes player p returns string return PlayerNames[GetPlayerId(p)] endfunction
function FmtIP takes integer i returns string return PlayerNames[i] endfunction
function FmtPC takes player p returns string return ColouredNames[GetPlayerId(p)] endfunction
function FmtIPC takes integer i returns string return ColouredNames[i] endfunction
function FmtC takes integer i returns string return Colours[i] endfunction
constant function FmtEndl takes nothing returns string return "\n`~" endfunction
function IsZero takes string s returns boolean local integer i = StringLength(s) local boolean minus = false local boolean first = true local string ch if i == 0 then return false endif loop set ch = SubString(s, i - 1, i) if minus then if ch != "-" then return false endif elseif ch == "-" then if first then return false endif set minus = true elseif ch != "0" then return false endif exitwhen i == 1 set first = false set i = i - 1 endloop return true endfunction
function Format takes string format, string args returns string local integer l = StringLength(args) local integer i = 0 local integer j = 0 local integer k local string array arg local string result = "" local string ch local boolean b = false set arg[0] = "" loop exitwhen j >= l set ch = SubString(args, j, j + 1) if ch == "`" then set ch = SubString(args, j + 1, j + 2) if ch == "~" then set i = i + 1 set arg[i] = "" else set arg[i] = arg[i] + "`" endif set j = j + 2 else set arg[i] = arg[i] + ch set j = j + 1 endif endloop set l = StringLength(format) set j = 0 loop exitwhen j >= l set ch = SubString(format, j, j + 1) if ch == "`" then set result = result + SubString(format, j + 1, j + 2) set j = j + 2 else if ch == "{" then loop set args = "" loop set j = j + 1 set ch = SubString(format, j, j + 1) if ch == "{" then set result = result + "{" + args exitwhen true elseif ch == "}" then set k = S2I(args) if k < 0 or k >= i then set result = result + "{" + args + "}" elseif k != 0 or IsZero(args) then set result = result + arg[k] else set result = result + "{" + args + "}" endif set b = true exitwhen true elseif j >= l + 1 then return result + "{" + args + ch else set args = args + ch endif endloop exitwhen b endloop else set result = result + ch endif set j = j + 1 endif endloop return result endfunction
function FmtDisplay takes string format, string args returns nothing call DisplayTextToPlayer(GetLocalPlayer(), .0, .0, Format(format, args)) endfunction
function FmtDisplayTimed takes real time, string format, string args returns nothing call DisplayTimedTextToPlayer(GetLocalPlayer(), .0, .0, time, Format(format, args)) endfunction
function FmtDebug takes string format, string args returns nothing call FmtDisplayTimed(60., format, args) endfunction
public function UpdatePlayerNames takes nothing returns nothing local integer i = 0 loop set PlayerNames[i] = FmtS(GetPlayerName(Player(i))) set ColouredNames[i] = Colours[i] + /* */ SubString(PlayerNames[i], 0, StringLength(PlayerNames[i]) - 2) + "|r`~" exitwhen i == 15 set i = i + 1 endloop endfunction
private function Init takes nothing returns nothing set Colours[0] = "|cffff0303" set Colours[1] = "|cff0042ff" set Colours[2] = "|cff1ce6b9" set Colours[3] = "|cff540081" set Colours[4] = "|cffffff01" set Colours[5] = "|cfffe8a0e" set Colours[6] = "|cff20c000" set Colours[7] = "|cffe55bb0" set Colours[8] = "|cff959697" set Colours[9] = "|cff7ebff1" set Colours[10] = "|cff106246" set Colours[11] = "|cff4e2a04" set Colours[12] = "|cffffffff" set Colours[13] = "|cffffffff" set Colours[14] = "|cffffffff" set Colours[15] = "|cffffffff" static /* */ if AUTO_INITIALIZE_NAMES then call UpdatePlayerNames() endif endfunction endlibrary
SirNikolas, Я ХОЧУ ОТ ТЕБЯ ДЕТЕЙ Ты не мог бы как-нибудь выложить ман по этой библиотеке? (я про стандартную printf) Хоть немного и знаю Си и плюсы, но в cJass'овской путаюсь ):
Вызываем printf, передаем форматную строку, в которой на месте подставляемых значений ставим эти символы:
Quote
%p - имя игрока, принимает player %pc - цветное имя игрока, принимает player %i - десятичное число, принимает int %igold - десятичное число, золото, принимает int %ilumb - десятичное число, древесина, принимает int %ip - имя игрока, принимает int (номер игрока) %ipc - цветное имя игрока, принимает int (номер игрока) %b - bool, выводит "true" или "false" %r - вещественное число, без форматирования, принимает real %s - строка, в случае передачи immed значение "склеится" с источником %v - var, прямая подстановка аргумента в строку %h - десятичное число, ид дескриптора, принимает соответсвенно дескриптор (handle)
Последующими аргументами перечисляем значения в том порядке, в котором они идут в строке. Если значение используется несколько раз - пишем его несколько раз.
printf("%ipchas just pwned%ipc's head! for%igoldgold!", killer, victim, GetHeroLevel(victim) * 50);
it's fucking amazing соглашусь с Максимкой, тоже хочу от тебя детей ты сделал то, до чего у меня руки из-за кривости их и лени не дошли нормально(я про {x}), давно эту фишку из шарпа привинтить хотел) всем рекомендую)