一、在线虚拟机环境
二、变量
1. 变量声明
- 全局变量
不加任何修饰符的默认情况下声明的变量即为全局变量.
-- 以下是全局变量
a = 1
b = 2
- 局部变量
使用 local 修饰符将变量声明为局部变量.
local a = 1
local b = 2
- 空
所有没有被声明的变量默认为空.
print(a)
-- 输出为 nil
- 声明多个变量并赋值
Lua中可以用以下语法同时声明多个变量并且赋值:
a, b = 1, 2
print(1, 2)
2. 变量的数据类型
数字(number)类型
最基本的数字即为number类型, 且其拥有多种表示方法:
-- 十进制数字
a = 1
b = 2
-- 以十六进制表示的数字类型
c = 0x11 -- 等于 17
-- 科学计数法
d = 2e10 -- 等于 20000000000.0
字符串(string)类型
与其他语言相似, 在Lua中可以用双引号或单引号来表示一个字符串:
str1 = "hello world"
str2 = 'foo bar'
print(str1) -- 输出 hello world
print(str2) -- 输出 foo bar
Lua中可以使用双中括号来声明一个文本块:
str = [[
114514
1919
810
]]
print(str)
Lua中可以使用字符串连接符号来进行字符串的连接:
a = 'foo'
b = 'bar'
c = a..b
print(c) -- 输出 foobar
使用tostring()
函数可以将其他类型的变量转换为字符串:
a = 123
b = tostring(a)
print(type(b)) -- 输出 string
同时, 也可以使用tonumber()
函数来将字符串变量转换为Number类型:
a = "10"
b = tonumber(a)
print(type(b)) -- 输出 number
-- 注意, 如果tonumber()转换失败, 则输出结果将为nil
c = "abc"
d = tonumber(c)
print(d) -- 输出 nil
使用#
号获取字符串的长度:
a = "114514 1919 810"
print(#a) -- 输出 15
字符串(string)内建函数
string.char()
在Lua中的字符串类似其他语言, 本质上是一个字符(char)类型的数组. 对于 string.char(...)函数, 它可以接收一组ascii码值, 然后返回一个由这些字符组成的字符串.
s = string.char(0x30, 0x31, 0x32, 0x34)
print(s) -- 输出 0124
string.byte()
函数string.byte(x, y)
接收两个变量, x为任意字符串, y则是该字符串中任意字符的下标, 该函数返回对应下标的字符的ascii码值
str = "hello"
n = string.byte(str, 2)
print(n) -- 输出 101, 即e
print(string.char(n)) -- 输出 e
布尔(boolean)类型
与其他语言类似, Lua拥有布尔类型, 其值只有 true 和 false 两种
a = true
b = false
布尔值可以用比较符号得出, Lua支持的比较符号有以下几种
-- 小于
print(1 < 2)
-- 大于
print(1 > 2)
-- 小于等于
print(1 <= 2)
-- 大于等于
print(1 >= 2)
-- 等于
print(1 == 2)
-- 不等于
print(1 ~= 2)
同时, Lua使用 and、or
和 not 等关键字来作为逻辑连接词
a = true
b = false
-- a且b
print(a and b) -- 输出 false
-- a或b
print(a or b) -- 输出 true
-- 非a
print(not a) -- 输出 false
在Lua中, 只有nil
和false
为成假赋值, 其他所有值均为成真赋值
a = nil -- 假
b = 0 -- 真
-- 由于无法进行类型转换, 因此直接使用两次求反运算来转换为布尔值
print(not not a) -- 输出 false
print(not not b) -- 输出 true
当使用逻辑连接词对非布尔值进行运算时, 将不一定会返回布尔值,
例如, 当多个变量以and
相连时, 会返回第一个为成假赋值(false/nil)的变量:
a = "hello"
b = 0
c = false
print(a and b and c) -- 输出 false
a = nil
b = 0
c = 123
print(a and b and c) -- 输出 nil
当相连的变量中不含有成假赋值的变量时, 返回最后一个变量(右值)
a = "hello"
b = 0
c = 123
print(a and b and c) -- 输出 123
类似的, 对于or
语句相连的变量, 会返回第一个成真赋值, 而当不存在成真赋值时, 返回最后一个变量(右值)
a = 'hello'
b = a
c = nil
print(a or b or c) -- 输出 hello
a = false
b = false
c = nil
print(a or b or c) -- 输出 nil
利用上述特性, 可以用逻辑连接词来构建一个三元表达式
a = 1
print(1 > 0 and "yes" or "no") -- 输出 yes
表(table)类型
表是一种类似数组的数据结构, 可以用一对大括号进行声明
-- 声明一个表
a = {}
print(type(a)) -- 输出 table
表中可以存放任意类型的元素, 除了数字型和字符串型外还可以存储函数, 甚至可以在表中嵌套表
a = {
"hello",
114514,
function() end,
{}
}
注意 表使用一对中括号+下标来存取元素, 而下标的起始数为1
a = {"hello", 123}
print(a[0]) -- 输出为 nil
print(a[1]) -- 输出为 hello
-- 使用等号可以直接为任意下标的元素赋值
a[5] = "foo"
print(a[5]) -- 输出为 foo
使用#
符号也可以获取到表的长度
a = {123, 456}
print(#a) -- 输出为 2
表(table)的内建函数
- 插入元素
使用table.insert(x, y)
语句来为一个表插入元素, x为表名, y为任意变量
a = {}
table.insert(a, "hello")
print(a[1]) -- 输出 hello
还可以使用table.insert(x, y, z)
语句来在某个表的指定位置插入元素, x为表名, y为对应位置的下标, z为任意变量
a = {"hello", 123}
table.insert(a, 1, "foo") -- 在下标为1的位置插入元素, 即首位
print(a[1]) -- 输出为 foo
- 删除元素
使用table.remove(x, y)
来删除表中任意位置的元素, 其中x为表名, y为对于位置的下标
a = {"hello", 123}
table.remove(a, 1) -- 删除a表中下标为1的元素, 即"hello"
-- 删除元素后所有剩余元素向前移动一位
print(a[1]) -- 输出为 123
table.remove(x, y) 将返回其删除掉的元素
a = {"hello", 123}
local b = table.remove(a, 1)
print(b) -- 输出为 hello
表(table)的字符串(string)下标
Lua中的表还拥有类似Map的属性, 即可以使用字符串作为下标, 实现类似于key的效果.
a = {
el1 = 1, --使用 "el1"作为下标
el2 = 10
}
-- 注意 使用字符串下标时, 存取元素需要带有双引号来表示其下标, 否则会被认定为是一个变量
print(a["el1"]) -- 输出 1
当下标的命名符合变量的命名规范时, 还可以直接用 表名.下标名 来存取元素
a = {
el1 = 1,
el2 = 10
}
print(a.el2) -- 输出 10
全局表
在Lua中有一个特殊的表, 被称为全局表, 变量名为_G
, 它存储了当前上下文中的所有全局变量
a = 114514
print(_G["a"]) -- 输出 114514
注意 _G 表存储了所有的全局变量, 包括之前用到的 table 实际上便是Lua中内建的一个表, 该表存储了与表有关的操作函数
print(_G["table"]) -- 输出 table: 0x10
print(_G["table"]["insert"]) -- 输出 function: 0x155
三、运算符
除了最基本的加减乘除运算, Lua还支持一些其他的符号.
- 乘幂符号
乘幂符号用于计算x的y次方, 具体语法如下:
a = 10^5 -- 等于10的5次方
print(a) -- 输出为100000.0
- 左移、右移
基本的二进制移位运算:
a = 1 << 3 -- 将1左移3位 即 001 → 010 → 100 = 8
print(a) -- 输出 8
四、 函数
- 函数声明
一个最基础的函数声明如下:
function hello()
-- 函数体
end
在Lua中, 函数本质上也是一种变量类型, 可以将函数名在左侧声明, 然后用等号连接:
hello = function()
-- 函数体
end
- 形式参数
函数的形式参数声明类似变量:
-- 此处声明了三个形式参数a, b, c
function f(a, b, c)
-- 函数体
end
类似变量, 当形式参数被声明而没有传入值时, 未传值的形式参数值为nil
function f(a, b, c)
print(a, b, c)
end
f(114514, 1919810) -- 输出 114514 1919810 nil
- 返回值
默认情况下, 函数返回值为nil
function f()
-- 函数体
end
result = f()
print(result) -- 输出 nil
可以使用return
语句来返回值
function f(a, b)
return a
end
result = f(1, 2)
print(result) -- 输出 1
return语句也可以返回多个值
function f(a, b)
return a, b
end
print(f(1, 2)) -- 输出 1 2
-- 可以配合多重赋值语句使用
local i, j = f(1, 2)
print(i) -- 输出 1
print(j) -- 输出 2
五、分支判断语句
在Lua中的分支判断语句由if
关键字开始判断语句, 在than
关键字处结束判断语句, 并开始一段代码块, 用else
关键字开始另一分支代码块, 最后用end
关键字结束整个语句, 具体如下:
a = 1
b = 2
if a==b then
print("foo")
else
print("no")
end
-- 输出 no
使用elseif <布尔表达式> then
语句来开始另一个条件分支代码块
a = 1
b = 2
if a==b then
print("foo")
elseif b > a then
print("bar")
else
print("no")
end
-- 输出 bar
注意 在elseif
语句中, else和if
不可分开写, 否则将会视为一个新的if
语句而导致编译报错
六、循环语句
在Lua中拥有三种循环语句, 分别使用 for、while
和 repeat 关键字
for循环
for循环使用for
关键字作为起始, 然后接受一个循环范围表达式, 类似i = 1, 10
表示从1到10, 然后在 do 关键字之后开始循环代码块, 最后用end
关键字结束代码块
-- 这是一个最简单的循环
for i=1,10 do
print(i) -- 输出0 1 2 3 4 5 6 7 8 9 10
end
-- 此处的i为局部变量, 离开for代码块后将没有定义
print(i) -- 输出nil
循环范围表达式可以加入第三个值来代表i
所增加的步长
for i=1,10,2 do
print(i) -- 输出 1 3 5 7 9
end
步长值可以是负数, 此时每次循环使得i
减少对应步长值, 此时对应的i
值应大于结束值, 否则代码块不会被执行
for i=10,1,-1 do
print(i) -- 输出 10 9 8 7 6 5 4 3 2 1
end
循环过程中, i的值不能被更改, 若在循环代码块中对i
值进行修改, 则得到的是一个新的i
for i=10,1,-1 do
print(i) -- 输出 10 9 8 7 6 5 4 3 2 1
i = 1
end
循环过程中, 使用break
关键字提前退出循环
for i=10,1,-1 do
print(i) -- 输出 10 9 8
if i == 8 then break end
end
while循环
while循环类似for
循环表达式, 但是将循环范围的表达式换成了布尔表达式, 当布尔表达式成真时, 执行循环代码块中的语句.
local x = 10
while x > 0 do
print(x) -- 输出 10 9 8 7 6 5 4 3 2 1
x = x - 1
end