narinoa

Вывод строки

20 posts in this topic

Подскажите, как вывести строку 1234567 в формате в 1 234 567?

Share this post


Link to post
Share on other sites

А для совсем маленьких можно на примере с комментариями? :lol:

Share this post


Link to post
Share on other sites

В аддоне CurrencesInfo есть в функции AvatarGetMoney пример получения 

	--Получаем количество денег--------------------------------------------------------------------------------
    local money = avatar.GetMoney()
    --Разбираем полученную строку------------------------------------------------------------------------------
    local StringSize = string.len(tostring(money)) --Получаем размер строки
    local Copper = string.sub(tostring(money), StringSize - 1, StringSize) --Получем последние 2 символа - "медные"
    local Silver = string.sub(tostring(money), StringSize - 3, StringSize - 2) --Получаем 2 и 3 символы с конца строки - "серебряные"
    local Golg = string.sub(tostring(money), 0, StringSize - 4) --Получаем все остальные начиная с 4-го символа конца строки - "золотые"
    local lg = string.len(Golg) --Длина объема золота
	

Share this post


Link to post
Share on other sites

Вот это извращение! Не проще ли money поделить два раза на 100 и остатки сконвертировать в строки? Это же будет в разы оптимальнее!

Share this post


Link to post
Share on other sites
function UpdateMoney()
	money = avatar.GetMoney()
	gold = math.floor(money / 10000)
	local StringSize = string.len(tostring(money)) 
	local Golg = string.sub(tostring(money), 0, StringSize - 4) 
	local lg = string.len(Golg) 
end

И вывожу в АОпанель

userMods.ToWString(""..Golg)

Но мне показывает нуль. В чем ошибка?

Money.lua

Share this post


Link to post
Share on other sites

Нед, нагло вру

function UpdateMoney()
	money = avatar.GetMoney()
	local StringSize = string.len(tostring(money))
	local g = string.sub(tostring(money), StringSize - 6, StringSize - 4)
	local t = string.sub(tostring(money), StringSize - 9, StringSize - 7)
	local m = string.sub(tostring(money), StringSize - 12, StringSize - 10)
	local lg = string.len(Golg)
	Golg = m.." "..t.." "..g
	end

Все равно работает криво

Share this post


Link to post
Share on other sites

"Криво" - это как?

В чем задача-то, конкретнее? Нужно разбить строковое представление целого числа на группы по 3 разряда?

Тогда должно быть что-то типа такого:

function FormatInt(int)
    -- Если у нас число из трех разрядов или меньше, то мы можем сразу вернуть его строковое представление
    if int < 1000 then
    	return tostring(int)
    end
	
    -- Дополнительная функция, которая добавляет leading zeroes, если в значении блока вдруг меньше трех разрядов, т.е. присутствуют нолики в начале
    local GetThreeDigitBlock = function(num)
        return (num < 100 and (num < 10 and "00"..num or "0"..num) or num)
    end
	
    -- Если же оно больше, то мы делим его в цикле на 1000 и остаток от деления записываем в начало таблички blocks 
    local blocks = {}
    while int >=1 do
        local modulus = int % 1000
        -- Если modulus равен int, то мы дошли до самого начала нашего большого числа и в таком случае не нужно добавлять leading-zeroes
        -- Если же не равен, значит мы в данный момент добавляем блок из середины строкового представления входного числа,
        -- который надо корректно отформатировать, добавив нули в начало при необходимости
        local block = modulus ~= int and GetThreeDigitBlock(modulus) or modulus
        table.insert(blocks, 1, block)
        int = math.floor(int / 1000)
    end
	
    -- Возвращаем в конце конкатенированную таблицу blocks с пробелом в качестве разделителя
    return table.concat(blocks, " ")
end

Функция на входе принимает число (например, то же avatar.GetMoney() / 10000, т.е. количество золота), а на выходе выдает отформатированную строку (lua-string, которую нужно будет сконвертировать в WString для передачи в AOPanel).

Edited by Altair
Поправил баг с ноликами в начале блоков

Share this post


Link to post
Share on other sites

Криво, это когда число из трех разрядов отображается нормально, а число из одного разряда или двух - нет :mellow:

А задача да, получаем число золота и разбиваем на разряды, ибо "10 000 000" более понятно, чем "10000000".

Share this post


Link to post
Share on other sites

Если обойтись только строками:

