数学库
三角函数(sin,cos,tan……)

所有的三角函数都使用弧度单位,可以用函数deg(角度)和rad(弧度)来转换角度和弧度。示例代码:
print(math.sin(math.rad(30))) -- 0.5
谨记:三角函数的参数都是弧度,在实际使用中不要忘了,是弧度。


取整函数(floor,ceil)

floor:返回不大于x的最大整数;向下取整;
ceil:返回不小于x的最大整数;向上取整。示例代码:
print(math.floor(5.6)) -- 5
print(math.ceil(5.6)) -- 6

最大值和最小值(max,min)

max:取参数中的最大值;
min:取参数中的最小值。示例代码:
print(math.max(2, 3, 2, 14, 2, 30, -3)) -- 30
print(math.min(2, 3, 2, 14, 2, 30, -3)) -- -3

生成伪随机数的函数(random,randomseed)

在实际开发中,生成随机数的需求是经常有的。使用random和randomseed这两个函数就可以轻易的完成。math.random用于生成伪随机数,可以用3种方式来调用它:
(1)如果在调用时不提供任何参数,它将返回一个在区间[0, 1)内均匀分布的伪随机实数;
(2)如果提供了一个整数n作为参数,它将返回一个在区间[1, n]内的伪随机整数;
(3)如果提供了两个整数参数m和n,它将返回一个在区间[m, n]内的伪随机整数。
示例代码如下:
函数math.randomseed用于设置伪随机数生成器的种子数。
一般我们的做法是在一个程序启动时,用一个固定的种子数来调用它,以此初始化伪随机数生成器。
那么如何设置这个math.randomseed的种子值呢?如果使用同一个种子值的话,每次得到的随机数就会是一样的,在实际开发中,一般都是使用当前时间作为种子值,比如:
math.randomseed(os.time())
这样就好了。一般在我们的程序启动时,初始化一次种子就足够了。我曾经傻傻的在一个循环中,使用math.random取随机数,每次都调用math.randomseed(os.time())设置种子值

math.randomseed(os.time()) 

print(math.random()) -- 输出一个大于等于0,小于1的值 

print(math.random(2)) -- 输出不是1就是2 

print(math.random(3, 4)) -- 输出不是3就是4 


table库 


table库是由一些辅助函数构成的,这些函数将table作为数组来操作(重点:作为数组来操作的)。 


插入和删除函数 


table.insert用于将一个元素插入到一个数组的指定位置,它会移动后续元素以空出空间。如果在调用table.insert时没有指定位置参数,则会将元素添加到数组末尾。示例代码: 

local tb = {10, 20, 30} 

table.insert(tb, 40) -- 在table的最后插入,结果为:{10, 20, 30, 40} 

table.insert(tb, 2, 15) -- 在table的位置2插入,结果为:{10, 15, 20, 30, 40} 


排序 

local tb = {20, 10, 2, 3, 4, 89, 20, 33, 2, 3} 

  

-- 默认是升序排序 

table.sort(tb) 

for _, v in ipairs(tb) do 

    print(v) 

end 

  

print("=======") 

  

-- 修改为降序排序 

table.sort(tb, function (a, b) if a > b then return true end end) 

for _, v in ipairs(tb) do 

    print(v) 

end 


但是,在实际开发中,我们经常犯这样的错误,总是试图对一个table的索引进行排序。在table中,索引是一个无序的集合。 

如果对它们进行排序,则必须将它们复制到一个数组中,然后对这个数组进行排序。这就是我为什么一开始强调的,table库是对数组进行操作的。 

local tb = {x = 20, z = 10, y = 30, m = 2, n = 8} -- 这是一个key无序的table 

  

local keyTb = {} 

