Lua基础语法整理+演示代码

Lua基础语法整理+演示代码

参考自: 菜鸟教程Lua

目录

  • Lua基础语法整理+演示代码
    • 基本数据类型
      • nil
      • boolean
      • number
      • string
      • table
      • function
      • thread
      • userdata
    • Lua 变量
    • Lua 循环
    • Lua 流程控制
    • Lua 函数
    • Lua 运算符
      • 算数运算符
      • 关系运算符
      • 逻辑运算符
      • # 运算符
    • Lua 字符串
      • 字符串定义
      • 转义字符
      • 字符串操作
    • Lua 数组
      • 一维数组
      • 多维数组
    • Lua 迭代器
      • 状态迭代器
    • Lua 表格
      • 表格的连接
      • 表格的插入
      • 表格的删除
      • 表格的排序
      • 表格的最大值
    • Lua 模块
      • 模块的定义
      • 模块的使用
    • Lua 元表
      • 元表的设置与获取
      • __index 元方法
      • __newindex 元方法
      • 为表添加操作符
      • call 元方法 & tostring 元方法
    • Lua 文件 I/O
      • 简单模式
      • 完全模式
      • 其他方法
    • Lua 错误处理
    • Lua 垃圾回收
    • Lua 面向对象

基本数据类型

nil

  • nil 类型表示一种没有任何有效值,它只有一个值 – nil,例如打印一个没有赋值的变量,便会输出一个 nil 值
  • 对于全局变量和 table,nil 还有一个"删除"作用,给全局变量或者 table 表里的变量赋一个 nil 值,等同于把它们删掉
tab1 = {key1 = "value1", key2 = "value2"}
print(tab1.key1)
tab1.key1 = nil -- value1
print(tab1.key1) -- nil
  • nil 作比较时应该加上双引号 "
  • 因为 type(X) 实质是返回的 “nil” 字符串,是一个 string 类型
type(X) == "nil" -- true
type(X) == nil -- false

boolean

  • boolean 类型只有两个可选值:true(真) 和 false(假)

  • Lua 把 false 和 nil 看作是 false,其他的都为 true,数字 0 也是 true

print(type(true)) --boolean
print(type(false)) --boolean
print(type(nil)) --nil

if false or nil then
    print("至少有一个是 true")
else
    print("false 和 nil 都为 false") -- 结果
end

if 0 then
    print("数字 0 是 true") -- 结果
else
    print("数字 0 为 false")
end

number

  • Lua 默认只有一种 number 类型 – double(双精度)类型(默认类型可以修改 luaconf.h 里的定义)
  • 以下几种写法都被看作是 number 类型
print(type(2)) --number
print(type(2.2)) --number
print(type(0.2)) --number
print(type(2e+1)) --number
print(type(0.2e-1)) --number
print(type(7.8263692594256e-06)) --number

string

  • 字符串由一对双引号或单引号来表示
  • 也可以用 2 个方括号 “[[]]” 来表示"一块"字符串
string1 = "this is string1"
string2 = 'this is string2'
string3 = [[



    菜鸟教程


]]
  • 在对一个数字字符串上进行算术操作时,Lua 会尝试将这个数字字符串转成一个数字
print("2" + 6) --8
print("2" + "6") --8
print("2 + 6") -- 2 + 6
print("-2e2" * "6") -- -1200
print("error" + 1) -- error: attempt to perform arithmetic on a string value
  • 字符串连接使用的是 …
  • 使用 # 来计算字符串的长度,放在字符串前面
print("a" .. 'b') --ab
print(157 .. 428) --157428

