欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 新闻 > 焦点 > Lua 初级教程

Lua 初级教程

2025/1/30 15:57:54 来源:https://blog.csdn.net/qq_55342245/article/details/145306824  浏览:    关键词:Lua 初级教程

Lua 初级教程

  • Lua
  • Lua 数据类型
  • 变量
  • Lua 循环
    • while 循环
    • for 循环
    • repeat...until 循环
    • 循环嵌套
    • break 语句
  • if...else 语句
  • 函数
  • Lua 数组
    • 数组的增删改
    • 二维数组
    • Table 函数
  • Lua 模块与包

IDEA运行lua脚本

Lua

lua 是一种轻量小巧的脚本语言,用标准C语言编写并以源代码形式开放, 其设计目的是为了嵌入应用程序中,从而为应用程序提供灵活的扩展和定制功能。

Lua 数据类型

Lua 是动态类型语言,变量不要类型定义,只需要为变量赋值。 值可以存储在变量中,作为参数传递或结果返回。

Lua 中有 8 个基本类型分别为:nil、boolean、number、string、userdata、function、thread 和 table。

数据类型描述
nil这个最简单,只有值nil属于该类,表示一个无效值(在条件表达式中相当于false)
boolean包含两个值:false和true
number表示双精度类型的实浮点数
string字符串由一对双引号或单引号来表示
function由 C 或 Lua 编写的函数
userdata表示任意存储在变量中的C数据结构
thread表示执行的独立线路,用于执行协同程序
tableLua 中的表(table)其实是一个"关联数组"(associative arrays),数组的索引可以是数字、字符串或表类型。在 Lua 里,table 的创建是通过"构造表达式"来完成,最简单构造表达式是{},用来创建一个空表

可以使用 type 函数测试给定变量或者值的类型:

print(type("Hello world"))      --> string
print(type(10.4*3))             --> number
print(type(print))              --> function
print(type(type))               --> function
print(type(true))               --> boolean
print(type(nil))                --> nil
print(type(type(nil)))          --> string
print(type(type(X)))            --> string

nil(空)
nil 类型表示一种没有任何有效值,它只有一个值 – nil,例如打印一个没有赋值的变量,便会输出一个 nil 值。对于全局变量和 table,nil 还有一个"删除"作用,给全局变量或者 table 表里的变量赋一个 nil 值,等同于把它们删掉。

boolean(布尔)
boolean 类型只有两个可选值:true(真) 和 false(假),Lua 把 false 和 nil 看作是 false,其他的都为 true,数字 0 也是 true。

number(数字)
对于数字,Lua 默认只有一种 number 类型。例如 2,2.2,0.2,2.35e+8,0.2e-1,7.8263692594256e-06 这些都是number类型。

string(字符串)
字符串由一对双引号或单引号来表示。也可以用 2 个方括号 “[[]]” 来表示"一块"字符串。

str = [[
this is a stringthis is a string
]]
print(str)>>>输出结果
this is a stringthis is a string

在对一个数字字符串上进行算术操作时,Lua 会尝试将这个数字字符串转成一个数字。字符串连接使用的是两个小数点。

print("2" + 6)      --> 8
print("2" + "6")    --> 8
print("2 + 6")      --> 2 + 6
print("-2e2" * "6") --> -1200
print("error" + 1)  --> 报错
print("error" .. 1)    --> error1
print("error" .. "1")  --> error1
print(1 .. 1)          --> 11
print("1" .. "1")      --> 11

使用 # 来计算字符串的长度,放在字符串前面。(补充一下,注释代码用两个减号,不能用井号和双斜杠)