for k, _ in pairs(tb) do 

    keyTb[#keyTb + 1] = k 

end 

  

table.sort(keyTb) 

  

for _, v in ipairs(keyTb) do 

    print(v .. " = " .. tb[v]) 

end 


连接 


使用table.concat可以完成数组的连接。它接受一个字符串数组,并返回这些字符串连接后的结果,它有一个可选参数, 

用于指定插到字符串之间的分隔符,同时这个函数另外还接受两个可选参数,用于指定第一个和最后一个要连接的字符串索引。示例代码: 

local tb = {"Jelly", "Think", "Is", "Good"} 

local strTb = table.concat(tb, " ") 

print(strTb) 


完整I/O模型 


简单I/O功能太受限了,以至于基本没有什么用处,而用的更多的则是这里说的完整I/O模型。完整I/O模型可以进行更多的I/O控制,它是基于文件句柄的,就好比与C语言中的FILE*,表示一个正在操作的文件。 


要打开一个文件,可以使用io.open函数,它有两个参数,一个表示要打开的文件名,另一个表示操作的模式字符串。模式字符串可以有以下四种取值方式: 


(1)”r”:以读取方式打开文件;只能对文件进行读取操作; 

(2)”w”:以写入方式打开文件;可以对文件进行写入操作,但是会覆盖文件原有内容; 

(3)”a”:以追加方式打开文件;可以对文件进行写入操作;会在原来文件的基础在,进行追加写入; 

(4)”b”:表示打开二进制文件,这种模式一般都是和前面三种混合使用,比如:”rb”,”wb”。 


open函数会返回表示文件的一个句柄;如果发生错误,就返回nil,一条错误消息和一个错误代码。示例代码: 

-- 访问一个不存在的文件 

print(io.open("ooxx.txt", r)) 

--[[ 

输出以下内容: 

nil    ooxx.txt: No such file or directory    2 

--]]



当成功打开一个文件以后,就可以使用read/write方法读写文件了,这与read/write函数相似,但是需要用冒号语法,将它们作为文件句柄的方法来调用,示例代码:

local hFile = io.open("input.txt", r) 

if hFile then 

    local strContent = hFile:read("*all") 

    --local strContent = hFile.read(hFile, "*all") 你也可以使用这种方法 

    print(strContent) 

end 


time 


如果不带任何参数调用time函数,它会以数字形式返回当前的日期和时间。 

print(os.time()) -- 输出当前时间的描述 


date 



函数date是time的一个反函数,它可以将一个表示日期和时间的数字转换成某些高级的表现形式。 

其第一个参数是格式字符串,指定了期望的表示形式;第二个参数是日期和时间的数字,默认为当前日期和时间。例如: 

local tbCurrentTime = os.date("*t") 

  

for k, v in pairs(tbCurrentTime) do 

    print(k .. "=" .. tostring(v)) 

end 


assert 


当Lua遇到不期望的情况时就会抛出错误,比如:两个非数字进行相加;调用一个非函数的变量;访问表中不存在的值等。你也可以通过调用error函数显示的抛出错误,error的参数是要抛出的错误信息。 

assert(a,b) a是要检查是否有错误的一个参数,b是a错误时抛出的信息。第二个参数b是可选的。 

assert首先检查的是第一个参数是否返回错误,如果不返回错误,则assert简单返回,否则则以第二个参数抛出异常信息。 

assert()是普通函数,他首先计算两个参数,然后在调用函数,如: 


n = io.read() 

assert(tonumber(n), "invalid input:" .. n .. "is not a number") 


  

先进行tonumber(n), "invalid input:" .. n .. "is not a number"这两个参数的计算。 


没用assert( )时: 


input = io.read("*number") 

print(input)   

运行结果: 

nil 

[Finished in 0.3s]   


用assert( )时: 


input = assert(io.read("*number")) 

print(input) 


运行结果: 


lua: D:\UserProfiles\BenLuo\Desktop\study\test.lua:44: assertion failed! 

stack traceback: 

    [C]: in function 'assert' 

    D:\UserProfiles\BenLuo\Desktop\study\test.lua:44: in main chunk 

    [C]: ? 

[Finished in 0.3s with exit code 1] 



 local name = io.read();   

local result = assert(name == "笨木头", "你是一个非常善良有爱心的人,我很喜欢你..所以,去死吧!");   

如果assert的第一个参数为不为false,则返回第一个参数的值;否则,执行error函数,输出错误信息,错误信息的内容为assert的第二个参数。 


error 

当我们在调用一个函数之前,可以先判断即将传递的参数是否正常,如果不正常,我们就可以选择直接抛出error,方便写代码的过程中发现问题。 

    local name = io.read();   

       if name ~= "笨木头" then   

           error("你是一个非常善良有爱心的人,我很喜欢你..所以,去死吧!");   

       end   

只要发现输入的内容不是“笨木头”,就狠狠地抛出异常。 


pcall 

如果在错误发生时,我们不希望代码停止运行,而是做一些紧急措施,那么,可以使用pcall捕获错误。 

    function test()   

            print(a[1]);   

        end   

        if pcall(test) then   

            print("正常,呵呵");   

        else   

            print("哎,函数出错了,我正在帮你处理,放心吧,等我睡醒就...不是,等你睡醒就没事了~");   

              

        end 

函数test执行的时候肯定会报错的,因为并不存在a这个table。 

使用pcall调用test函数,如果test不报错,则pcall返回ture,否则,返回false。 

利用这个特性,我们就可以捕获异常,做一些紧急处理。 

pcall除了会返回true或者false外,还能返回函数的错误信息,如下代码: 

    function test()   

            print(a[1]);   

        end   

        local status, err = pcall(test);   

        if status then   

            print("正常,呵呵");   

        else   

            print("哎,函数出错了,我正在帮你处理,放心吧,等我睡醒就...不是,等你睡醒就没事了~");   

            print(err);   

        end   

pcall的第一个返回值和之前一样,true或者false。 


而第二个参数则是test函数抛出的错误信息,执行代码,结果如下: 

    [LUA-print] 哎,函数出错了,我正在帮你处理,放心吧,等我睡醒就…不是,等你睡醒就没事了~   

    [LUA-print] [string "src/main.lua"]:94: attempt to index global ‘a' (a nil value)   



数学函数 


这些表函数同样可以参考Lua函数库(他们都是以math.开头, 详情参阅数学库了解更多信息). 


abs(value) - 返回当前数值的绝对值 


acos(value) - 返回此角度值的弧余弦值. 


asin(value) - 返回此角度值的弧正弦值 


atan(value) - 返回此角度值的弧正切值 


atan2(y, x) - 在角度中, 返回Y/X的弧正切值. 


ceil(value) - 返回一个整数, 不管小数点后面是多少, 整数部分都进1 


cos(degrees) - 返回角度的余弦值 


deg(radians) - 弧度转换角度 


exp(value) - 返回此值的指数值 


floor(value) - 返回此值的整数值 


frexp(num) - 返回当前数字小数点后的数值以及小数点后的位数 



ldexp(value, 倍数) - 输出此数值的倍数 


log(value) - 返回此值的自然对数 (以e为底数) 


log10(value) - 返回以10为底数的值 


max(value[, values...]) - 在一堆值中查找最大值 


min(value[,values...]) - 在一堆值中查找最小值 


mod(value,modulus) - 返回此值的余数 


rad(degrees) - 角度转换弧度 


random([ [lower,] upper]) - 返回一个随机数字 (可选界限为整数值) 


randomseed(seed) - 为伪随机数字生成器设定种子 


sin(degrees) - 返回当前角度的正弦值 


sqrt(value) - 返回数值的平方根值(比如100的平方根为10) 


tan(degrees) - 返回当前角度的正切值 




table.concat(table, sep,  start, end) 


concat是concatenate(连锁, 连接)的缩写. table.concat()函数列出参数中指定table的数组部分从start位置到end位置的所有元素, 元素间以指定的分隔符(sep)隔开。除了table外, 其他的参数都不是必须的, 分隔符的默认值是空字符, start的默认值是1, end的默认值是数组部分的总长. 


sep, start, end这三个参数是顺序读入的, 所以虽然它们都不是必须参数, 但如果要指定靠后的参数, 必须同时指定前面的参数. 


> tbl = {"alpha", "beta", "gamma"} 

> print(table.concat(tbl, ":")) 

alpha:beta:gamma 

> print(table.concat(tbl, nil, 1, 2)) 

alphabeta 

> print(table.concat(tbl, "\n", 2, 3)) 

beta 

gamma 


table.insert(table, pos, value) 


table.insert()函数在table的数组部分指定位置(pos)插入值为value的一个元素. pos参数可选, 默认为数组部分末尾. 


> tbl = {"alpha", "beta", "gamma"} 

> table.insert(tbl, "delta") 

> table.insert(tbl, "epsilon") 

> print(table.concat(tbl, ", ") 

alpha, beta, gamma, delta, epsilon 

> table.insert(tbl, 3, "zeta") 

> print(table.concat(tbl, ", ") 

alpha, beta, zeta, gamma, delta, epsilon 



table.maxn(table) 


table.maxn()函数返回指定table中所有正数key值中最大的key值. 如果不存在key值为正数的元素, 则返回0. 此函数不限于table的数组部分. 


> tbl = {[1] = "a", [2] = "b", [3] = "c", [26] = "z"} 

> print(#tbl) 

3               -- 因为26和之前的数字不连续, 所以不算在数组部分内 

> print(table.maxn(tbl)) 

26 

> tbl[91.32] = true 

> print(table.maxn(tbl)) 

91.32 



table.remove(table, pos) 


table.remove()函数删除并返回table数组部分位于pos位置的元素. 其后的元素会被前移. pos参数可选, 默认为table长度, 即从最后一个元素删起. 


table.sort(table, comp) 


table.sort()函数对给定的table进行升序排序. 


> tbl = {"alpha", "beta", "gamma", "delta"} 

> table.sort(tbl) 

> print(table.concat(tbl, ", ")) 

alpha, beta, delta, gamma 


comp是一个可选的参数, 此参数是一个外部函数, 可以用来自定义sort函数的排序标准. 


此函数应满足以下条件: 接受两个参数(依次为a, b), 并返回一个布尔型的值, 当a应该排在b前面时, 返回true, 反之返回false. 


例如, 当我们需要降序排序时, 可以这样写: 


> sortFunc = function(a, b) return b < a end 

> table.sort(tbl, sortFunc) 

> print(table.concat(tbl, ", ")) 

gamma, delta, beta, alpha 


用类似的原理还可以写出更加复杂的排序函数. 例如, 有一个table存有工会三名成员的姓名及等级信息: 


guild = {} 


table.insert(guild, { 

 name = "Cladhaire", 

 class = "Rogue", 

 level = 70, 

}) 


table.insert(guild, { 

 name = "Sagart", 

 class = "Priest", 

 level = 70, 

}) 


table.insert(guild, { 

 name = "Mallaithe", 

 class = "Warlock", 

 level = 40, 

}) 



对这个table进行排序时, 应用以下的规则: 按等级升序排序, 在等级相同时, 按姓名升序排序. 


可以写出这样的排序函数: 


function sortLevelNameAsc(a, b) 

 if a.level == b.level then 

  return a.name < b.name 

 else 

  return a.level < b.level 

 end 

end 


测试功能如下: 


> table.sort(guild, sortLevelNameAsc) 

> for idx, value in ipairs(guild) do print(idx, value.name) end 

1, Mallaithe 

2, Cladhaire 

3, Sagart 


table.foreachi(table, function(i, v)) 

会期望一个从 1(数字 1)开始的连续整数范围,遍历table中的key和value逐对进行function(i, v)操作 


t1 = {2, 4, 6, language="Lua", version="5", 8, 10, 12, web="hello lua"}; 

table.foreachi(t1, function(i, v) print (i, v) end) ; --等价于foreachi(t1, print) 


输出结果: 

1 2 

2 4 

3 6 

4 8 

5 10 

6 12 


table.foreach(table, function(i, v)) 

与foreachi不同的是,foreach会对整个表进行迭代 


t1 = {2, 4, 6, language="Lua", version="5", 8, 10, 12, web="hello lua"}; 

table.foreach(t1, function(i, v) print (i, v) end) ; 


输出结果: 

1 2 

2 4 

3 6 

4 8 

5 10 

6 12 

web hello lua 

language Lua 

version 5 


table.getn(table) 

返回table中元素的个数 


t1 = {1, 2, 3, 5}; 

print(getn(t1)) 

->4 


table.setn(table, nSize) 

设置table中的元素个数 



 dofile (filename) 


打开该名字的文件,并执行文件中的 Lua 代码块。 不带参数调用时, dofile 执行标准输入的内容(stdin)。 返回该代码块的所有返回值。 对于有错误的情况,dofile 将错误反馈给调用者 (即,dofile 没有运行在保护模式下)。 

例子 


同一目录下新建两个 Lua 文件,代码及输出: 


-- another.lua 

return "Message from another file!" 


-- sample.lua 

x = dofile("./another.lua") 

print(x)    --> Message from another file! 



 ipairs (t) 


返回三个值:迭代器、传入的表 t、值 0 。迭代器能够根据传入的表 t 和索引 i 得到 i+1 和 t[i+1] 的值。 


其实现形式类似于这样: 

例子 


使用 ipairs 对表进行遍历,会从键值为 1 开始依次向后遍历,直到值为 nil。 


t = {"1","2",nil,[4]="4"} 

-- t = {"1","2",[4]="4"}   -- 使用该表会得到相同的输出 


for i,v in ipairs(t) do 

    print(i,v) 

end 


--> 1   1 

--> 2   2 



 pairs (t) 


返回三个值:next 函数,表 t,nil。通常用来遍历表中的所有键值对。 

如果 t 有元方法 __pairs ,将 t 作为参数 传入该函数并返回前三个返回值。 


在使用 pairs 函数遍历表的过程中,可以删除域或者修改已有的域,但是如果添加新的域,可能出现无法预期的问题。 

例子 


t = {"table",["a"] = 5, ["c"] = 6} 

for k,v in pairs(t) do 

    print(k,v) 

end 

--> 1   table 

--> a   5 

--> c   6 


 rawequal (v1, v2) 


以 raw 作为前缀的函数均表示该方法在不触发任何元方法的情况下调用。 


rawequal 检查 v1 是否与 v2 相等,返回比较结果。 

例子 


t = {"value"} 

s = "value" 

s2 = "value" 

print(rawequal(t, s))     --> false 

print(rawequal(s, s2))    --> true 


 rawget (table, index) 


获取 table 中键 index 的关联值,table 参数必须是一个表,找不到返回 nil 。 

例子 


t = {"value",x = 5} 


print(rawget(t, 1))     --> value 

print(rawget(t, "x"))   --> 5 

print(rawget(t, 2))     --> nil 

print(rawget("value",1))--> bad argument #1 to 'rawget' (table expected, got string) 


rawset (table, index, value) 


将 table[index] 的值设置为 value 。table 必须是一张表,index 不能是 nil 或 NaN 。value 可以是任何值。返回修改后的 table 。 

例子 


t = {"value",x = 5} 

t2 = {"sub table"} 

rawset(t, 1,"new value") 

rawset(t, "y", 6) 

rawset(t, t2,"sub table") 

rawset(t,NaN,"NaN")         --> table index is nil 


print(t[1])                 --> new value 

print(t.y)                  --> 6 

print(t[t2])                --> sub table 



 tonumber (e [, base]) 


tonumber([值],[基数]=10) 


尝试把 e 转换为十进制数值并返回。如果无法转换返回 nil 。 


base 表示传入参数的进制,默认为 10 进制。base 的可输入范围 [2,36]。高于 10 的数字用字母表示,A-Z 分别表示 11-35 。 

例子 


print(tonumber(123))            --> 123 

print(tonumber("123"))          --> 123 

print(tonumber("abc"))          --> nil 

print(tonumber("abc", 20))      --> 4232 

print(tonumber("ABC", 20))      --> 4232 



 tostring (e) 


能将任意类型的值转换为合适的字符串形式返回。要控制数字转换为字符串的方式,使用 string.format(formatstring,...) 。 


如果值所关联的元表有 __tostring 域,则使用该域的元方法获取字符串。 

例子 


function func() 

    print("this is a function") 

end 

t = {name = "table"} 


print(tostring(123))        --> 123 

print(tostring("abc"))      --> abc 

print(tostring(func))       --> function: 0x7f86348013b0 

print(tostring(t))          --> table: 0x7f86348013e0 



 type (v) 


返回 v 的类型,类型以字符串形式返回。 有以下八种返回值: "nil" , "number", "string", "boolean", "table", "function", "thread", "userdata"。 

例子 


type(nil)                   --> "nil" 

type(false)                 --> "boolean" 

type(123)                   --> "number" 

type("abc")                 --> "string" 


print(type(nil) == "nil")   --> true 



 unpack (list [, i [, j]]) 


unpack([列表],[起始位置]=1,[返回个数]=[列表长度]) 


返回表中的各个域的值,等价于返回 


return list[i], list[i+1], ···, list[j] 


例子 


t = {1,2,3,a = 4,b = 5} 


print(unpack(t, 1, 4))      --> 1   2   3   nil