len = "www.runoob.com"
print(#len) --14
print(#"www.runoob.com") --14
print(#"你好") --4 一个汉字两个字节

table

  • 在 Lua 里,table 的创建是通过"构造表达式"来完成,最简单构造表达式是{},用来创建一个空表
  • 在表里添加一些数据,直接初始化表,该表的键从1自增,做数组使用
  • 当表中添加字符串数据作为键时,作为字典使用
  • 在 Lua 里表的默认初始索引一般以 1 开始
-- 创建一个空的 table
tab1 = {}
-- 数组,索引自增数字
tab2 = {"apple", "pear", "orange", "grape"}
print(tab2[1]) -- apple
-- 字典,索引字符串
tab3 = {key1 = 100, key2 = "value2"}
print(tab3.key1) -- 100
print(tab3["key1"]) --100
-- 遍历
for key,val in pairs(tab3) do
     print(key .. " : " .. val)
end
-- key1 : 100
-- key2 : value2
for key,val in pairs(tab2) do
     print(key .. " : " .. val)
end
-- 1 : apple
-- 2 : pear
-- 3 : orange
-- 4 : grape
  • table 不会固定长度大小,有新数据添加时 table 长度会自动增长,没初始的 table 都是 nil
  • table 不要求索引的连续,索引和值可以为数字,字符串,nil 等
  • 删除元素直接将其置为 nil,后面的元素不会填充空值,该位置的值将持续为 nil
-- 接上文
-- table 值的修改与添加
tab2[2] = nil
tab2["key"] = "value"
tab2[100] = "芒果"
tab2.key = "new value"
for key,val in pairs(tab2) do
     print(key .. " : " .. val)
end
--[[
1 : apple
2 : pear
3 : orange
4 : grape
1 : apple
3 : orange
4 : grape
key : new value
100 : 芒果 --]]

function

  • 在 Lua 中,函数是被看作是"第一类值(First-Class Value)",函数可以存在变量里
-- 定义阶乘函数
function fact(n)
	if n == 1 then
		return n
	else
		return n*fact(n-1)
	end
end

print(fact(5))
print(type(fact))

-- 直接赋值function变量
fact2 = fact
print(fact2(5))

-- 传递function 变量
function testFun(tab,fun)
	for  k,v in pairs(tab) do
		fun(k,v)
	end
end

tab = {key1 = "val1", key2 = "val2"}
function f1(k,v)
	print(k..":"..v)
end
function f2(k,v)
	print(k.." "..v)
end

testFun(tab,f1)
testFun(tab,f2)
  • function 可以以匿名函数(anonymous function)的方式通过参数传递
-- 匿名函数
testFun(tab,
function(k,v)
	print(k.."-"..v)
end
)

thread

  • 在 Lua 里,最主要的线程是协同程序(coroutine)。它跟线程(thread)差不多,拥有自己独立的栈、局部变量和指令指针,可以跟其他协同程序共享全局变量和其他大部分东西

  • 线程跟协程的区别:线程可以同时多个运行,而协程任意时刻只能运行一个,并且处于运行状态的协程只有被挂起(suspend)时才会暂停

userdata

  • userdata 是一种用户自定义数据,用于表示一种由应用程序或 C/C++ 语言库所创建的类型,可以将任意 C/C++ 的任意数据类型的数据(通常是 struct 和 指针)存储到 Lua 变量中调用

Lua 变量

  • Lua 变量有三种类型:全局变量、局部变量、表中的域
  • Lua 中的变量全是全局变量,那怕是语句块或是函数里,除非用 local 显式声明为局部变量
  • 局部变量的作用域为从声明位置开始到所在语句块结束
  • 变量的默认值均为 nil
a = 5 -- 全局变量
a = "Hello"
local b = 20

-- 局部变量的销毁是在所语句块结束
function test()
	c = 5
	local d = 10
end

test()
print(c) -- 5 
print(d) -- null

do
	local a = 10
	b = 11 -- 覆盖局部变量
	print(a,b) -- 10	11
end
print(a,b) -- Hello	11
  • 变量的一些其他用法
-- 多个变量同时赋值
a, b = 10, 20
a, b, c = 10, 20, "Hello"
print(a,b,c) -- 10	20	Hello

-- 交换两个变量的值
a, b = b, a
print(a,b) -- 20   10

-- 特殊情况
a, b = 10, 20, 30
print(a,b) -- 10   20
a, b, c = 10, 20
print(a,b,c) -- 10	20	nil

-- 接收返回的多个值
function test()
	return 40, 50
end
a = test()
print(a) -- 40
a,b = test()
print(a,b) -- 40   50

Lua 循环

  • Lua 有三种循环

  • while 循环,for 循环,repeat until (do while)

--[[

while(condition) do
   statements
end 

--]]

a = 1
while (a <= 20) do
	if (a%2 == 1) then
		print(a)
	end
	a = a + 1
end

--[[

for var = start,end,step do
   statements
end

--]]

-- 数值for循环
for i = 1,10,2 do
	print(i)
end

for i = 20,1,-3 do
	print(i)
end

-- 泛型for循环
tab = {key1 = "val1", key2 = "val2"}
for k,v in pairs(tab) do
	print(k,v)
end


-- repeat until
a = 1
repeat
	print(a)
	a = a + 1
until(a > 10)

-- 循环嵌套
for i = 1,10 do
	for j = 1,i do
		print(i)
	end
end

for i = 1,10 do
	j = 1
	while (j <= i) do
		print(i)
		j = j + 1
	end
end

Lua 流程控制

-- if
if (0) then
	print(0)
end

-- 判断变量是否为空
if (b) then
	print("b不为空")
else
	print("b为空")
end

-- if else
a = 100
if (a <= 50) then
	print("a <= 50")
elseif (a <= 100) then
	print("a <= 100")
elseif (a <= 150) then
	print("a <= 150")
else
	print("上面三种情况都不满足")
end

Lua 函数

  • Lua 函数主要有两种用途
  • 完成指定的任务,这种情况下函数作为调用语句使用
  • 计算并返回值,这种情况下函数作为赋值语句的表达式使用
--[[

[local] function function_name( arg1, argt2, arg3..., argn)
    function_body
    [return value1, value2, value3..., valuen]
end

-]]

local function max (num1, num2)
	if(num1 > num2) then
		return num1
	else
		return num2
	end
end

print(max(1,10)) -- 10

-- 函数可以作为数据赋值 可以作为参数传递

myprint = function(param)
   print("这是打印函数"..param)
end

myprint(100) -- 这是打印函数100

function add(num1,num2,printFun)
   result = num1 + num2
   -- 调用传递的函数参数
   printFun(result)
end

-- myprint 函数作为参数传递
add(2,5,myprint) -- 这是打印函数7
  • 函数的可变参数和多返回值
  • 在函数参数列表中使用三点 表示函数有可变的参数
  • local arg = {…} 来获取参数列表
-- lua里面的函数可以返回多个值
function test()
	return 40, 50, 60
end

-- 可变参数
function average(...)
	res = 0
	local arg = {...} --> arg 为一个表,局部变量
	for k,v in pairs(arg) do
		res = res + v
	end
	print(res/#arg)
end

average(1,2,3,4,5) -- 3

Lua 运算符

算数运算符

-- 算术运算符
a = 21
b = 10
c = a + b
print("a b 的和 ", c ) -- 31
c = a - b
print("a b 的差 ", c ) -- 11
c = a * b
print("a b 的积 ", c ) -- 210
c = a / b
print("a b 的商 ", c ) -- 2.1
c = a % b
print("a 对 b 求余数 ", c ) -- 1
c = a^2
print("a 的2次幂 ", c ) -- 441
c = -a
print("a 的相反数 ", c ) -- -21

关系运算符

-- 关系运算符
a = 21
b = 10

if( a == b ) then
   print("a 等于 b" )
end
if( a ~= b ) then
   print("a 不等于 b" )
end
if ( a < b ) then
   print("a 小于 b" )
end
if ( a > b ) then
   print(" a 大于 b" )
end

逻辑运算符

-- 逻辑运算符
a = true
b = true

print(a and b)
print(a or b)
print(not a)

# 运算符

-- # 取得table的最大数字索引
tab = {key1 = 12, key2 = 13}
print(#tab) -- 0
tab[1] = 123
tab[2] = 456
tab[4] = 789
print(#tab) -- 4

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

--1	123
--2	456
--4	789
--key1	12
--key2	13

Lua 字符串

字符串定义

  • Lua 语言中字符串可以使用以下三种方式来表示
-- 字符串的定义
str1 = "Lua"
print("\"字符串 1 是\"",str1)
str2 = 'runoob.com'
print("字符串 2 是",str2)
str3 = [["Lua 教程"]]
print("字符串 3 是",str3)

转义字符

  • \n 换行 \\ 代表一个反斜杠
  • \" 代表双引号 \’ 代表单引号
-- 转义字符
-- \n 换行  \\ 代表一个反斜杠
--  \" 代表双引号  \' 代表单引号
str = 'Hello\nWorld My name is \'Micheal\'' 
--Hello
--World My name is 'Micheal'
print(str)
path = "C:\\Users\\10849\\Desktop\\LuaScripts"
-- C:\Users\10849\Desktop\LuaScripts
print(path)

字符串操作

  • string.sub(str, init, [end]) 截取指定字符串
  • string.upper(argument) 字符串全部转为大写字母
  • string.lower(argument) 字符串全部转为小写字母
  • string.gsub(mainStr, findSt, replaceStr, num) 在字符串中替换 [num 指定次数]
  • string.find(str, substr, [init, [end]]) 在一个指定的目标字符串中搜索指定的内容(第三个参数为索引),返回其具体位置,不存在则返回 nil,注意索引从1开始
  • string.reverse(arg) 字符串反转
  • string.format(…) 返回一个类似printf的格式化字符串
  • string.char(arg)string.byte(arg[,int]) char 将整型数字转成字符并连接, byte 转换字符为整数值(可以指定某个字符,默认第一个字符)
  • string.len(arg) 计算字符串长度
  • string.rep(string, n) 返回字符串string的n个拷贝
  • string.gmatch(str, pattern) 回一个迭代器函数,每一次调用这个函数,返回一个在字符串 str 找到的下一个符合 pattern (正则表达式) 描述的子串,如果参数 pattern 描述的字符串没有找到,迭代函数返回 nil
  • string.match(str, pattern, init) 只寻找源字串str中的第一个配对,在成功配对时,函数将返回配对表达式中的所有捕获结果,当没有成功的配对时, 返回nil
-- 格式控制
string1 = "Lua"
string2 = "Tutorial"
number1 = 10
number2 = 20
-- 基本字符串格式化
print(string.format("基本格式化 %s %s",string1,string2))
-- 日期格式化
date = 2; month = 1; year = 2014
print(string.format("日期格式化 %02d/%02d/%03d", date, month, year))
-- 十进制格式化
print(string.format("%.4f",1/3))

-- 模式匹配
for word in string.gmatch("Hello Lua user", "%a+") do 
    print(word)
end
-- Hello
-- Lua
-- user

Lua 数组

一维数组

  • 默认索引从1开始,可以以负数为索引
-- 一维数组
array = {"Lua", "Tutorial"}

for i= 0, 2 do
   print(array[i])
end

-- 可以以负数为索引
array = {}
for i= -2, 2 do
   array[i] = i *2
end

for i = -2,2 do
   print(array[i])
end

多维数组

-- 二维数组
array = {{"a","b"},{"c","d"},{"e","f"},{"h","i"}} -- 4*2
print(array[1][2])

for i = 1, 4 do
	for j = 1, 2 do
		print(array[i][j])
	end
end

-- 初始化数组
array = {}
for i=1,3 do
   array[i] = {}
      for j=1,3 do
         array[i][j] = i*j
      end
end

-- 访问数组
for i=1,3 do
   for j=1,3 do
      print(array[i][j])
   end
end

Lua 迭代器

  • 在 Lua 中迭代器是一种支持指针类型的结构,它可以遍历集合的每一个元素
  • pairs迭代table,遍历表中所有的key跟value
  • ipairs按照索引从1开始,递增遍历,遇到nil值就停止
array = {"Lua","C#","Java"}
for k,v in pairs(array) do
	print(k,v) -- Lua C# Java
end

array[2] = nil
for k,v in ipairs(array) do
	print(k,v) -- Lua
end

状态迭代器

--[[

for 变量列表 in 迭代函数,状态变量,控制变量 do
	-- 循环体
end

-- 1.调用迭代函数,把状态变量和控制变量当作参数传递给迭代函数,状态变量只会在第一次调用时赋值
-- 2.如果迭代函数的返回值为nil,退出for循环
		-- 如果不是nil的话,把返回值赋值给变量列表,并执行循环体
--]]

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

Lua 表格

  • 表格是按引用传递的
  • 如果没有指定的变量指向table,Lua的垃圾回收机制会清理相对应的内存
tab = {}
tab[1] = "Lua"
tab["name"] = "lee"

newtab = tab
newtab[1] = "C#"
print(tab[1])

tab = nil
print(tab) -- nil
print(newtab.name) -- lee 仍然有值,只有没有变量引用了,给内存才会被回收

表格的连接

mytable = {"Lua","C#","Java","C++","C","abc","ABC"}
print(table.concat(mytable,",",2,4) ) -- C#,Java,C++

表格的插入

--插入
table.insert(mytable,"Javascript" )
print(mytable[#mytable]) -- Javascript

table.insert(mytable,2,"Boo")
print(mytable[2],mytable[3]) -- Boo	C#

表格的删除

--删除
table.remove(mytable,2)
print(mytable[2]) -- Boo 被删除,还是C#

表格的排序

--排序
fruits = {"banana","orange","apple","grapes","Apple"}
print("排序前")
for k,v in ipairs(fruits) do
        print(k,v)
end

table.sort(fruits)
print("排序后")
for k,v in ipairs(fruits) do
        print(k,v)
end
-- 排序后
-- 1	Apple
-- 2	apple
-- 3	banana
-- 4	grapes
-- 5	orange

表格的最大值

-- 最大值
function table_maxn(t)
  local mn=nil;
  for k, v in pairs(t) do
    if(mn==nil) then
      mn=v
    end
    if mn < v then
      mn = v
    end
  end
  return mn
end
tbl = {[1] = 2, [2] = 6, [3] = 34, [26] =5}
print("tbl 最大值:", table_maxn(tbl))
print("tbl 长度 ", #tbl)

Lua 模块

  • Lua 的模块是由变量、函数等已知元素组成的 table,因此创建一个模块很简单,就是创建一个 table,然后把需要导出的常量、函数放入其中,最后返回这个 table 就行

模块的定义

-- 文件名为 module.lua
-- 定义一个名为 module 的模块
module = {}
-- 定义常量
module.constant = "这是一个常量"
-- 定义函数
module.func1 = function()
	print("这是一个公有函数")
end

local function func2()
    print("这是一个私有函数!")
end

function module.func3()
    func2()
end

return module

模块的使用

-- test_module.lua 文件
require("module")
print(module.constant) -- 这是一个常量
module.func1() -- 这是一个公有函数
-- module.func2() local无法访问
module.func3() -- 这是一个私有函数

-- 别名变量 m
local m = require("module")
print(m.constant)
m.func1()
m.func3() 

Lua 元表

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

  • 例如,使用元表我们可以定义Lua如何计算两个table的相加操作 a+b

  • 当Lua试图对两个表进行相加时,先检查两者之一是否有元表,之后检查是否有一个叫*"__add"*的字段,若找到,则调用对应的值

  • “__add” 等即时字段,其对应的值(往往是一个函数或是table)就是元方法

元表的设置与获取

  • setmetatable(table,metatable) 对指定 table 设置元表(metatable),如果元表(metatable)中存在 __metatable 键值,setmetatable 会失败

  • getmetatable(table) 返回对象的元表(metatable)

-- 返回第一个表,即普通表
mytable = setmetatable(mytable,mymetatable)

-- 返回元表
print(getmetatable(mytable)) --table: 00A894C8
print(mymetatable) -- table: 00A894C8

-- 直接赋值定义
mytable = setmetatable({"Lua","Java","C#","C++"},{__metatable="lock"})
-- 使用__metatable可以保护元素,禁止用户访问元表中的成员或者修改元表
print(getmetatable(mytable)) -- lock

__index 元方法

  • 当你通过键来访问 table 的时候,如果这个键没有值,那么Lua就会寻找该table的metatable(假定有metatable)中的__index 键
  • 如果__index包含一个表格,Lua会在表格中查找相应的键
-- __index 元方法
-- 当访问一个不存在的索引的时候起作用
mytable = {"Lua","Java","C#","C++"}
-- 方法1
mymetatable = {
__index = function (table, key)
	if(key >= 10) then
		return "Javascript"
	end
end
}
-- 方法2
newtable = {}
newtable[7] = "Javascript"
newtable[8] = "PHP"
newtable[9] = "C"
mymetatable = {
__index = newtable
}
-- 输出测试
mytable = setmetatable(mytable,mymetatable)
print(mytable[1])
print(mytable[10])

__newindex 元方法

  • 当你给表的一个缺少的索引赋值,解释器就会查找__newindex 元方法,如果存在则调用这个函数而不进行赋值操作,而是进行你定义的操作
-- __newindex
-- 对表的数据进行修改,给表添加新的键值对的时候起作用
mytable = {"Lua","Java","C#","C++"}

-- 方式1
mymetatable = {
__newindex = function (tab, key, value)
	print("我们要修改的key为:"..key.."将这个key值改为:"..value)
	rawset(tab,key,value)
end
}
mytable = setmetatable(mytable,mymetatable)
mytable[1] = "C#" -- 不会输出
mytable[5] = "Lua" -- 我们要修改的key为:5将这个key值改为:Lua
print(mytable[1]) -- C#
print(mytable[5]) -- Lua

-- 方式2
-- 新数据添加进 newtable 中
newtable = {}
mymetatable = {
__newindex = newtable
}

mytable = setmetatable(mytable,mymetatable)
mytable[5] = "Lua"
print(mytable[5]) -- nil
print(newtable[5]) -- Lua

为表添加操作符

  • __add 对应的运算符 ‘+’.
  • __sub 对应的运算符 ‘-’.
  • __mul 对应的运算符 ‘*’.
  • __div 对应的运算符 ‘/’.
  • __mod 对应的运算符 ‘%’.
  • __unm 对应的运算符 ‘-’.
  • __concat 对应的运算符 ‘…’.
  • __eq 对应的运算符 ‘==’.
  • __lt 对应的运算符 ‘<’.
  • __le 对应的运算符 ‘<=’.
-- 为表添加操作符  __add
mytable = {"Lua","Java","C#","C++"}
mymetatable = {
__add = function(tab, newtab)
	local mi = 0
	-- 寻找最大索引
	for k,v in pairs(tab) do
		if(k > mi) then
			mi = k
		end
	end
	for k,v in pairs(newtab) do
		mi = mi + 1
		table.insert(tab,mi,v)
	end
	return tab
end
}

mytable = setmetatable(mytable,mymetatable)
newtable = {"PHP","Python"}

-- 一个实现元表即可,影响新表的元素顺序
v1 = mytable + newtable -- 必须有返回值
v2 = newtable + mytable

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

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

call 元方法 & tostring 元方法

  • _call 元方法在 Lua 调用一个值时调用
-- __call __tostring
mytable = {"Lua","Java","C#","C++"}

mymetatable = {
__call = function(tab,arg1,arg2,arg3)
	print(arg1,arg2,arg3)
	return "Lua"
end,
__tostring = function (mytable)
	local str = ""
	for k,v in pairs(mytable) do
		str = str..v..","
	end
	return str
end
}

mytable = setmetatable(mytable,mymetatable)
v = mytable(123,12,1) -- 可以没有返回值
print(v) -- 123	12	1
print(mytable) -- Lua,Java,C#,C++,PHP,Python,

Lua 文件 I/O

  • Lua I/O 库用于读取和处理文件,分为简单模式和完全模式

  • 简单模式(simple model)拥有一个当前输入文件和一个当前输出文件,并且提供针对这些文件相关的操作

  • 完全模式(complete model) 使用外部的文件句柄来实现,它以一种面对对象的形式,将所有的文件操作定义为文件句柄的方法

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

  • 打开文件操作语句: file = io.open (filename [, mode])

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

简单模式

  • 简单模式使用标准的 I/O 或使用一个当前输入文件和一个当前输出文件
-- 以只读方式打开文件
file = io.open("test.lua", "r")
-- 设置默认输入文件为 test.lua
io.input(file)
-- 输出文件第一行
print(io.read())
-- 关闭打开的文件
io.close(file)
-- 以附加的方式打开只写文件
file = io.open("test.lua", "a")
-- 设置默认输出文件为 test.lua
io.output(file)
-- 在文件最后一行添加 Lua 注释
io.write("--  test.lua 文件末尾注释")
-- 关闭打开的文件
io.close(file)

完全模式

  • 通常我们需要在同一时间处理多个文件。我们需要使用 file:function_name 来代替 io.function_name 方法
  • file:read 的参数与简单模式一致
-- 以只读方式打开文件
file = io.open("test.lua", "r")
-- 输出文件第一行
print(file:read())
-- 关闭打开的文件
file:close()
-- 以附加的方式打开只写文件
file = io.open("test.lua", "a")
-- 在文件最后一行添加 Lua 注释
file:write("--test")
-- 关闭打开的文件
file:close()

其他方法

  • file:seek(optional whence, optional offset): 设置和获取当前文件位置,成功则返回最终的文件位置(按字节),失败则返回nil加错误信息

  • file:flush(): 向文件写入缓冲中的所有数据

  • io.lines(optional file name): 打开指定的文件filename为读模式并返回一个迭代函数,每次调用将获得文件中的一行内容,当到文件尾时,将返回nil,并自动关闭文件

Lua 错误处理

  • Lua 可以使用两个函数:assert 和 error 来处理错误
  • 实例中assert首先检查第一个参数,若没问题,assert不做任何事情;否则,assert以第二个参数作为错误信息抛出
local function add(a,b)
   assert(type(a) == "number", "a 不是一个数字")
   assert(type(b) == "number", "b 不是一个数字")
   return a+b
end
add(10) -- b 不是一个数字

Lua 垃圾回收

  • Lua 采用了自动内存管理
  • Lua 运行了一个垃圾收集器来收集所有死对象 (即在 Lua 中不可能再访问到的对象)来完成自动内存管理的工作
  • Lua 实现了一个增量标记-扫描收集器。 它使用这两个数字来控制垃圾收集循环: 垃圾收集器间歇率和垃圾收集器步进倍率。 这两个数字都使用百分数为单位 (例如:值 100 在内部表示 1 )
  • 垃圾回收器函数略,一个简单的垃圾回收实例如下,输出内存的变化
mytable = {"apple", "orange", "banana"}
print(collectgarbage("count")) -- 20.9560546875
mytable = nil
print(collectgarbage("count")) -- 20.9853515625
print(collectgarbage("collect")) -- 0
print(collectgarbage("count")) -- 19.4111328125

Lua 面向对象

  • LUA中的类可以通过 table + function 模拟出来
  • 继承可以通过 metetable 模拟出来(不推荐用,只模拟最基本的对象大部分时间够用了)
Person = { name = "lee", age = 99 }
-- 当通过 : 调用的时候,系统会自动传递当前的table给self,  
-- 当通过 . 来调用方法的时候,self不会自动赋值,我们必须通过第一个参数来传递当前的table
-- a.eat(a)
-- a:eat()
function Person:eat()
	print(self.name.."在吃饭")
	print(self.name.."的年龄是"..self.age)
end

function Person:new(o)
	local t = o or {} -- 如果o不为空,则 t = o,否则 t = {}
     --调用一个属性的时候,如果t中不存在,那么会在__index 所指定的table中查找
	-- setmetatable( t, { __index = self }) -- 方法1
	-- 方法2
    setmetatable(t,self)
	self.__index = self
	return t
end

person1 = Person:new()
person2 = Person:new() -- person2 与 person1 没有关系
person1.name="leenew" -- 新表定义了,再次访问时,不再采用元表的数据
person1:eat()
person1.weight = 100
print(person1.weight) -- 可以增加新的字段

-- 继承,构建新类 Student
Student = Person:new()
Student.grade=1
stu1 = Student:new()
stu1:eat() -- Student没有,访问的是Person的
print(stu1.grade) -- Student有的,访问的是Student里的

你可能感兴趣的:(lua,lua,编程语言,字符串)