• 设为首页
  • 点击收藏
  • 手机版
    手机扫一扫访问
    迪恩网络手机版
  • 关注官方公众号
    微信扫一扫关注
    公众号

第52天-lua语言基础语法

原作者: [db:作者] 来自: [db:来源] 收藏 邀请

注意:在保存lua文件时,必须是<文件名.lua>的形式,必须加.lua后缀名

执行脚本:Ctrl + B

清空执行结果区:全选 + 删除

Lua语句

Lua语言是区分大小写的

Lua语句不需要使用分号结尾, 但是即使写了分号也不保错

Lua注释

单行注释:-- (sublime快捷键:ctrl+/)

多行注释: --[[ 语句 ]] (sublime快捷键:ctrl+shift+/)、--[[ 语句 ]]--、--[[ 语句 --]]

--单行注释
--print("11111111111")

--多行注释
--[[
print("22222222222")

print("33333333333333")
]]

--[[
print("22222222222")

print("33333333333333")
]]--

--[[
print("22222222222")

print("33333333333333")
--]]
多行注释推荐使用 --[=[注释内容]=]
print("44444444444444444")

Lua变量定义

变量名 = 初始值

无需指定数据类型, 会根据赋值的值自动改变变量的数据类型

-- C#  数据类型  变量名 = 初始值
c1 = [[abcdefg]]
print(c1, type(c1))

变量名(标识符)规范

1、以字母或下划线开头

2、后面可以有数字、字母、下划线组成

3、尽量避免 下划线+大写字母 开头的写法,lua自身保留格式

查看变量类型

type(变量名)

num = 10.1
print(num, type(num))

Lua数据类型

number数字类型

lua不区分整数与小数, 数都是number类型

num = 10.1
print(num, type(num))
num2 = 10
print(num2, type(num2))

nil空数据

等同于null

nil可以使用在条件判断中,表示false结果

boolean布尔类型

ture 或者 false

lua认为只有false和nil是假的(不满足条件), 其他都是真的(满足条件)

string字符串类型

Lua没有字符类型, 双引号与单引号都表示字符串类型

"字符内容":不可以换行编辑

'字符串内容':不可以换行编辑

[[字符串内容]]:可以换行编辑,容易与多行注释冲突

字符串的基本操作

数学运算符 +、-、*、/、%

当两个字符串进行数学运算符运算时,会将两个字符串转换成数值进行计算,如果转换失败就报错

str1 = "5"
str2 = "7"

print("--------------------------字符的数学运算------------------------------")
str3 = str1 + str2
str4 = str1 - str2
str5 = str1 * str2
str6 = str1 / str2
str7 = str1 % str2

print(str3)
print(str4)
print(str5)
print(str6)
print(str7)

字符串的连接

使用“..” 两个点进行拼接

print("-----------------------------字符串的连接-----------------------------")
str8 = str1 .. str2
print(str8)

字符串的长度

#变量名

print("----------------------字符串的长度------------------------")

str9 = "12345asgfasfd"
length = #str9
print(length)

str10 = [[12345a
sgfasfd]]
length = #str10
print(length)

Lua运算符

算术运算符

+, -, *, /, %

print(1 + 2)
print(4 % 2)

^:幂次方

2 ^ 3表示2的3次方

print(2 ^ 3)

关系运算符

<,>,<=,>=,==,

print(1 > 2)

~=:不等判断,与C#不一样

print(1 ~= 2)

逻辑运算符

and:与

同时为真才为真,相当于C# &&

print(true and true)
print(false and true)

or:或

只要有一个为真就为真,相当于C# ||

print(false or true)

not:非

取反,相当于C# !

print(not true)

流程控制语句

if 条件 then  语句  end

--num为nil, lua认为nil为false
if not num then
    print("num为nil")
end

year = 2004
--1 能被4整除,不能被100整除
--2 能被400整除
if (year % 4 == 0 and year % 100 ~= 0) or year % 400 == 0 then
    print("year: "..year.." 是闰年")
