Lua 语法

本文探讨了Lua作为轻量级脚本语言如何通过C语言实现,以及其在应用程序中的关键特性,如全局和局部变量、数据类型、控制结构、函数、表和元表,以及协同程序和面向对象编程的模拟。重点介绍了逻辑运算符、字符串操作、表操作和元方法的使用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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

其设计目的是为了嵌入应用程序中,从而为应用程序提供灵活的扩展和定制功能。

打印语句

print("Hello SDHK")

注释

--注释

--[[
    注释段
--]]

关键词

andbreakdoelse
elseifendfalsefor
functionifinlocal
nilnotorrepeat
returnthentrueuntil
whilegoto

逻辑运算符

下表列出了 Lua 语言中的常用逻辑运算符,设定 A 的值为 true,B 的值为 false:

操作符描述实例
and逻辑与操作符。 若 A 为 false,则返回 A,否则返回 B。(A and B) 为 false。
or逻辑或操作符。 若 A 为 true,则返回 A,否则返回 B。(A or B) 为 true。
not逻辑非操作符。与逻辑运算结果相反,如果条件为 true,逻辑非为 false。not(A and B) 为 true。

全局变量

在默认情况下,变量总是认为是全局的。

全局变量不需要声明,给一个变量赋值后即创建了这个全局变量,访问一个没有初始化的全局变量也不会出错,只不过得到的结果是:nil。

想删除一个全局变量,只需要将变量赋值为nil。

局部变量

i1 = 0--全局变量

local i2 = 0;--局部变量

数据类型

print(type("Hello world"))      --string
print(type(10.4*3))             --number Lua 默认只有一种 number 类型 -- double(双精度)类型
print(type(print))              --function
print(type(type))               --function
print(type(true))               --boolean
print(type(nil))                --nil
print(type(type(X)))            --string ,X为nil

字符串

str = "this is string"

html = [[
    
    一段字符串

]]

