学习Lua碰到的问题踩坑记录
Posted 森明帮大于黑虎帮
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了学习Lua碰到的问题踩坑记录相关的知识,希望对你有一定的参考价值。
文章目录
- 一、遍历字典是无序的
- 二、Lua的遍历和C#不同
- 三、同名传参和同名字段
- 四、传参是引用传递
- 五、rawget()和rawset()
- 六、在Windows上安装Lua
- 七、把数值转成16进制的格式
- 八、把16进制色号转成三元数Color
- 九、去掉商里的小数
- 十、string.format() 保留3位小数
- 十一、向上/下取整, 四舍五入
- 十二、string拆成表, (不支持中文)
- 十三、敏感词过滤, 替换成*
- 十四、通配符, 正则表达式
- 十五、用正则实现trim()
- 十六、字符串截取string.sub()
- 十七、数组增删
- 十八、if后面跟一个方法, 这个方法会运行
- 十九、匿名函数
- 二十、死循环
- 二十一、右移: “>>”, 按位与: “&”
- 二十二、左移数值越界
- 二十三、可变参数: ‘…’
- 二十四、浅拷贝表
- 二十五、字典用table.sort()排序
- 二十六、多条件排序
- 二十七、Lua里没有string.split()
- 二十八、lua特殊写法
- 二十九、变量名
- 三十、今天星期几
- 三十一、os.time(): 秒
- 三十二、裆下日期转成表, 再把表转成秒
- 三十三、看身份证满18没有
- 三十四、Lua没有"继承"的弊端
- 三十五、取字符串的长度
- 三十六、#号
- 三十七、身份证验证
- 三十八、逻辑运算符的优先级
- 三十九、虚变量
- 四十、匹配字母和数字
- 四十一、if not a
- 四十二、墙裂推荐一个VS Code的插件: Rainbow Fart
- 四十三、数组洗牌打乱
- 四十四、JavaBean的要求规范
- 四十五、实现Switch
- 四十六、实现continue
- 四十七、string.format
- 四十八、三元表达式
- 四十九、"逻辑与"的截断机制
- 五十、问题:Lua的输出乱码
- 五十一、问题:Lua不是内部或外部命令,也不是可运行的程序或批处理文件
- 五十二、判断table里有没有某元素
- 五十三、(不)连续表的遍历
- 五十四、正则表达式
- 五十五、取模和取余
- 五十六、#汉字长度
- 五十七、赋值多个值
- 五十八、交换2个值
- 五十九、返回多个值
- 六十、方法后面不加小括号
- 六十一、按位运算
- 六十二、// 运算, 取商
一、遍历字典是无序的
t =
t.a = '1'
t.b = '2'
t.c = '3'
t.d = '4'
for i,v in pairs(t) do
print(v)
end
-- 每次输出都是乱序的!!!
二、Lua的遍历和C#不同
function Cnt()
print('执行Cnt方法')
return 3
end
for i = 1, Cnt() do
print(i)
end
输出:
执行Cnt方法
1
2
3
三、同名传参和同名字段
同名传参, 第1个传参无效。
function Do(arg, arg)
print(arg)
end
Do(1, 2)
输出:
2
同名字段, 第2个字段无效。
a, a = 1, 2
print(a)
输出:
1
四、传参是引用传递
表作为参数传递时, 是引用传递, 传的是地址。
在C#里也是这样的:
如下↓, 改变"参数表"(arg)的内容, “原来的表”(tab)也会改变。
function ReName(arg)
arg.name = '咸蛋超人'
end
tab = name = '奥特曼'
ReName(tab)
print(tab.name)
输出:
咸蛋超人
但是, 改变arg表自身, tab却不会变。
function ReName(arg)
arg = name = '咸蛋超人'
end
tab = name = '奥特曼'
ReName(tab)
print(tab.name)
输出:
奥特曼
改变attr.name, 会同时改变ultraman.attr.name。
置空attr.name, 会同时置空ultraman.attr.name。
如下↓:
ultraman = attr = name = '奥特曼'
attr = ultraman.attr
attr.name = '咸蛋超人'
print(ultraman.attr.name)
attr.name = nil
print(ultraman.attr.name)
输出:
咸蛋超人
nil
改变attr, 不会同时改变ultraman.attr。
置空attr, 不会同时置空ultraman.attr。
如下↓:
ultraman = attr = name = '奥特曼'
attr = ultraman.attr
attr = name = '咸蛋超人'
print(ultraman.attr.name)
attr = nil
print(ultraman.attr.name)
输出:
奥特曼
奥特曼
结论:
改变attr内部字段, ultraman.attr会同时改变。
但是改变attr自身, ultraman.attr不变。
在lua中, 如果我想置空attr怎么办呢? 只能在方法外把它置空。
在C#中, 可以给传参添加ref关键字, 这样一来, 置空attr, 原本的attr也会被置空。
五、rawget()和rawset()
只对自身get和set, 而不访问元表。
otab = a = '我是元表a'
tab = a = '我是a'
setmetatable(tab, __index = otab, __newindex = otab)
-- 获取tab的a, 与元表无瓜
print(rawget(tab, 'a'))
print(tab.a)
print(otab.a)
-- 给tab的b赋值, 与元表无瓜
rawset(tab, 'b', '我是b')
print(tab.b)
print(otab.b)
输出:
我是a
我是a
我是元表a
我是b
nil
六、在Windows上安装Lua
Lua下载地址:Lua:download
1.get a binary
2.选择自己电脑的版本
3.解压文件,(存放文件地址文件夹名全部不要出现中文最佳)
4.修改环境变量
5.win+R,cmd,输入lua或者lua53后如下即安装完成
6.最后intellij idea 中推荐一个EmmyLua,使用安装比较简单,在设置setting里面选择Plugins,查找EmmyLua安装即可
七、把数值转成16进制的格式
print(string.format('%x', 1221197823))
输出:
48c9ffff
八、把16进制色号转成三元数Color
比如色号是: FFA2FC, 先用string.sub()把她肢解为: 红FF, 绿A2, 蓝FC。
再用tonumber(str, 16)把16进制转为10进制, (例如: FF转为255)。
再用rgb分别除以255。
最后new一个三元数Color。
local colorString = 'FFA2FC'
local r = tonumber(string.sub(colorString, 1, 2), 16) / 255
local g = tonumber(string.sub(colorString, 3, 4), 16) / 255
local b = tonumber(string.sub(colorString, 5, 6), 16) / 255
return UnityEngine.Color(r, g, b)
九、去掉商里的小数
用"/"来做除法, 得到的结果中总会带有小数, 像这样:
print(700 / 100)
print(701 / 100)
输出:
7.0
7.01
需要实现:
当结果是7.0时, 去掉小数部分, 结果为7。
当结果是7.01时, 保留小数部分, 结果为7.01。
思路: 用math.modf(), 把整数部分与小数部分拆开:
local t1, t2 = math.modf(700 / 100)
print(t1)
print(t2)
输出:
7
0.0
再加个判断"小数部分是否为0"就好了:
function GetFixedQuotient(num1, num2)
quotient = num1 / num2
local t1, t2 = math.modf(quotient)
-- 去掉数字后面的.0
if t2 == 0 then
return t1
else
return quotient
end
end
print(GetFixedQuotient(700, 100))
print(GetFixedQuotient(701, 100))
输出:
7
7.01
十、string.format() 保留3位小数
print(string.format('%.3f', 0.5))
print(string.format('%.3f', 0.0005))
print(string.format('%.3f', 0.0004))
print(string.format('%.3f', 500))
输出:
0.500
0.001(这里四舍五入了)
0.000(这里四舍五入了)
500.000
十一、向上/下取整, 四舍五入
-- 取整
print('向上取整: 1 / 3 = ' .. math.ceil(1 / 3))
print('向下取整: 1 / 3 = ' .. math.floor(1 / 3))
-- 想实现四舍五入, 就+0.5
print('四舍五入: 1 / 3 = ' .. math.floor(1 / 3 + 0.5))
print('四舍五入: 2 / 3 = ' .. math.floor(2 / 3 + 0.5))
-- 保留3位小数的四舍五入, 就先*1000再+0.5再/1000
print('四舍五入: 1 / 3 = ' .. math.floor(1 / 3 * 1000 + 0.5) / 1000)
print('四舍五入: 2 / 3 = ' .. math.floor(2 / 3 * 1000 + 0.5) / 1000)
输出:
向上取整: 1 / 3 = 1
向下取整: 1 / 3 = 0
四舍五入: 1 / 3 = 0
四舍五入: 2 / 3 = 1
四舍五入: 1 / 3 = 0.333
四舍五入: 2 / 3 = 0.667
十二、string拆成表, (不支持中文)
input = "2b*)我"
tabA =
for i = 1, #input do
let = string.sub(input, i, i)
table.insert(tabA, i, let)
print(i, let)
end
输出:
1 2
2 b
3 *
4 )
5 �
6 �
7 �
十三、敏感词过滤, 替换成*
input = 'ABc大大大'
word = 'bc大'
lower = string.lower(input)
result = lower
if string.find(lower, tostring(word)) ~= nil then
-- 汉字占3个字符, 所以不能直接用string.len()
local _, count = string.gsub(word, '[^\\128-\\193]', '')
local stars = string.rep('*', count)
result = string.gsub(lower, tostring(word), stars)
end
print(result)
输出: A***大大
十四、通配符, 正则表达式
s = "abc \\"it's a cat\\""
_, _, _, d = string.find(s, "([\\"'])(.-)%1")
print(d) -----输出: it's a cat
十五、用正则实现trim()
name = ' 蒂纳 奥特曼 '
local _name = string.gsub(name, '^%s*(.-)%s*$', '%1')
print(_name)
输出:蒂纳 奥特曼
十六、字符串截取string.sub()
s = 'abcde'
print(string.sub(s, 1, 3)) -- 从1数到3
print(string.sub(s, 3, 3)) -- 从3数到3
print(string.sub(s, 3)) -- 从3数到末尾
print(string.sub(s, 8)) -- 没有8,直接空了
print(string.sub(s, 3, -1)) -- 从3数到5(末尾)
print(string.sub(s, 3, -2)) -- 从3数到4(末尾-1)
print(string.sub(s, -4, -2)) --从2(末尾-3)数到4(末尾-1)
print(string.sub(s, -9))-- 从头数到尾
-- 输出:
abc
c
cde
cde
cd
bcd
abcde
十七、数组增删
数组能用, 字典不行。
table.insert(list, [pos, ]value), -- 不给pos就是#list+1
table.remove(list[, pos]), -- 不给pos就是#list
注意: 在for的时候, 要从后往前删。
十八、if后面跟一个方法, 这个方法会运行
function fun()
print(2)
end
if fun() then
end
输出: 2
↓写成这样则不执行。
if fun then
end
十九、匿名函数
注意: 直接 a = fun(), fun会立即执行, 不想立即执行的话, 就用个匿名方法把它包起来, 或者像delegate的+=一样, 方法后面别带括号。
function foo(arg)
print(arg)
end
---------1----------
arg1 = 1
-- 直接执行, 输出1
fun = foo(arg1)
---------2----------
arg2 = 2
-- 不执行
fun = function()
foo(arg2)
end
-- 执行, 输出2
fun()
---------3----------
arg3 = 3
-- 不执行
fun = foo
-- 执行, 输出3
fun(arg3)
进阶: 2个不同来源的传参:
function fooo(arg1, arg2)
print(arg1, arg2)
end
a = 2
-- 不执行
fun = function(b)
fooo(a, b)
end
-- 执行, 输出2,3
fun(3)
二十、死循环
这样写就是死循环↓:
for i = 1, i + 10 do
print(i)
end
正确写法↓:
local endNum = i + 10
for i = 1, endNum do
print(i)
end
二十一、右移: “>>”, 按位与: “&”
print(0x0000ffff)
print(32794992 >> 16)
print(500 & 65535)
print(500 & 63)
输出:
65535
500
500
52
---------------------------------------------------------------
先看: 0x0000ffff (得: 65535)
16进制的: 0x0000ffff, 就是10进制的: 65535, 就是2进制的: 11111111111111111111(16个1)
(10进制的: 65536, 就是2进制的: 1000000000000000000(16个0), 就是 1>>16)
再看: 32794992 >> 16 (得: 500)
10进制的: 32794992, 就是2进制的: 1111101000110100101110000
左移16位, 后面16位就被丢掉了, 只剩下111110100, 就是10进制的: 500
(计算器算 32794992 ÷ 65536 = 500.41186523438)
再看 500 & 65535 (得: 500)
一个2进制数, 只要小于16个1, 它和 11111111111111(16个1) 做按位与, 还是它自己
所以 500(111110100) 和 11111111111111(16个1) 做按位与, 还是它自己
再看 500 & 63
10进制的: 63, 就是2进制的: 111111
500(111110100) 和 111111 做按位与
就相当于高于6位的都丢掉了, 结果是 110100, 也就是10进制的 52
实例: id是64位, 其组成为:14位没用 - 8位大区id - 10位服务器id - 32位玩家id。
需求: 取服务器id。
分析: 先右移32位, 去除玩家id, 再和1111111111(10个1)做按位与, 就能得到10位的服务器id。
local id = 3063948711696181930
zoneID = (id >> 32) & 1023
print(zoneID)
二十二、左移数值越界
local id = 3063948711696181930
-- 即为2进制的: 10 1010 1000 0101 0101 0101 0001 1110 1010 1010 1010 1010 1010 1010 1010 1010
zoneID = (id << 2)
-- 左移2位, 即后面填2个0, 即为2进制的: 10 1010 1000 0101 0101 0101 0001 1110 1010 1010 1010 1010 1010 1010 1010 1010 00
-- 共64位, 其首位是1, 代表负号
print(zoneID)
-- 所以打印出负数: -6190949226924823896
二十三、可变参数: ‘…’
以上是关于学习Lua碰到的问题踩坑记录的主要内容,如果未能解决你的问题,请参考以下文章
fltk-rs踩坑记录,解决could not find native static library cfltk, perhaps an -L flag is missing 问题