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

  • 只有两个值:truefalse

  • lua把falsenil看作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

ipairs和pairs的区别

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提供了控制函数流程的语句,如breakreturngoto

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)
posted @ 2025-04-18 11:13  Midraos  阅读(120)  评论(0)    收藏  举报