lua入门
lua
数据类型
lua 是动态类型语言,变量不需要类型定义,可直接赋值。 值可以存储在变量中,作为参数传递或结果返回。lua 中有 8 个基本类型分别为:nil、boolean、number、string、userdata、function、thread 和 table。
type函数获取变量类型
print(type("ciallo"))
-- string
print(type(true))
-- boolean
print(type(1234))
-- number
print(type(print))
-- function
print(type(nil))
-- nil
print(type({}))
-- table
nil
-
只有值nil属于
nil
类型,表示一个无效的值,再条件表达式中相当于false。 -
nil
类型表示没有任何有效值,打印一个没有赋值的变量,会输出nil -
对于全局变量和
table
,nil还起到删除的作用,将nil赋值给全局变量或者table,等同于删除 -
nil做比较时应加上双引号
boolean
-
只有两个值:
true
和false
-
lua把
false
和nil
看作flase,其它都为true
,数字0也是true
number
- 默认只有一种 number 类型 – double(双精度)类型(默认类型可以修改 luaconf.h 里的定义)
string
-
字符串由一对双引号或单引号来表示
-
也可以用 2 个方括号 “[[]]” 来表示"一块"字符串
-
在对一个数字字符串上进行算术操作时,会尝试将这个数字字符串转成一个数字
-
使用 # 来计算字符串的长度,放在字符串前面
a = "ciallo";
b = 'ciallo';
c = [[ciallo]];
print(#a);
print(#b);
print(#c);
print(#a+#b+#c);
--输出结果
--[[
6
6
6
18
]]
function
-
由 C 或 lua 编写的函数
-
函数是被看作是"第一类值(First-Class Value)",函数可以存在变量里
-
function 可以以匿名函数(anonymous function)的方式通过参数传递
thread
- 表示执行的独立协程,用于执行协同程序
- 最主要的线程是协同程序(coroutine)。它跟线程(thread)差不多,拥有自己独立的栈、局部变量和指令指针,可以跟其他协同程序共享全局变量和其他大部分东西
- 线程跟协程的区别:线程可以同时多个运行,而协程任意时刻只能运行一个,并且处于运行状态的协程只有被挂起(suspend)时才会暂停
userdata
- userdata 是一种用户自定义数据,用于表示一种由应用程序或 C/C++ 语言库所创建的类型,可以将任意 C/C++ 的任意数据类型的数据(通常是 struct 和 指针)存储到 lua 变量中调用
table
- 表(table)其实是一个"关联数组"(associative arrays),数组的索引可以是数字、字符串或表类型。在 lua 里,table 的创建是通过"构造表达式"来完成,最简单构造表达式是{},用来创建一个空表
创建一个空的table
local myTable = {}
创建一个带有初始值的table
local myTable = {1, 2, 3, 4, 5} -- 数组形式的table
local myTable = {name = "John", age = 25} -- 字典形式的table
访问和修改table
中的元素
local myTable = {1, 2, 3, 4, 5}
print(myTable[1]) -- 输出第一个元素:1
myTable[2] = 10 -- 修改第二个元素的值
print(myTable[2]) -- 输出修改后的值:10
使用#
操作符获取table
的长度(只适用于数组部分)
local myTable = {1, 2, 3, 4, 5}
print(#myTable) -- 输出数组部分的长度:5
使用table
作为字典(键值对)
local myTable = {name = "John", age = 25}
print(myTable.name) -- 输出键为"name"的值:"John"
myTable.city = "New York" -- 添加新的键值对
print(myTable.city) -- 输出新增的键值对:"New York"
迭代遍历table
local myTable = {1, 2, 3, 4, 5}
for key, value in ipairs(myTable) do
print(key, value)
end
table
的嵌套使用
local myTable = {
name = "John",
age = 25,
contact = {
phone = "123456789",
email = "john@example.com"
}
}
print(myTable.contact.phone) -- 访问嵌套的table中的值:"123456789"
变量
变量在使用前,必须在代码中进行声明,即创建该变量。
编译程序执行代码之前编译器需要知道如何给语句变量开辟存储区,用于存储变量的值。
lua 变量有三种类型:全局变量、局部变量、表中的域。
lua 中的变量全是全局变量,那怕是语句块或是函数里,除非用 local 显式声明为局部变量。
局部变量的作用域为从声明位置开始到所在语句块结束。
变量的默认值均为 nil。
赋值语句
- 赋值是改变一个变量的值和改变表域的最基本的方法。
- 可以对多个变量同时赋值,变量列表和值列表的各个元素用逗号分开,赋值语句右边的值会依次赋给左边的变量
- 遇到赋值语句会先计算右边所有的值然后再执行赋值操作
- 当变量个数和值的个数不一致时,.变量个数 > 值的个数,按变量个数补足nil.变量个数 < 值的个数,多余的值会被忽略
索引
索引操作用于访问和操作table
中的元素
数字索引
使用整数作为索引来访问数组部分的元素
local myTable = {10, 20, 30}
print(myTable[1]) -- 输出第一个元素:10
print(myTable[2]) -- 输出第二个元素:20
字符串索引
使用字符串作为索引来访问字典部分的元素
local myTable = {name = "John", age = 25}
print(myTable["name"]) -- 输出键为"name"的值:"John"
print(myTable["age"]) -- 输出键为"age"的值:25
当使用字符串作为索引时,可以使用点号(`.`)来简化语法
print(myTable.name) -- 输出键为"name"的值:"John"
print(myTable.age) -- 输出键为"age"的值:25
混合索引
table
中的索引可以同时使用数字和字符串
local myTable = {10, 20, name = "John", age = 25}
print(myTable[1]) -- 输出第一个元素:10
print(myTable["name"]) -- 输出键为"name"的值:"John"
特殊索引操作
Lua还提供了一些特殊的索引操作符和函数来访问和操作table
#
操作符用于获取数组部分的长度
local myTable = {1, 2, 3, 4, 5}
print(#myTable) -- 输出数组部分的长度:5
ipairs
函数用于迭代遍历数组部分的元素
local myTable = {10, 20, 30}
for index, value in ipairs(myTable) do
print(index, value)
end
pairs
函数用于迭代遍历整个table
的键值对
local myTable = {name = "John", age = 25}
for key, value in pairs(myTable) do
print(key, value)
end
当使用索引操作时,如果指定的索引不存在,Lua会返回`nil`
条件判断语句
Lua使用if
语句进行条件判断,支持嵌套的if-elseif-else
结构
if condition1 then
-- 当条件1为真时执行的代码
elseif condition2 then
-- 当条件1不满足但条件2为真时执行的代码
else
-- 当所有条件都不满足时执行的代码
end
循环语句
循环语句是由循环体及循环的终止条件两部分组成
Lua提供了多种循环结构,包括while
循环、repeat-until
循环和for
循环
while
while condition do
-- 循环体执行的代码
end
repeat-until
循环
repeat
-- 循环体执行的代码
until condition
for
循环
for variable = start, end, step do
-- 循环体执行的代码
end
其中,variable
是循环变量,start
是起始值,end
是结束值,step
是步长
控制流
Lua提供了控制函数流程的语句,如break
、return
和goto
。
break
语句
用于跳出当前循环
while condition do
if someCondition then
break
end
-- 循环体执行的代码
end
return
语句
用于从函数中返回值
function add(a, b)
return a + b
end
goto
语句
用于无条件跳转到指定的代码行(请谨慎使用)
local count = 0
::loop::
count = count + 1
if count < 5 then
goto loop
end
函数
函数定义
optional_function_scope function function_name( argument1, argument2, argument3..., argumentn)
function_body
return result_params_comma_separated
end
- optional_function_scope: 该参数是可选的制定函数是全局函数还是局部函数,未设置该参数默认为全局函数,如果你需要设置函数为局部函数需要使用关键字 local。
- function_name: 指定函数名称。
- argument1, argument2, argument3…, argumentn: 函数参数,多个参数以逗号隔开,函数也可以不带参数。
- function_body: 函数体,函数中需要执行的代码语句块
- result_params_comma_separated: 函数返回值,lua语言函数可以返回多个值,每个值以逗号隔开
-- 定义一个无参数的函数
function sayHello()
print("Hello!")
end
-- 定义一个带参数和返回值的函数
function add(a, b)
return a + b
end
函数调用
可以通过函数名和参数列表来调用函数
-- 调用无参数的函数
sayHello()
-- 调用带参数和返回值的函数
local result = add(10, 20)
print(result) -- 输出:30
函数参数和返回值
函数可以接收多个参数,并且可以返回多个值
function addAndMultiply(a, b)
local sum = a + b
local product = a * b
return sum, product
end
local s, p = addAndMultiply(5, 3)
print(s, p) -- 输出:8 15
可变参数
函数可以接受可变数目的参数,和 C 语言类似,在函数参数列表中使用三点 … 表示函数有可变的参数
function add(...)
local s = 0
for i, v in ipairs{...} do
s = s+v
end
return s
end
print(add(1,2,3,4,5,6))
匿名函数(函数字面量)
Lua还支持匿名函数的定义,也称为函数字面量或lambda函数
local square = function(x)
return x * x
end
print(square(5)) -- 输出:25
函数作为参数
在Lua中,函数可以作为参数传递给其他函数
function applyOperation(x, operation)
return operation(x)
end
function double(x)
return 2 * x
end
local result = applyOperation(5, double)
print(result) -- 输出:10
函数作为返回值
在Lua中,函数可以作为另一个函数的返回值。
function createMultiplier(factor)
return function(x)
return factor * x
end
end
local double = createMultiplier(2)
local result = double(5)
print(result) -- 输出:10
函数的闭包
闭包是一种特殊的函数,它可以捕获并记住其创建时所处的环境(变量和值),即使在其创建环境退出后仍然可以访问和操作这些变量。在Lua中,函数的闭包是通过函数内部定义的嵌套函数来实现的。
function outerFunction()
local x = 10 -- 在外部函数中定义的局部变量
-- 内部函数是闭包,可以访问外部函数中的变量
local function innerFunction()
print(x) -- 访问外部函数的变量
end
return innerFunction -- 返回内部函数作为闭包
end
local closure = outerFunction() -- 获取闭包函数
closure() -- 输出:10
在上面的示例中,innerFunction
是一个内部函数,它捕获了outerFunction
的局部变量x
。尽管outerFunction
的执行环境已经结束,但通过闭包的方式,innerFunction
仍然可以访问和操作变量x
的值。
闭包在编程中有许多应用场景,其中包括:
- 封装数据和行为:使用闭包可以创建具有私有状态和行为的对象,将数据和相关操作封装在一个闭包中。
- 记忆函数状态:通过闭包可以实现某些函数的记忆功能,缓存之前的计算结果以提高性能。
- 创建回调函数:闭包常用于创建回调函数,在事件处理、异步编程等场景中发挥重要作用。
闭包的特性使得它成为一种强大的编程工具,可以提供灵活性和封装性。在Lua中,通过嵌套函数和闭包的使用,可以实现许多高级的编程技术和模式
数组
一维数组
array = {'lua','Tutorial'}
for i = 0, 2 do
print(array[i])
end
-- 输出: nil lua Tutorial
- 使用整数索引来访问数组元素,如果相应的索引没有值则返回nil
- 索引值是以 1 为起始,但你也可以指定 0或者负数 开始。
多维数组
a = {}
for i=1,3 do
a[i] = {}
for j = 1,3 do
a[i][j] = i*j
end
end
for k,v in ipairs(a) do
for k1,v1 in ipairs(v) do
print(v1)
end
end
输入输出
标准输出
使用print
函数将数据输出到标准输出(通常是控制台)
print("Hello, World!") -- 输出字符串到标准输出
标准输入
使用io.read
函数从标准输入(通常是控制台)读取用户输入的数据
print("Please enter your name:")
local name = io.read() -- 读取用户输入的数据
print("Hello, " .. name .. "!")
文件读写
使用io.open
函数来打开文件并进行读写操作
-- 写入文件
local file = io.open("output.txt", "w") -- 打开文件用于写入
file:write("Hello, World!") -- 写入数据到文件
file:close() -- 关闭文件
-- 读取文件
local file = io.open("input.txt", "r") -- 打开文件用于读取
local content = file:read("*a") -- 读取文件的全部内容
file:close() -- 关闭文件
print(content)
格式化输出
local name = "John"
local age = 25
local message = string.format("My name is %s and I am %d years old.", name, age)
print(message)
字符串
字符串拼接
使用..
操作符或string.concat
函数将多个字符串连接起来。
local str1 = "Hello"
local str2 = "World"
local result1 = str1 .. " " .. str2 -- 使用 .. 连接字符串
print(result1)
大量字符串拼接使用table.concat
local tb = {}
table.insert(tb,"hello")
table.insert(tb,' ')
table.insert(tb,"world")
print(table.concat(tb))
字符串长度
使用#
操作符或string.len
函数获取字符串的长度。
local str = "Hello, World!"
local length1 = #str -- 使用 # 获取字符串长度
local length2 = string.len(str) -- 使用 string.len 函数获取字符串长度
print(length1, length2)
字符串查找和替换
使用string.find
函数查找指定子串在字符串中的位置,使用string.gsub
函数进行字符串替换
local str = "Hello, Lua!"
local start, endPos = string.find(str, "Lua") -- 查找 "Lua" 在字符串中的位置
print(start, endPos)
local replaced = string.gsub(str, "Lua", "World") -- 将 "Lua" 替换为 "World"
print(replaced)
print(str)
字符串切割
使用string.gmatch
函数根据指定模式切割字符串为迭代器,可以遍历获取切割后的子串
local str = "Hello,World,Lua"
local pattern = "[^,]+"
for substr in string.gmatch(str, pattern) do
print(substr) -- 逐个输出切割后的子串
end
字符串转换
使用string.upper
将字符串转换为大写,使用string.lower
将字符串转换为小写。
local str = "Hello, Lua!"
local upper = string.upper(str) -- 将字符串转换为大写
local lower = string.lower(str) -- 将字符串转换为小写
字符串分割
使用string.split
函数根据指定的分隔符将字符串分割为多个子串
function string.split(str, delimiter)
local result = {}
local pattern = string.format("([^%s]+)", delimiter)
str:gsub(pattern, function(substr) table.insert(result, substr) end)
return result
end
local str = "Hello,World,Lua"
local delimiter = ","
local substrs = string.split(str, delimiter)