print(#"获取字符串长度")

print(str.."字符串连接"..html)
str = "My String"

str2 = string.upper(str)--转换成大写字母

str3= string.lower(str)--转换成小写字母

str4  =string.gsub(str,"S","i")--S转换为i

str5  =string.gsub(str,"S","i",2)--S转换为i,2为替换次数,默认为全部替换

str6  =string.find(str,"ing")--返回所查找到的位置的索引,可以设置起始搜索位置

str7 = string.reverse(str)--翻转字符串
str8 = string.format("加法运算:%02d+%02d=%02d",num1,num2,(num1+num2))--格式化输出
print(str8)

控制语句:

分支

if(a>=b) then --nil会被判断为false
	print("a")
else
	print("B")
end

循环

--for循环 变量,最大值,每次+1

for i=1,10,1 do

	print(i)

end

--for遍历 双返回 --pairs是迭代器
for k,v in pairs(tab2)do

	print(k,v)

end

--类似于do while

repeat
print(a)

a=a+1

until(a>11)--满足时退出循环

自定义迭代循环

--自定义迭代函数

--状态变量不会变化,控制变量会一直变化

function square(state,control)


	if(control>=state) then

		return nil
	else
		control = control+1
		return control,control*control
	end

end



for i,j in square,9,0 do
	print(i,j)
end

函数

function ceshi001()--可以返回多变量
	return 40,50
end

a,b = ceshi001()

print(a,b)


function ceshi002(...)--多参数传参函数

    local arg = {...}--三个点代表可变参数

    print(arg[1])

    print(#arg)--参数个数获取

end

ceshi002(1,2,3)


--匿名函数
fun(321,
    function (name)
        print(name.."hello")
    end
)

table表

在 Lua 里,table 的创建是通过"构造表达式"来完成,最简单构造表达式是{},用来创建一个空表。也可以在表里添加一些数据,直接初始化表

个人理解:表是个很强大的东西,可以是数组,可以是字典,可以是方法,可以是类。个人感觉更接近字典。

字典和数组

tab1 = {} -- 空表 {}构造表达式

tab2 = {key1 = 100 , key2="v2"  } --任意类型键值对

tab3={"a1","a2","a3","a4"}--无键值对时,键为数字 从1开始

array1 ={{},{},{}}--二维数组

tab3[1] = 1 --随意改变储存类型
tab3[2] = nil --删除元素 
tab3 = nil--删除整个表,相当于释放内存

表的操作

mytable = {"lua","C#","Java","C++","C"}

table.insert(mytable,"JavaScript")--末端插入数据

table.insert(mytable,2,"Boo")--指定位置插入

table.remove(mytable,2)--删除指定位置


print(table.concat(mytable))--拼接字符串
--指定符号拼接
print(table.concat(mytable,"|"))


table.sort(mytable)--这个排字符串会更具ascll码排序

元表

 Lua 提供了元表(Metatable),允许我们改变table的行为,每个行为关联了对应的元方法。

元方法

描述

__index

通过键来访问 table 的时候,如果这个键没有值,那么就会寻找该table的metatable(假定有metatable)中的__index 键。如果__index包含一个表格,Lua会在表格中查找相应的键。

1.在表中查找,如果找到,返回该元素,找不到则继续

2.判断该表是否有元表,如果没有元表,返回 nil,有元表则继续。

3.判断元表有没有 __index 方法,如果 __index 方法为 nil,则返回 nil;如果 __index 方法是一个表,则重复 1、2、3;如果 __index 方法是一个函数,则返回该函数的返回值。

__newindex

当给表的一个不存在的键赋值,解释器就会查找__newindex 元方法:

如果存在则调用这个函数而不进行赋值操作。

如果__newindex是个表,则会拿到这个表继续查找键进行赋值,重复上面操作。

设置元表

mytable = {}                          -- 普通表
mymetatable = {}                      -- 元表
setmetatable(mytable,mymetatable)     -- 把 mymetatable 设为 mytable 的元表

mytable = setmetatable({},{})--另一种写法
--设置__index,定义访问不存在的键时调用的委托事件
mymetatable = {
__index = function(tab,key)

	if(key>=10) then
		return "不存在的键"
	end
end
}
--设置__newindex,定义添加新键值对时调用的委托
mymetatable = {
__newindex = function(tab,key,value)
	print("要修改的key为:"..key..",把这个值修改为:"..value)
	rawset(tab,key,value)--设置一个键值对到表
end
}
--设置__add,可以定义表和表之间的+操作符运算
mymetatable = {
__add = function(tab,newtab)

	local m1 = 0

	for k,v in pairs(tab) do

			if(k>m1) then
				m1= k
			end
	end

	for k,v in pairs(newtab) do

		m1 = m1+1
		table.insert(tab,m1,v)

	end

	return tab
end
}
--设置__call属性,可以吧表当成函数使用
mymetatable = {
__call = function (tab,arg)
	print(arg)
	return "SDHK"
end
}
--设置__tostring,可以定义打印表的委托方法
mymetatable = {
__tostring = function(tab)

	local str = ""

	for k,v in pairs(tab) do
			str = str..v.."."
	end

	return str

end
}

运算符键

模式描述
__add对应的运算符 '+'.
__sub对应的运算符 '-'.
__mul对应的运算符 '*'.
__div对应的运算符 '/'.
__mod对应的运算符 '%'.
__unm对应的运算符 '-'.
__concat对应的运算符 '..'.
__eq对应的运算符 '=='.
__lt对应的运算符 '<'.
__le对应的运算符 '<='.

引入模块

--模块代码 :文件名"module.Lua"
module ={}

module.var = "siki"


module.func1 = function() --匿名函数赋值给变量
	print("这个是module里的函数")
end


local function func2()--局部函数相当于私有函数

	print("这个是module的局部函数")

end


function module.func3()--全局变量需要加上表名

	print("这个是module的全局函数")

end


return module
--引入lua模块
--require "模块文件名"

m = require "module" --返回的是表

print(module.var)--调用模块

m.func1()--调用表里方法

协同程序

Lua 协同程序(coroutine)与线程比较类似:拥有独立的堆栈,独立的局部变量,独立的指令指针,同时又与其它协同程序共享全局变量和其它大部分东西。

协同是非常强大的功能,但是用起来也很复杂。

基本语法

方法描述
coroutine.create()创建 coroutine,返回 coroutine, 参数是一个函数,当和 resume 配合使用的时候就唤醒函数调用
coroutine.resume()重启 coroutine,和 create 配合使用
coroutine.yield()挂起 coroutine,将 coroutine 设置为挂起状态,这个和 resume 配合使用能有很多有用的效果
coroutine.status()查看 coroutine 的状态
注:coroutine 的状态有三种:dead,suspended,running,具体什么时候有这样的状态请参考下面的程序
coroutine.wrap()创建 coroutine,返回一个函数,一旦你调用这个函数,就进入 coroutine,和 create 功能重复
coroutine.running()返回正在跑的 coroutine,一个 coroutine 就是一个线程,当使用running的时候,就是返回一个 corouting 的线程号
--定义协同函数
co =  coroutine.create(

	function (a,b)--匿名函数不需要写函数名

		print(a+b)

		print(coroutine.status(co))  --打印状态:running

        --挂起 coroutine,将 coroutine 设置为挂起状态,这个和 resume 配合使用能有很多有用的效果
		coroutine.yield(a*b)    

		print(coroutine.status(co))  --running
		print(a-b)

		return a*b+1
	end
)

--启动协同函数
coroutine.resume(co,20,30)
--定义协同函数的第二种方法:这种方法好像有使用限制
co1 = coroutine.wrap(

	function (a,b)--匿名函数不需要写函数名

		print(a+b)


		coroutine.yield(a*b)

		print(a-b)
		return a*b+2

	end
)

co1(20,30)--启动协同函数
res1,res2 = coroutine.resume(co)--再启动协同程序,不需要再次传递参数

print("携程启动成功:",res1,"返回值为",res2)

文件读写

Lua I/O 库用于读取和处理文件。分为简单模式(和C一样)、完全模式。

  • 简单模式(simple model)拥有一个当前输入文件和一个当前输出文件,并且提供针对这些文件相关的操作。
  • 完全模式(complete model) 使用外部的文件句柄来实现。它以一种面对对象的形式,将所有的文件操作定义为文件句柄的方法

简单模式在做一些简单的文件操作时较为合适。但是在进行一些高级的文件操作的时候,简单模式就显得力不从心。例如同时读取多个文件这样的操作,使用完全模式则较为合适。

模式描述
r以只读方式打开文件,该文件必须存在。
w打开只写文件,若文件存在则文件长度清为0,即该文件内容会消失。若文件不存在则建立该文件。
a以附加的方式打开只写文件。若文件不存在,则会建立该文件,如果文件存在,写入的数据会被加到文件尾,即文件原先的内容会被保留。(EOF符保留)
r+以可读写方式打开文件,该文件必须存在。
w+打开可读写文件,若文件存在则文件长度清为零,即该文件内容会消失。若文件不存在则建立该文件。
a+与a类似,但此文件可读可写
b二进制模式,如果文件是二进制文件,可以加上b
+号表示对文件既可以读也可以写
模式描述
"*n"读取一个数字并返回它。例:file.read("*n")
"*a"从当前位置读取整个文件。例:file.read("*a")
"*l"(默认)读取下一行,在文件尾 (EOF) 处返回 nil。例:file.read("*l")
number返回一个指定字符个数的字符串,或在 EOF 时返回 nil。例:file.read(5)
file = io.open("data1.txt","r")

-- 设置默认输入文件为 ata1.txt
io.input(file)

print( io.read())--读取一行
print( io.read())--读取下一行 默认*|

print( io.read("*a"))--读取剩下全部字符


io.close()-- 关闭打开的文件


--追加只写a
file = io.open("data1.txt","a")

io.output(file)


--io.write("SD_Y_HK\n")
io.close()

--完全模式
file = io.open("data1.txt","r")

print(file:read())


file:close()

面向对象

  •  封装:指能够把一个实体的信息、功能、响应都装入一个单独的对象中的特性。
  •  继承:继承的方法允许在不改动原程序的基础上对其进行扩充,这样使得原功能得以保存,而新功能也得以扩展。这有利于减少重复编码,提高软件的开发效率。
  • 多态:同一操作作用于不同的对象,可以有不同的解释,产生不同的执行结果。在运行时,可以通过指向基类的指针,来调用实现派生类中的方法。
  • 抽象:抽象(Abstraction)是简化复杂的现实问题的途径,它可以为具体问题找到最恰当的类定义,并且可以在最恰当的继承级别解释问题。

LUA中最基本的结构是table,所以需要用table来描述对象的属性。

lua 中的 function 可以用来表示方法。那么LUA中的类可以通过 table + function 模拟出来。

至于继承,可以通过 metetable 模拟出来

定义类

-- 元类 :把这个看为定义类
Rectangle = {area = 0, length = 0, breadth = 0}

-- 派生类的方法 new :定义类的New方法和构造函数
function Rectangle:new (o,length,breadth)
  o = o or {}            --假如o不为nil则返回自己,为nil则新建表

  setmetatable(o, self) --把自己设置为O的原表
  self.__index = self   --不存在返回,自己(将自己复制了一份)

  self.length = length or 0    --初始化数值
  self.breadth = breadth or 0
  self.area = length*breadth;

  return o               --将新表返回出去
end

-- 派生类的方法 printArea    :定义类的功能方法
function Rectangle:printArea ()
  print("矩形面积为 ",self.area)
end
RT = Rectangle:new(nil,10,20)--新建对象

print(r.length)--属性访问

r:printArea()--函数访问

继承类

-- 基类
Shape = {area = 0}
-- 基础类方法 new
function Shape:new (o,side)
  o = o or {}

  setmetatable(o, self)   --将自己设置为O的元表
  self.__index = self    --将自己复制一份

  side = side or 0
  self.area = side*side;
  return o
end
-- 基础类方法 printArea
function Shape:printArea ()
  print("面积为 ",self.area)
end
Square = Shape:new() --新建复制父类

function Square:new (o,side) --子类的new方法

  o = o or Shape:new(o,side) --假如o为nil则复制一个父类为新类

  setmetatable(o, self) --将自己设置为新类的元表
  self.__index = self    --通过不存在事件,将自己复制一份

  return o    --新建好的子类
end
-- 派生类方法 printArea 重写函数
function Square:printArea ()
  print("正方形面积 ",self.area)
end

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值