end

if 条件 then  语句1 else 语句2 end

-- if  else

age = 19
if age > 18 then
    print("你已经成年了")
else
    print("你未成年")
end

if 条件1 then 语句1  elseif 条件2 then  语句2  else 语句3 end

-- if  else if  else 
--判断字符串是否是A或B ,如果是A打印 A1,如果是B打印B2, 如果都不是,打印C3
str = "9"
if str == "A" then
    print("A1")

--elseif是放在一起写的,中间没有空格, 只要是条件判断,条件后要加then关键字
elseif str == "B" then
    print("B2")
else
    print("C3")
end

循环语句

while

--[[
C# : 
while(循环条件)
{
    循环体
}
]]

--[[
Lua:
while 循环条件 do
    循环体
end
]]
num = 37
--判断num是否是质数,  只能被1和本身整除的数就是质数
print("判断num是否是质数,  只能被1和本身整除的数就是质数")
isPrime = true
i = 2
while i < num do
    if num % i == 0 then
        isPrime = false
        --可以跳出
        break
    end
    i = i + 1
end
if isPrime then
    print("num: "..num .."是质数")
else
    print("num: "..num .. "不是质数")
end


--打印100到999之间的水仙花数
--153 = 1*1*1 + 5*5*5 + 3*3*3
print("打印100到999之间的水仙花数")
num = 100
while num < 1000 do
    --取个位,十位,百位
    one = num % 10;
    tow = (num - one) / 10 % 10
    -- (153 - 3 - 5 * 10) / 100
    three = (num - one - tow * 10) / 100
    if one^3 + tow^3 + three^3 == num then
        print(num)
    end
    num = num + 1
end

repeat

--[[
C#:
do
{
    循环体
}while(循环条件)
满足条件循环
]]

--[[
lua:
repeat
    循环体
until 跳出循环条件
满足条件退出循环
]]


num = 10
repeat
    print(num)
    num = num - 1
    --注意条件是跳出循环的条件
until num >= 1

for

 

--[[
C#
for(int 变量 = 初始值; 循环条件; 增量表达式)
{
    循环体
}
]]

--[[
Lua

for 变量 = 初始值, 阈值, 增量值 do

    循环体

end 
变量超过阈值,结束循环, 
每次循环变量都增加增量值
增量值可以省略,如果省略那么默认是1

]]

--打印2到100之间的质数,包含2和100
for num = 2,100 do

    isPrime = true
    for i = 2, num-1 do
        if num % i == 0 then
            isPrime = false
        end
    end
    if isPrime then
        print(num)
    end
end


--打印2000年到2050年之间的所有闰年
for year = 2000, 2050 do
    if (year % 4 == 0 and year % 100 ~= 0) or year % 400 == 0 then
        print(year)
    end
end

注意:lua的循环语言可以使用break跳出,但是没有continue

Lua中的数组

lua  中没有数组的,是使用表table结构来模拟数组, 长度不是固定的

lua数组的默认索引是从1开始的,不是从0,遇到非连续的索引后就停

--[[
C#
数据类型[] 数组名 = new 数据类型[数组的长度]
]]

--[[
lua  中没有数组的,是使用表table结构来模拟数组, 长度不是固定的

数据名 = {}
]]

array1 = {}
--可以初始化赋值
array2 = {"123", "456"}

--打印第1个数组元素
print(array2[1])

