Lua

学习文档:LuatOS 文档

在线环境:LuatOS 在线模拟 - lua在线测试

官网:official::The Programming Language Lua

官方API手册:official::Lua 5.3 Reference Manual - contents


一、Lua基础

1 数字变量

作用域:lua中声明的变量默认是全局变量,在其他文件中也可以使用。如果只想在当前文件夹中使用需要加上local

空值:lua中没有被声明过的变量都是nil(相当于null值)

数字型:lua中的数字类型是number(不同于c,c有int,float等)。但是因为lua是用c写的,number实际上是c里面的double

-- 这是行注释

--[[
这是块注释,
块注释可以
注释多行!
--]]

-- 声明全局变量(直接赋值就是声明,类似python)
a = 1
b = 2

-- 声明局部变量
local a = 1

-- c没被声明过,打印是nil
print(c)

-- 多个变量赋值(a=1,b=2)
a,b = 1,2
-- 左边变量多余右边时,多出的变量会赋值为nil(c=nil)
a,b,c = 1,2

-- 其他数字
a = 0x11 -- 十六进制
b = 2e10 -- 2 * 10的10次方

2 运算符

-- 数字型
a = b + c
a = b - c
a = b * c
a = b / c
a = b // c -- 整除
a = b ^ c -- a = b的c次方
a = b << c -- a = b左移c位
a = b >> c

3 字符串

-- 声明字符串
a = "abcdef"

-- 声明带转义字符的字符串(打印时转义字符会被转义)
b = "abc\ndef"

-- 声明多行字符(字符和文字结构直接全部保留,怎么输入就怎么输出(相当于html的textarea))
c = [[abc
\ndef
gg]]

-- 连接字符串
c = a..b

-- 数字转字符串
char = tostring(10)
-- 字符串转数字(转化失败则输出nil)
num = tonumber("10")

-- 获取字符串长度(字符串前面加个井号,像上述的b长度则为7,因为\n算一个)
len = #a
-- 一些API

-- ASCII码构造字符串(参数:字符值)
s = string.char(0x30, 0x31, 0x32, 0x33)

-- 找出字符串中指定位置的ASCII值(参数:字符串,索引)
c = string.byte(str, index)

-- 0x00不会让字符串结束(不同于c)
s = string.char(0x30, 0x00, 0x31, 0x32, 0x33)
print(s)
print(#s)

4 函数

函数返回值默认是nil

函数传递变量时按顺序赋值,如果后面的变量没被赋值(函数需要传递三个变量但是实际上只传递了两个),那么后续的变量使用时值就为nil

函数返回值存在多个时,可以对返回值进行解包。

-- 声明函数(方法一)
function function_name(...)
-- body
end

-- 声明函数(方法二)
function_name = function(...)
-- body
end
-- 案例
f = function(a,b,c)
return a,b,c
end

-- 输出1 2 nil
print(f(1,2))
local i,j = f(1,2)
-- 输出1
print(i)
-- 输出2
print(j)

5 数组table

类似于python的list

table的下标是从1开始而不是0

table遇到nil会停下。所以如果直接给table中的值赋值给nil时,table会认为到nil的位置就是table的结尾了,哪怕后面还有值。

-- 声明table
a = {1, "ac", {}, function() end}

-- 输出1
print(a[1])

-- 获取table长度(和字符串一样前面加一个井号)
len = #a

-- 此时a[0]和a[5]后面的元素都nil,可以直接给a[5]赋值,这样table长度就会发生变化
a[5] = "gg"
-- 一些API

-- 在尾部插入数据(参数:table名,插入值)
table.insert(table, value)

-- 在指定位置插入(参数:table名,下标,插入值)
table.insert(table, index, value)

-- 移除元素同时返回被移除的元素(参数:table名,下标)
local s = table.remove(table, index)
-- 补充说明

-- 定义a
a = {1, "ac", {}, function() end}

-- 用循环遍历table
for key, value in ipairs(a) do
print(key, value)
end

-- 尝试给a[0]赋值,然后使用循环遍历发现不会遍历到a[0],同时table长度不变,但是直接访问a[0]的值是可以的
a[0] = "0"

-- 尝试给a[6]赋值,然后使用循环遍历发现不会遍历到a[6],同时table长度不变,但是直接访问a[6]的值是可以的
a[6] = 6

-- 假设此时已经给a[6]赋值了,再次insert,会发现a[5]被填入了数据,同时table的长度直接变成了6,如果再进行一次insert,a[6]的值不会覆盖,新插入的值会插入到a[7]当中
table.insert(a, "five")
table.insert(a, "seven")

-- 同理假设此时给a[6]赋值,remove一个数据,会发现a[5]之前的数据会向前移动一位,但是a[6]不会
table.remove(a, 3)

6 字典table

table可以作为字典使用。

-- 声明table
a = {
a = 1,
b = "123456",
c = function()

end,
d = 123456,
[",;"] = 123456
}

-- 正常下标可以索引查找值也可以点查找值
print(a["a"])
print(a.a)

-- 异常下标只可以索引查找
print(a[",;"])

-- 对不存在的下标可以直接赋值
a["abc"] = "abcdefg"
print(a.abc)

-- 打印不存在的下标,输出的值为nil
print(a.null)

7 全局表

在lua中有一个特殊的table是_G_G存储所有的全局变量

-- 查看_G table
print(_G)

-- 定义全局变量后查看
a = 1
print(_G.a)

-- 打印所有全局变量
for key,value in pairs(_G) do
print(key, value)
end

-- table也是全局变量存在_G中,同时table里的函数是table的值,所以可以如下打印
print(_G.table)
print(_G.table.insert)

8 条件判断

在lua中,只有nilfalse才代表假,其他都是真,包括0这些。

-- 声明布尔类型
a = true
b = false

-- 值比较
print(1 > 2)
print(1 < 2)
print(1 == 2)
print(1 >= 2)
print(1 ~= 2) -- 这是不等于(不是!=,和其他语言不通)

-- 与或非
print(a and b) -- a为假返回a,a真b假返回b,a真b真返回b
print(a or b) -- 返回第一个为真的变量值,都为假返回最后一个
print(not a) -- 返回true或者false

-- 短路求值
print(a > 10 and "yes" or "no")

-- if判断
if 1 > 10 then
print("1 > 10")
elseif 1 < 10 then
print("1 < 10")
else
print("no")
end

9 循环

注:lua中没有n--n-=1这种操作,只能是n = n - 1

-- for循环,for后面的是初值,结束值,步长(不写默认是1,可以是负数)
for i = 1, 10, 2 do
print(i)
if i == 5 then break end
end

-- 在for中不可以修改i,修改i相当于新建了一个变量
for i = 10, 1, -1 do
print("first:"..tostring(i)) -- 按顺序10到1
i = 5 -- 相当于 local i = 5
print("local:"..tostring(i)) -- 重新新建了一个i,i一直是5
end

-- while循环
local n = 10
while n > 1 do
n = n - 1
print(n)
end

二、Lua进阶