local function getFormattedMoney(money)

	assert(type(money) == 'number', string.format('money type is not a number (type: %s)', type(money)))

	local smoney = money < 10000 and string.format('%05d', money) or tostring(money)

	local gold, silver, copper = string.match(smoney, '(%d-)(%d%d)(%d%d)$')
	
	if #gold >= 3 then

		local n = #gold % 3 == 0 and #gold/3 - 1 or nil
		
		local replace = function(v)
			
			return string.format('%s ', v)
			
		end

		gold = string.reverse(gold)
		gold = string.gsub(gold, '(%d%d%d)', replace, n)
		gold = string.reverse(gold)
	
	end

	return gold, silver, copper

end


-- example

local money = avatar.GetMoney()

local gold = getFormattedMoney(money)

local SetVal = { val = userMods.FromWString(gold) }

--[[

-- если понадобится знать еще серебро и медь, то можно сделать так:

local gold, silver, copper = getFormattedMoney(money)

-- при money 12345678900 результат будет такой:

gold = '1 234 567'
silver = '89'
copper = '00'

--]]

 

Edited by LEM
небольшая правка кода

Share this post


Link to post
Share on other sites
17 часов назад, Altair сказал:

Ну так воспользуйся тогда моей функцией)

Да, я так и сделал, все теперь работает отлично. Однако я еще попытался использовать способ LEM, но мне при входящем параметре 124993253965 почему-то форматирует в 43 920.

Share this post


Link to post
Share on other sites

Работа со строками в LUA дорогая. Любое создание строки, любой вызов функции из библиотеки string (кроме len, char, byte) - это дорого в вычислительном плане. Если у вас изначально есть число, то лучше с этим числом операции производить именно в виде числа.

Share this post


Link to post
Share on other sites
4 часа назад, narinoa сказал:

Да, я так и сделал, все теперь работает отлично. Однако я еще попытался использовать способ LEM, но мне при входящем параметре 124993253965 почему-то форматирует в 43 920.

Исправлено.

Share this post


Link to post
Share on other sites
В 4/27/2017 в 00:51, Altair сказал:

"Криво" - это как?

В чем задача-то, конкретнее? Нужно разбить строковое представление целого числа на группы по 3 разряда?

Тогда должно быть что-то типа такого:


function FormatInt(int)
    -- Если у нас число из трех разрядов или меньше, то мы можем сразу вернуть его строковое представление
    if int < 1000 then
    	return tostring(int)
    end
    
    -- Если же оно больше, то мы делим его в цикле на 1000 и остаток от деления записываем в начало таблички blocks 
    local blocks = {}
    while int >=1 do
    	table.insert(blocks, 1, int % 1000)
        int = math.floor(int / 1000)
    end
	
    -- Возвращаем в конце конкатенированную таблицу blocks с пробелом в качестве разделителя
    return table.concat(blocks, " ")
end

Функция на входе принимает число (например, то же avatar.GetMoney() / 10000, т.е. количество золота), а на выходе выдает отформатированную строку (lua-string, которую нужно будет сконвертировать в WString для передачи в AOPanel).

Есть одна проблема: если число вида 2474067, то вывод по вашей функции - 2 474 67, т.е.0 пропускается и не дописывается 

Share this post


Link to post
Share on other sites
В 4/28/2017 в 08:10, LEM сказал:

Если обойтись только строками:


local function getFormattedMoney(money)

	assert(type(money) == 'number', string.format('money type is not a number (type: %s)', type(money)))

	local smoney = money < 10000 and string.format('%05d', money) or tostring(money)

	local gold, silver, copper = string.match(smoney, '(%d-)(%d%d)(%d%d)$')
	
	if #gold >= 3 then

		local n = #gold % 3 == 0 and #gold/3 - 1 or nil
		
		local replace = function(v)
			
			return string.format('%s ', v)
			
		end

		gold = string.reverse(gold)
		gold = string.gsub(gold, '(%d%d%d)', replace, n)
		gold = string.reverse(gold)
	
	end

	return gold, silver, copper

end


-- example

local money = avatar.GetMoney()

local gold = getFormattedMoney(money)

local SetVal = { val = userMods.FromWString(gold) }

--[[

-- если понадобится знать еще серебро и медь, то можно сделать так:

local gold, silver, copper = getFormattedMoney(money)

-- при money 12345678900 результат будет такой:

gold = '1 234 567'
silver = '89'
copper = '00'

--]]

 

Я так понимаю, вашей функцией можно полностью заменить парсинг строки getMoney?

Share this post


Link to post
Share on other sites
6 часов назад, rawnblade сказал:

Есть одна проблема: если число вида 2474067, то вывод по вашей функции - 2 474 67, т.е.0 пропускается и не дописывается 

Да, писал на коленке из другой страны, баги неизбежны )) Исправил оригинальное сообщение, теперь корректно обрабатываются блоки, которые начинаются с нулей.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now