--数组的长度
print(#array2)

--遍历数组
for i = 1, #array2 do
    print(array2[i])
end

--对第5个索引赋值为“789”
array2[5] = "789"

--数组的长度
print("数组长度: "..#array2)

--这种写法在语法上没有错误,但是主管不认为是数组
array3 = {[-1] = "45678", [0] = "123", [1] = "456"}
print(array3[-1])
print(array3[0])

--数组的长度
print("数组长度: "..#array3)


--将10 - 1 依次存储到一个数组中

arr = {}

index = 1
for num = 10, 1, -1 do
    arr[index] = num
    index = index + 1
end

for i = 1, #arr do
    print(arr[i])
end

函数

先定义,再执行

-- 函数的定义
--[[
function 函数名(参数列表)
    
end
]]

--[[
函数名 = function(参数列表)
    
end
]]


function Func1()
    print("执行Func1的方法")
    --该位置调用,只要保证Func1调用时在Func2定义之后就可以
    Func2()
end

--调用会报错, 因为Func2在该行执行时未定义
--Func2()

Func2 = function()
    print("Func2")
end

Func1()

--带有参数与返回值的,注意参数列表无需指定类型
function Func3(a, b)
    sum = a + b
    return sum
end

sum = Func3(10, 20)
print(sum)


--多个返回值
function Func4()
    return 1, "str", true, {"abc", "def"}
end

--接收多个返回值的函数,要使用多个变量接收
one, tow, three, four = Func4()
print(one)
print(tow)
print(three)
print(four[1])


--lua函数还支持可变参数  ...
function Func5(...)
    --通过数组获取可变参数
    --[[
    args = {...}
    for i = 1, #args do
        print(args[i])
    end
    ]]

    --第二种获取可变参数的方式, arg是lua方法中默认的可变参数组
    for i = 1, #arg do
        print(arg[i])
    end

    print("Func5")
end

Func5(1,"334", true, {"abc", "def"})

表(table)

lua中的table是一个关联数组, 索引可以是数字也可以是字符串

--定义
tab1 = {}
tab2 = {[1] = "123", ["Key"] = 34, Name = "小明"}

--赋值访问
print(tab2[1])
tab2["Name"] = "小李"
tab2.Name = "小红"
--访问字符串索引的元素
print(tab2["Name"])
print(tab2.Name)
print(tab2["Key"])
print(tab2.Key)

-- 释放
tab2 = nil

print("----------------------------------------------------------")
--表中存储方法
tab3 = 
    { 
         Func1 = function(a)
            print("Func1: " .. type(a))
            print(a)
         end 
    }

tab3.Func2 = function(a)
    print("Func2: " .. type(a))
end

--调用表中的方法
--当使用:调用表中初始化时方法或通过表.方法名定义的方法时, 会将表作为第一个参数传递到方法中
--当使用 . 调用表中初始化时方法或通过表.方法名定义的方法时, 不会将表传入
tab3:Func1()
print(tab3)
tab3:Func2()

print("=======================================================")
function tab3:Func3(a)
    print("Func3: " .. type(a))
    print("self: " .. type(self))
end

--当调用使用 表:方法名 定义的方法时
-- 表.方法()调用, 表示不传入当前表
-- 表:方法()调用, 表示传入当前表, 不占参数位置,通过self可以获取表
tab3:Func3()

模块化开发

require 函数

require("<模块名>")

TestModel引用其他文件

--执行Model.lua的文件
local m = require("Model")
print("-----------------------------------------------------------------")

print(m.Name)
print(m.Age)
m:Show()

print("-----------------------------------------------------------------")
--执行Model1.lua的文件, 注意Model1在当前文件文件夹的子文件夹Lesson下
require("Lesson/Model1") -- Lesson/Model1 表示相对路径,相对于当前文件所在文件夹的路径

--执行文件都有一个加载路径, 加载路径都存储在table表 package.path中
--路径与路径间使用分号分隔,后缀是.lua,通过?来匹配文件名
print(type(package.path))

--执行Model3.lua的文件, 注意Model3在D盘的TestLua文件夹下
--需要将桌面路径添加到 package.path 中,文件路径以 ";" 号分隔,最后的 2 个 ";;" 表示新加的路径后面加上原来的默认路径。
package.path = package.path .. ";D:/TestLua/?.lua"

require("Model3")

print("========================================================================")
tab = {"123", "234", "456", "567"}

local Json = require("JsonUtility")
--将表解析成Json串
str = Json.encode(tab)
print(str)

Model

print("Start Model ......")

local Model = {}

Model.Name = "小明"

Model.Age = 18

function Model:Show()
    print("我叫:" .. self.Name .. ", 我的年龄: " .. self.Age .. "")
end

return Model

 

元表

算术类

+:__add

--元表, 针对table的, 元表是改变表与表间的运算或操作的规则的

t1 = {key = "123", age = 18}
t2 = {name = "456", [-1] = "abc", [1] = "ghj", [2] = "fhgdsh", [4] = "asdfasdf"}

add = 
{
    --合并两个表为一个新的表
    __add = function (tab1, tab2)
        local tab = {}
        --遍历tab1
        for k,v in pairs(tab1) do
            tab[k] = v
        end
        --遍历tab2
        for k,v in pairs(tab2) do
            tab[k] = v
        end
        return tab
    end

}

--设置meta表为t1表的元表
--setmetatable(t1, meta)
setmetatable(t1, add)

--当两个表向加运算时,先判断两个表是否有元表,如果都没有元表,直接报错
--如果其中一个有元表,再判断元表中是否有 __add 的元方法,如果没有,直接报错
--如果有元表并且有__add元方法, 那么执行__add的元方法, 该方法的返回值就是两个表相加的结果
--执行__add元方法时,将 + 号左边的表作为第一个参数传入, 将+号右边的表作为第二个参数传入
t3 = t1 + t2

--print("t1", t1)
--print("t2", t2)

print(t3)

for k,v in pairs(t3) do
    print(k,v)
end

-:__sub

*:__mul

/:__div

比较类

等于:__eq

设置元表

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

__index 元方法

这是 metatable 最常用的键。

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

> other = { foo = 3 }
> t = setmetatable({}, { __index = other })
> t.foo
3
> t.bar
nil

如果__index包含一个函数的话,Lua就会调用那个函数,table和键会作为参数传递给函数。

__index 元方法查看表中元素是否存在,如果不存在,返回结果为 nil;如果存在则由 __index 返回结果。

mytable = setmetatable({key1 = "value1"}, {
  __index = function(mytable, key)
    if key == "key2" then
      return "metatablevalue"
    else
      return nil
    end
  end
})

print(mytable.key1,mytable.key2)

实例输出结果为:

value1    metatablevalue

__newindex 元方法

__newindex 元方法用来对表更新,__index则用来对表访问 。

当你给表的一个缺少的索引赋值,解释器就会查找__newindex 元方法:如果存在则调用这个函数而不进行赋值操作。

mymetatable = {}
mytable = setmetatable({key1 = "value1"}, { __newindex = mymetatable })

print(mytable.key1)

mytable.newkey = "新值2"
print(mytable.newkey,mymetatable.newkey)

mytable.key1 = "新值1"
print(mytable.key1,mymetatable.key1)

输出结果为:

value1
nil    新值2
新值1    nil

以上实例中表设置了元方法 __newindex,在对新索引键(newkey)赋值时(mytable.newkey = "新值2"),会调用元方法,而不进行赋值。而如果对已存在的索引键(key1),则会进行赋值,而不调用元方法 __newindex。


鲜花

握手

雷人

路过

鸡蛋
该文章已有0人参与评论

请发表评论

全部评论

专题导读
上一篇:
Lua增加一个节点到文件中发布时间:2022-07-22
下一篇:
LUA中的TABLE函数库发布时间:2022-07-22
热门推荐
热门话题
阅读排行榜

扫描微信二维码

查看手机版网站

随时了解更新最新资讯

139-2527-9053

在线客服(服务时间 9:00~18:00)

在线QQ客服
地址:深圳市南山区西丽大学城创智工业园
电邮:jeky_zhao#qq.com
移动电话:139-2527-9053

Powered by 互联科技 X3.4© 2001-2213 极客世界.|Sitemap