a = "abcdefg"
print(#a)      --> 7
print(#"xyz")  --> 3

table(表)
在 Lua 里,table 的创建是通过"构造表达式"来完成,最简单构造表达式是{},用来创建一个空表。也可以在表里添加一些数据,直接初始化表。
Lua 中的表(table)其实是一个"关联数组"(associative arrays),数组的索引可以是数字或者是字符串。
table 不会固定长度大小,有新数据添加时 table 长度会自动增长,没初始的 table 都是 nil。

-- 创建一个空的 table
local tbl1 = {}
-- 直接初始表
local tbl = {"apple", "orange", "grape"}print(tbl1)
print(tbl)tbl[-1] = "National"
tbl[1] = nil
tbl[2] = "Tomato"
tbl["key1"] = "value1"print(#tbl)
print("============")
for k, v in pairs(tbl1) doprint(k .. " : " .. v)
end
print("============")
for k, v in pairs(tbl) doprint(k .. " : " .. v)
end>>>输出结果
table: 00C99200
table: 00C99700
0
============
============
3 : grape
2 : Tomato
-1 : National
key1 : value1

function(函数)
在 Lua 中,函数是被看作是"第一类值(First-Class Value)",函数可以存在变量里。

-- function_test.lua 脚本文件
function factorial1(n)if n == 0 thenreturn 1elsereturn n * factorial1(n - 1)end
end
print(factorial1(5))
factorial2 = factorial1
print(factorial2(5))>>>输出结果
120
120

function 可以以匿名函数(anonymous function)的方式通过参数传递。

-- function_test2.lua 脚本文件
function testFun(tab,fun)for k ,v in pairs(tab) doprint(fun(k,v))end
endtab={key1="val1",key2="val2"};
testFun(tab,
function(key,val)--匿名函数return key.."="..val;
end
)>>>输出结果
key1=val1
key2=val2

thread(线程)
在 Lua 里,最主要的线程是协同程序(coroutine)。它跟线程(thread)差不多,拥有自己独立的栈、局部变量和指令指针,可以跟其他协同程序共享全局变量和其他大部分东西。

线程跟协程的区别:线程可以同时多个运行,而协程任意时刻只能运行一个,并且处于运行状态的协程只有被挂起(suspend)时才会暂停。

userdata(自定义类型)
userdata 是一种用户自定义数据,用于表示一种由应用程序或 C/C++ 语言库所创建的类型,可以将任意 C/C++ 的任意数据类型的数据(通常是 struct 和 指针)存储到 Lua 变量中调用。

变量

应该尽可能的使用局部变量,有两个好处:

  1. 避免命名冲突。
  2. 访问局部变量的速度比全局变量更快。
-- test.lua 文件脚本
a = 5               -- 全局变量
local b = 5         -- 局部变量function joke()c = 5           -- 全局变量local d = 6     -- 局部变量print(a, b, c, d) --> 5 5 5 6
endjoke()
print(c,d)          --> 5 nil
print(a, b, c, d)   --> 5 5 5 nildolocal a = 6     -- 局部变量b = 6           -- 对局部变量重新赋值print(a,b);     --> 6 6
endprint(a,b)      --> 5 6

Lua 可以对多个变量同时赋值,变量列表和值列表的各个元素用逗号分开,赋值语句右边的值会依次赋给左边的变量。
赋值语句Lua会先计算右边所有的值然后再执行赋值操作,所以我们可以不引入第三变量就能对变量的值进行交换。

a, b = 10, 20       --> 等价于       a=10; b=20x, y = y, x                     -- swap 'x' for 'y'
a[i], a[j] = a[j], a[i]         -- swap 'a[i]' for 'a[j]'

赋值的时候,等号两边的元素数量不匹配

a, b, c = 0, 1
print(a,b,c)             --> 0   1   nila, b = 3, 4, 5
print(a,b)               --> 3   4a, b, c = 0
print(a,b,c)             --> 0   nil   nila, b, c = 0, 0, 0
print(a,b,c)             --> 0   0   0

Lua 循环

while 循环

-- 输出10到19
a=10
while( a < 20 )
doprint(a)a = a+1
end

for 循环

-- 输出-10到10(一共21个数)
for i=-10,10 doprint(i)
end-- 输出 -10到10之间的偶数(一共11个数)
for i=-10,10,2 doprint(i)
end-- 输出10到1
for i=10,1,-1 doprint(i)
end-- 不进入循环体,所以不打印数字111
for i=1,10,-1 doprint(111)
end

i是数组索引值,v是对应索引的数组元素值。ipairs是Lua提供的一个迭代器函数,用来迭代数组

a = {key1 = "value1", key2 = "value2", key3 = "value3"}
-- 打印表a的键和值
for k, v in pairs(a) doprint(k, v)
endb = {"apple", "banana", "orange"}
-- 打印数组b的索引和值
for i, v in pairs(b) doprint(i, v)
end-- 下面的写法会报错
for i in a doprint(i)
end

repeat…until 循环

repeat…until 循环语句不同于 for 和 while循环,for 和 while 循环的条件语句在当前循环执行开始时判断,而 repeat…until 循环的条件语句在当前循环结束后判断。

repeatstatements
until( condition )

循环条件判断语句(condition)在循环体末尾部分,所以在条件进行判断前循环体都会执行一次。
如果条件判断语句(condition)为 false,循环会重新开始执行,直到条件判断语句(condition)为 true 才会停止执行。

-- 输出10到15(如果交换循环体里的两行代码,打印结果为11到16)
a = 10
repeatprint(a)a = a + 1
until( a > 15 )

结构与do while 循环类似。不管条件如何都会进入循环体一次。不同的是,当until 的条件判断为 true 时会停止执行。

循环嵌套

-- 打印九九乘法表
for i = 1,9
dolocal line = ""for j = 1,idoline = line .. " ".. (j.."x"..i.."="..i*j)endprint(line)
end

break 语句

break 语句插入在循环体中,用于退出当前循环或语句。
如果使用循环嵌套,break语句将停止最内层循环的执行,并开始执行外层的循环语句。

-- 输出1到5
for i = 1,10 doprint(i)if (i == 5) thenbreakend
end

if…else 语句

a = 50
if (a == 10) thenprint("a 的值为 10")
elseif (a == 20) thenprint("a 的值为 20")
elseif (a == 30) thenprint("a 的值为 30")
elseprint("没有匹配 a 的值")
end
print("a 的真实值为: ", a)>>>输出结果
没有匹配 a 的值
a 的真实值为: 	50

lua中不支持switch-case语句,我们可以使用if elseif来代替

a = "Sunday"
if (a == "Monday") thenprint("星期一")
elseif (a == "Tuesday") thenprint("星期二")
elseif (a == "Wednesday") thenprint("星期三")
elseif (a == "Thursday") thenprint("星期四")
elseprint("休息日")
end

函数

多个入参

-- 函数返回两个值的最大值
function max(num1, num2)if (num1 > num2) thenresult = num1;elseresult = num2;endreturn result; 
end-- 对所有参数求和
function add(...)local sum = 0;local args = {...}  -- 将所有参数收集到一个表里for i, v in ipairs(args) dosum = sum + vendreturn sum
end

多参数的循环也可以这么写 for i, v in ipairs{…}

多返回值

function maximum (a)local mi = 1             -- 最大值索引local m = a[mi]          -- 最大值for i,val in ipairs(a) doif val > m thenmi = im = valendendreturn m, mi
end
index, num = maximum({8,10,23,12,5});

通常在遍历变长参数的时候只需要使用 {…},然而变长参数可能会包含一些 nil,那么就可以用 select 函数来访问变长参数了:select(‘#’, …) 或者 select(n, …)

select(‘#’, …) 返回可变参数的长度。
select(n, …) 用于返回从起点 n 开始到结束位置的所有参数列表。
调用 select 时,必须传入一个固定实参 selector(选择开关) 和一系列变长参数。如果 select为数字 n,那么 select 返回参数列表中从索引 n 开始到结束位置的所有参数列表,否则只能为字符串 #,这样 select 返回变长参数的总数。

function myFun (...)a = {...}print(#a)  --> 6b = select(2,...)  --函数返回一个列表。因为左侧变量只有一个,所以会将列表第一个值赋值给变量print (b)  --> 10print(select("#", ...))    --> 6print(select("3", ...))    --> nil	7	3	5print(select(3, ...))      --> nil	7	3	5
end
myFun(8,10,nil,7,3,5);

Lua 数组

lua 索引默认从 1 开始。使用整数索引来访问数组元素,如果指定的索引没有值则返回 nil。除此外还可以以负数为数组索引值

-- 创建一个数组
local myArray = {10, 20, 30, 40, 50}
-- 循环遍历数组
for i = -1, #myArray doprint(myArray[i])
end>>>输出结果
nil
nil
10
20
30
40
50
-- 将 -2 到 2 之间的五个整数,添加到数组中
array = {}
for i= -2, 2 doarray[i] = i
end

数组的增删改

-- 创建一个数组
local myArray = {10, 20, 30, 40, 50}-- 添加新元素到数组末尾
myArray[#myArray + 1] = 60-- 修改数组元素(将20修改为25)
myArray[2] = 25-- 删除第三个元素(将30删除)
table.remove(myArray, 3)

二维数组

-- 依次将1到9写入数组中
array = {}
for i=1,3 doarray[i] = {}for j=1,3 doarray[i][j] = 3*(i-1)+jend
end

Table 函数

concat 拼接

local myArray = {"Sun", "Mon", "Tue", "Wed", "Thu", "Fri"}
print(table.concat(myArray))   --> SunMonTueWedThuFri
print(table.concat(myArray, "-"))  --> Sun-Mon-Tue-Wed-Thu-Fri
print(table.concat(myArray, "-", 3)) --> Tue-Wed-Thu-Fri
print(table.concat(myArray,"-",1,5))  --> Sun-Mon-Tue-Wed-Thu

insert 插入

local myArray = {"Sun", "Mon", "Tue", "Wed", "Thu", "Fri"}
table.insert(myArray, "DayEnd")   --> 数组末尾添加元素 DayEnd
table.insert(myArray, 2, "Day2")   --> 数组第二个位置插入元素 Day2

remove 删除

local myArray = {"Sun", "Mon", "Tue", "Wed", "Thu", "Fri"}
print(table.remove(myArray))   --> 删除数组最后一个元素,并返回 Fri
print(table.remove(myArray, 3))   --> 删除数组第三个元素,并返回 Tue

Lua 模块与包

require("./utils/TimeUtil")print(dateTime.year)
print(dateTime.name)
-- 函数有入参必须传,不写会报错。但如果函数没入参,参数传不传都可以
dateTime.fun1(2)
--dateTime.fun2()  fun2是私有函数,无法调用
dateTime.fun3()>>>输出结果
2025
dateTime
函数1打印参数a:2
函数2打印

TimeUtil.lua 文件内容

-- 定义一个名为 dateTime 的模块
dateTime = {}
-- 定义两个常量
dateTime.year = 2025
dateTime.name = "dateTime"
-- 定义公有一个函数
function dateTime.fun1(a)print("函数1打印参数a:" .. a)
end
-- 定义私有一个函数
local function fun2()print("函数2打印")
end
-- 通过公有函数调用私有函数
function dateTime.fun3()fun2()
endreturn dateTime

Lua 的模块是由变量、函数等已知元素组成的 table,因此创建一个模块很简单,就是创建一个 table,然后把需要导出的常量、函数放入其中,最后返回这个 table 就行。
模块的结构就是一个 table 的结构,因此可以像操作调用 table 里的元素那样来操作调用模块里的常量或函数。
上面的 func2 声明为程序块的局部变量,即表示一个私有函数,因此是不能从外部访问模块里的这个私有函数,必须通过模块里的公有函数来调用。

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com