lua 小技巧


lua 小技巧

  1. 把常用的工具函數添加到 _G 里面,所有的文件都可以直接調用:

    -- 在 a 文件中將工具函數添加到 _G:
    _G.IsEmptyStr = function(str) 
    	return str==nil or type(str) ~= "string" or str == "" 
    end  
    _G.PrintObjPos = function(prefix, obj)
    	prefix = prefix or ""
    	local l,t,r,b = obj:GetObjPos()
    	XLPrint(prefix .. " l=" .. l .. ", t=" .. t .. ", r=" .. r .. ", b=" .. b)
    end
    	
    
    -- 在其它文件中直接使用工具函數:
    if not IsEmptyStr(obj:GetText()) then  
    	PrintObjPos("[Dongyu]", obj)
    end  
    
  2. 使用 or 操作符賦默認值:

    num = num or 0
    
  3. 使用 (a and b) or c 操作符實現 C 語言中 a ? b : c 的功能 :

    num = (num < 0 and 0) or num
    
    這樣做的原理是:
    a and b  -- 如果 a 為 false, 則返回 a, 否則返回 b
    a or b   -- 如果 a 為 true, 則返回 a, 否則返回 b
    
  4. 獲取 UTF-8 字符串中的字符數(中英文混合) :

    local function strlength(str)
    	-- 計算字符串長度,中英文混合
    	str = string.gsub(str, "%%", " ") -- 將%替換成" "
    	local str = string.gsub(str, "[\128-\191]","")
    	local _,ChCount = string.gsub(str, "[\192-\255]","")
    	local _,EnCount = string.gsub(str, "[^\128-\255]","")
    	return ChCount + EnCount
    end
    

    這種做法跟 UTF-8 格式有關,標准 ASC|| 碼(英文)是 0-127 ;中文占 3 個字符(192-255)(128-191)(128-191);
    詳情可參考這篇文章

  5. 去除字符串首尾空格:

    function trim (s) 
    	return (string.gsub(s, "^%s*(.-)%s*$", "%1")) 
    end
    
  6. 關閉 string.find(s, pattern, start, plain) 的模式匹配:

    -- 將 find 的第四個參數設定為 true, 則 pattern 將被視為普通字符串,不會處理特殊字符
    pos = string.find(str, "%s", 1, true)
    
  7. 分割字符串:

    function split(s, delim)
        if type(delim) ~= "string" or string.len(delim) <= 0 then
            return
        end
    
        local start = 1
        local t = {}
        while true do
        local pos = string.find (s, delim, start, true) -- plain find
            if not pos then
              break
            end
    
            table.insert (t, string.sub (s, start, pos - 1))
            start = pos + string.len (delim)
        end
        table.insert (t, string.sub (s, start))
    
        return t
    end
    
  8. table.concat 打印數組:

    local t = {"2016", "3", "6"}
    print(table.concat(t, "-"))    -- 2016-3-6
    
  9. 打印 table:

    function print_lua_table (lua_table, indent)
        local function print_func(str)
            XLPrint("[Dongyu] " .. tostring(str))
        end
    
        if lua_table == nil or type(lua_table) ~= "table" then
    		print_func(tostring(lua_table))
            return
        end
    
        indent = indent or 0
        for k, v in pairs(lua_table) do
            if type(k) == "string" then
                k = string.format("%q", k)
            end
            local szSuffix = ""
            if type(v) == "table" then
                szSuffix = "{"
            end
            local szPrefix = string.rep("    ", indent)
            formatting = szPrefix.."["..k.."]".." = "..szSuffix
            if type(v) == "table" then
                print_func(formatting)
                print_lua_table(v, indent + 1)
                print_func(szPrefix.."},")
            else
                local szValue = ""
                if type(v) == "string" then
                    szValue = string.format("%q", v)
                else
                    szValue = tostring(v)
                end
                print_func(formatting..szValue..",")
            end
        end
    end
    
  10. 拷貝 table:

    function copy_table(ori_tab)
        if type(ori_tab) ~= "table" then
            return
        end
        local new_tab = {}
        for k,v in pairs(ori_tab) do
            local vtype = type(v)
            if vtype == "table" then
                new_tab[k] = copy_table(v)
            else
                new_tab[k] = v
            end
        end
        return new_tab
    end
    

    function deepcopy(object)
        local lookup_table = {}
        local function _copy(object)
            if type(object) ~= "table" then
                return object
            elseif lookup_table[object] then
                return lookup_table[object]
            end
    
            local new_table = {}
            lookup_table[object] = new_table
            for index, value in pairs(object) do
                new_table[_copy(index)] = _copy(value)
            end
            return setmetatable(new_table, getmetatable(object))
        end
        return _copy(object)
    end
    
  11. for 循環中 remove 數組元素:

    local t = {1,2,3,3,5,3,6}
    for i,v in ipairs(t) do
    	if v == 3 then
    		table.remove(t,i)
    	end
    end
    -- 錯誤,第四個 3 沒有被移除,ipairs 內部會維護一個變量記錄遍歷的位置,
    -- remove 掉第三個數字 3 之后,ipairs 下一個返回的值是 5 而不是 3
    
    local t = {1,2,3,3,5,3,6}
    for i=1, #t do
    	if t[i] == 3 then
    		table.remove(t,i)
    		i = i-1
    	end
    end
    -- 錯誤,i=i-1 這段代碼沒有用,i 的值始終是從 1 到 #t,for 循環里修改 i 的值不起作用
    
    local t = {1,2,3,3,5,3,6}
    for i=#t, 1, -1 do
    	if t[i] == 3 then
    		table.remove(t,i)
    	end
    end
    -- 正確,從后往前遍歷
    
    local t = {1,2,3,3,5,3,6}
    local i = 1
    while t[i] do
    	if t[i] == 3 then
    		table.remove(t,i)
    	else
    		i = i+1
    	end
    end
    -- 正確,自己控制 i 的值是否增加
    
  12. table.sort(t, comp) 排序數組 :
    sort 可以將 table 數組部分的元素進行排序,需要提供 comp(a,b) 函數,如果 a 應該排到 b 前面,則 comp 要返回 true 。

    注意: 對於 a==b 的情況,一定要返回 false:

    local function comp(a,b) 
    	return a <= b 
    end 
    table.sort(t,comp) 
    -- 錯誤,可能出現異常:attempt to compare number with nil 
    
    local function comp(a,b) 
    	if a == nil or b == nil then 
    		return false 
    	end 
    	return a <= b 
    end 
    table.sort(t,comp) 
    -- 錯誤,可能出現異常:invalid order function for sorting 
    -- 也可能不報這個異常,但結果是錯誤的;
    

    之所以 a==b 返回true 會引發這些問題,是因為 table.sort 在實現快速排序時沒有做邊界檢測:

    for (;;) {
    	while (lua_rawgeti(L, 1, ++i), sort_comp(L, -1, -2))  // 未檢測邊界, i 會一直增加
    	{
    		if (i>=u) luaL_error(L, "invalid order function for sorting");
    		lua_pop(L, 1);
    	}
    	while (lua_rawgeti(L, 1, --j), sort_comp(L, -3, -1))  // 未檢測邊界, j 會一直減少
    	{
    		if (j<=l) luaL_error(L, "invalid order function for sorting");
    		lua_pop(L, 1);
    	}
    	if (j<i) {
    		lua_pop(L, 3);
    		break;
    	}
    	set2(L, i, j);
    }
    

    看以上代碼,如果 a==b 時返回 true 且邊界上的幾個值是相等的話, sort_comp 就無法阻止 i 繼續增長,直到超出邊界引發異常 attempt to compare number with nil;
    即使對 a 和 b 進行了非空判斷,也會因為 i 超過邊界而引發異常 invalid order function for sorting.


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM