Lua 语言学习
详细讲解见菜鸟教程 Lua。
一、数据类型
1 -- 直接输出 2 print("hello") 3 4 5 -- 全局变量 6 b = 11 7 print(b) 8 9 10 11 -- nil(空) 12 print(type(a)) 13 -- 对于全局变量和table,nil 还有清空的作用 14 15 16 -- number(数字) 17 -- Lua 默认只有一种number类型 -- double(双精度) 18 19 20 -- string(字符串) 21 -- 字符串由一对双引号或单引号来表示 22 string1 = "this is string1" 23 string2 = 'this is string2' 24 -- 在尝试对一个数字字符串进行算术操作时,Lua会尝试将数字字符串转换成数字 25 print("16" + 6) 26 -- 字符串连接 .. 27 print(16 .. 6) 28 -- 字符串长度 # 29 print(#string1) 30 31 32 -- table(表) 33 a = {} 34 -- 数组的索引可以为数字或者字符串 35 a["key"] = "value" 36 key = 10 37 a[key] = 22 38 -- 遍历 39 for k,v in pairs(a) do 40 print(k .. ":" .. v) 41 end 42 -- Lua里表的初始索引一般以 1 开始,而不是 0 43 -- table 长度不固定,会自动增加 44 45 -- function(函数) 46 -- 函数名字f,包含一个参数 n 47 -- 主要实现阶乘的计算 48 function f(n) 49 if n==0 then 50 return 1 51 else 52 return n * f(n-1) 53 end 54 end 55 -- 调用函数 56 print(f(5)) 57 -- 函数可以存储在一个变量中 58 f1 = f 59 print(f1(5)) 60 61 -- 匿名函数参数传递 62 -- 函数名 f1,有两个参数,其中第二个参数为一个函数 63 function f1(tab, f2) 64 for k, v in pairs(tab) do 65 -- 输出函数返回的值 66 print(f2(k, v)) 67 end 68 end 69 70 -- 新建表 71 tab = {"a", "b", "c"} 72 -- 调用函数,匿名函数作为参数传入 73 -- 注意key是从1开始的 74 f1(tab, 75 function(key, val) -- 匿名函数 76 return key .. " = " .. val 77 end 78 ) 79 80 81 -- 变量 82 a = 5 -- 全局变量 83 local b = 10 -- 局部变量 84 -- Lua可以对多个变量同时赋值 85 x,y = 11,12 86 print(x .. "," .. y) 87 -- 交换x,y的值 88 x,y = y,x 89 print(x .. "," .. y) 90 -- 多值赋值也可用来接收函数返回的多个变量 91 function f() 92 return 11, 12 93 end 94 x,y = f() 95 print(x .. "," .. y)
二、循环
1 -- while 语句 2 a = 10 3 -- 从10输出到20 4 while(a < 20) 5 do 6 print("a = " .. a) 7 a = a + 1 8 end 9 10 11 -- for 语句 12 -- 数值for循环 13 -- 从10变化到1,每次步长为-1 14 for i=10, 1, -1 do 15 print("i = " .. i) 16 end 17 -- 泛型for循环 18 days = {"Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"} 19 -- i为数组索引值,v是对应索引的数组元素值,ipairs为迭代器 20 for i,v in ipairs(days) do 21 print(v) 22 end 23 24 25 -- repeat...until 语句 26 -- 循环直到a>15 27 a = 10 28 repeat 29 print(a) 30 a = a + 1 31 until(a > 15) 32 33 34 -- break 语句 35 for a = 10,1,-1 do 36 print(a) 37 if(a < 5) 38 then 39 break -- 当a<5,跳出循环 40 end 41 end
三、流程控制
1 -- if...elseif..else 语句 2 a = 100 3 if(a == 10) 4 then -- a=10 5 print("a 的值为 10") 6 elseif(a == 20) 7 then -- a=20 8 print("a 的值为 20") 9 else -- 没有匹配。注意不需要then 10 print("没有匹配的值") 11 end 12 13 14 -- if嵌套语句 15 a = 100 16 b = 200 17 if(a == 100) 18 then -- a=100 19 if(b == 200) 20 then -- a=100且b=200 21 print("a = " .. a .. " b = " .. b) 22 end 23 end
四、函数
1 -- 多返回值 2 -- 寻找最大值和最大值所在的位置 3 function maximum(a) 4 local mi = 1 -- 最大值位置 5 local m = a[mi] -- 最大值 6 for k,v in ipairs(a) do 7 if(v > m) then -- 更大 8 m = v 9 mi = k 10 end 11 end 12 return m, mi -- 输出最大值及其索引 13 end 14 15 -- 输出最大值及其索引 16 print(maximum({8, 10, 13, 6, 15, 9})) 17 18 -- 可变参数 19 -- 求不确定参数个数的平均值 20 function averge(...) 21 result = 0 22 -- 可变参数可以赋值给变量 23 local arg = {...} 24 for k,v in ipairs(arg) do 25 result = result + v 26 end 27 -- #可以获取...长度 28 print("总共传入 " .. #arg .. " 个数") 29 -- 返回平均值 30 return result/#arg 31 end 32 33 -- 输出平均值 34 print("平均值为 " .. averge(10, 5, 3, 4, 5, 6))
五、运算符
1 -- 算术运算符 2 -- + - * / 加减乘除 3 -- % 取余 ^ 乘幂 - 负号 4 5 6 -- 关系运算符 7 -- == 等于 ~= 不等于 8 -- > < >= <= 大于 小于 大于等于 小于等于 9 10 11 -- 逻辑运算符 12 -- and 逻辑与 or 逻辑或 not 非 13 14 15 -- 其他运算符 16 -- .. 连接两个字符串 17 -- # 返回字符串或表的长度
六、字符串
1 -- 字符串大小写转换 2 s = "Lua" 3 print(string.upper(s)) -- 大写 4 print(string.lower(s)) -- 小写 5 6 7 -- 字符串查找与反转 8 s = "Lua Tutorial" 9 -- 查找字符串,若查找成功,返回头和尾,否则返回nil 10 print(string.find(s, "Tutorial")) 11 -- 字符串反转 12 reverses = string.reverse(s) 13 print(reverses) 14 15 16 -- 字符串格式化 17 date = 2 18 month = 1 19 year = 2014 20 -- 日期格式化 21 print(string.format("%02d/%02d/%04d", date, month, year)) 22 -- 十进制格式化 23 print(string.format("%.3f", 1/3)) 24 25 26 -- 字符与ASCII码的转换 27 -- 转换第一个字符 28 print(string.byte("Lua")) 29 -- 转换第三个字符 30 print(string.byte("Lua", 3)) 31 -- 转换倒数第一个字符 32 print(string.byte("Lua", -1)) 33 -- ASCII转字符 34 print(string.char(97)) 35 36 37 -- 字符串长度 38 s = "Lua Tutorial" 39 print(string.len(s)) 40 41 42 -- 模式匹配 43 -- 搜索 dd/mm/yy 格式的日期 44 s = "Deadline is 30/05/1999, firm" 45 date = "%d%d/%d%d/%d%d%d%d" 46 print(string.sub(s, string.find(s, date))) 47 -- 去除空格 48 -- gsub 返回的第二个参数为替代字符的个数 49 print(string.gsub(s, " ", ""))
七、数组
1 -- 一维数组 2 array = {} 3 -- 初始化数组 4 -- 注意数组下标默认从1开始,但是也可以自定义下标 5 for i=-2, 2 do 6 array[i] = i*2 7 end 8 -- 遍历数组 9 for i=-2, 2 do 10 print(array[i]) 11 end 12 13 -- 二维数组 14 array = {} 15 maxRow = 3 16 maxColumn = 3 17 -- 初始化3行3列数组 18 for row=1,maxRow do 19 array[row] = {} 20 for col=1,maxColumn do 21 array[row][col] = row * col 22 end 23 end 24 -- 遍历数组 25 for row=1,maxRow do 26 for col=1,maxColumn do 27 print(array[row][col]) 28 end 29 end
八、迭代器
1 -- pairs和ipairs区别 2 -- pairs 可以遍历集合的所有元素,即可以遍历集合中的所有key 3 -- ipairs 按照索引升序遍历,索引中断停止遍历 4 tab = { 5 [1] = "a", 6 [2] = "b", 7 [4] = "c" -- 注意索引值没有3 8 } 9 10 -- pairs 11 -- 输出 a,b,c 12 for k, v in pairs(tab) do 13 print(v) 14 end 15 16 -- ipairs 17 -- 只输出 a,b 18 for k, v in ipairs(tab) do 19 print(v) 20 end
九、表(table)
1 -- 初始化表 2 mytable = {} 3 -- 指定值 4 mytable[1] = "Lua" 5 -- 移除引用 6 -- 之后Lua垃圾回收会释放内存 7 mytable = nil 8 9 10 -- table 连接 11 fruits = {"banana","orange","apple"} 12 -- 直接连接 13 print(table.concat(fruits)) 14 -- 指定连接字符 15 print(table.concat(fruits, ",")) 16 -- 指定要连接的字符串 17 print(table.concat(fruits, ", ", 2, 3)) 18 19 20 -- 插入和删除 21 fruits = {"banana","orange","apple"} 22 -- 在末尾插入 23 table.insert(fruits, "watermelon") 24 print(table.getn(fruits)) 25 -- 在指定位置插入 26 table.insert(fruits, 2, "pear") 27 print(fruits[2]) 28 print(table.getn(fruits)) 29 -- 删除指定位置的元素 30 print(table.remove(fruits, 4)) 31 print(table.getn(fruits)) 32 33 34 -- 排序 35 fruits = {"banana","orange","apple","grapes"} 36 print("排序前") 37 for k,v in ipairs(fruits) do 38 print(k,v) 39 end 40 41 -- 排序,默认为升序 42 table.sort(fruits) 43 print("排序后") 44 for k,v in ipairs(fruits) do 45 print(k,v) 46 end 47 48 49 -- 注意使用 # 和 table.getn 其都会在索引中断的地方停止计数, 50 -- 而导致无法正确取得 table 的长度 51 -- 可以用以下的方法 52 function table_leng(t) 53 local leng=0 54 for k, v in pairs(t) do 55 leng=leng+1 56 end 57 return leng 58 end
十、模块
模块代码如下:
1 -- module.lua 2 -- 定义一个名为 module 的模块 3 module = {} 4 5 -- 定义一个常量 6 module.constant = "这是一个常量" 7 8 -- 定义一个函数 9 function module.func1() 10 io.write("这是一个公有函数!\n") 11 end 12 13 local function func2() 14 print("这是一个私有函数!") 15 end 16 17 function module.func3() 18 func2() 19 end 20 21 return module
调用模块代码如下:
1 -- 加载模块 2 -- 返回一个由模块常量和函数组成的table 3 local m = require("module") 4 5 print(m.constant) -- 访问模块常量 6 m.func3() -- 访问模块函数
十一、协同程序
1 -- 协同程序 2 -- 创建协程,resume时唤醒函数 3 co = coroutine.create( 4 function(i) 5 print(i); 6 end 7 ) 8 9 -- 重启协程,并传入参数 10 coroutine.resume(co, 1) -- 1 11 -- 输出协程状态 12 print(coroutine.status(co)) -- dead 13 14 print("----------") 15 16 -- 作用与create一样 17 co = coroutine.wrap( 18 function(i) 19 print(i); 20 end 21 ) 22 23 co(1) 24 25 print("----------") 26 27 -- create时就是在新线程中注册一个事件 28 co2 = coroutine.create( 29 function() 30 for i=1,10 do 31 print(i) 32 if i == 3 then 33 print(coroutine.status(co2)) --running 34 print(coroutine.running()) --thread:XXXXXX 35 end 36 -- 遇到yield协程会暂时挂起 37 coroutine.yield() 38 end 39 end 40 ) 41 42 -- resume会重新激活事件 43 coroutine.resume(co2) --1 44 coroutine.resume(co2) --2 45 coroutine.resume(co2) --3 46 47 print(coroutine.status(co2)) -- suspended 48 print(coroutine.running()) 49 50 print("----------")
十二、文件 I/O
1 -- 文件 I/O 2 -- 打开文件 3 file = io.open("协同程序.lua", "r") 4 5 -- 输出文件第一行 6 print(file:read()) 7 8 -- 获取倒数第10个字符位置 9 file:seek("end",-10) 10 -- 读取后10个字符 11 print(file:read("*a")) 12 13 -- 关闭文件 14 file:close() 15 16 -- 以附加的方式打开只写文件 17 file = io.open("协同程序.lua", "a") 18 19 -- 在文件末尾写入字符串 20 file:write("-- test io")
十三、面向对象
1 -- 面向对象 2 -- Shape 类,包含一个属性 area 3 Shape = {area = 0} 4 5 -- 构造方法 6 function Shape:new (o, side) 7 o = o or {} 8 setmetatable(o, self) 9 self.__index = self 10 side = side or 0 11 self.area = side*side 12 return o 13 end 14 15 -- 输出形状面积 16 function Shape:printArea() 17 print("面积为:", self.area) 18 end 19 20 -- 创建对象 21 myShape = Shape:new(nil, 10) 22 -- 输出面积 23 myShape:printArea() -- 100 24 25 26 -- 继承 27 -- 长方形 28 Rectangle = Shape:new() 29 -- 派生类构造方法 30 function Rectangle : new(o, length, breadth) 31 o = o or Shape:new(o) 32 setmetatable(o, self) 33 self.__index = self 34 self.area = length * breadth 35 return o 36 end 37 38 -- 函数重写 39 function Rectangle : printArea() 40 print("长方形面积为:", self.area) 41 end 42 43 -- 创建一个长方形对象 44 myRectangle = Rectangle:new(nil, 10, 20) 45 -- 输出长方形面积 46 myRectangle:printArea() -- 200