lua学习的查缺补漏
目录
- 多行注释
- 取整
- 长字符串
- 字符串标准库
- lua中安全访问
- 表
- 可变长参数
- 输入和输出
- lua运行一段程序
认真学习,增强自己的能力和知识面。
多行注释
1
2
3
4
--[[
fdsa
fdas
]]
取整
为了做到公平性取整,应该做到3.5+0.5为偶数则进位,而2.5+0.5为奇数不进位。
1
2
3
4
5
6
7
8
function round(x)
local f = math.floot(x)
if (x == f) or (x % 2.0 == 0.5) then
return f
else
return math.floor(x + 0.5)
end
end
长字符串
在lua中字符串是常量,一个字符串当被存到内存中的时候就不能再被改变了,所以我们发现如果一个变量引用了一个字符串,我们是不能像CC++那样通过索引进行改变其值的,只能从新赋值新的字符串,这样子其实是这个变量指向了另一块内存了。
1
2
3
4
5
6
local page = [[
fdsaf
fdasf
]]
字符串标准库
1
2
3
4
5
6
7
8
9
10
11
12
13
string.gsub("one string","one","two") --> two string
string.rep("abc",3)
string.reverse("abc")
string.lower("Abc")
string.upper("abc")
string.sub("abc",1,2) –包含1和2
string.char(97) – a,转换字符及其内部数值表示形式
string.byte(a) – 97
string.find("hello world", "wor") –7 9
string.gsub("hello world", "l", ".") –he…o wor.d
一般情况下,string内部的函数都是针对于字节进行操作的,当遇到中文就不行了,在这里lua增加了utf8的函数封装。
1
2
3
4
5
6
7
8
local s = "中华人民共和国"
utf8.len(s) --7,返回指定字符串中UTF-8字符的个数
--utf8把字符位置转换成字节位置
print(utf8.codepoint(s,utf8.offset(s,1),utf8.offset(s,2))) --
print(utf8.char(20013,21326))
print(utf8.offset(s,3))
print(string.sub(s,1,utf8.offset(s,3) - 1 )) --在使用的时候需要注意,offset返回的是字符的第一个字节位置,在截取的使用时候需要减去1
print(3.5 % 2)
lua中安全访问
通过 (class or {}). 的方式来实现安全访问
表
表的拷贝除了使用遍历赋值之外,还可以通过table.move函数来实现。
在这里注意到下面的代码,如果我将table插入到另一个table中,这里是引用,而不是新开辟了一块新的内存,如果我现在改变inta中index为1的值,那么表a中index为1的表的index为1的值也会随着改变。
这里还需要思考一个问题,什么时候一个变量才算引用一个表成功呢?意思是这两个变量是否指向同一块内存,一般我们常说基本类型一般是不会引用的像数值和布尔,这里table会被引用,
1
2
3
4
5
6
7
8
9
10
table.move(a,1,#a,1,{})
local inta = {1,2,3}
local a = {}
local b = {}
for i = 1, 3 do
table.insert(a,inta)
end
table.move(a,1,#a,1,b)
通过’#’符号对表进行取长度,只适应于数组,不适应于hash表,当表中存在空洞的时候,不要再使用’#’来取长度了,在对数组进行添加和移除的时候,应该使用remove和insert函数,而不应该直接赋空值。
这里常见的误区包括:
- 对一个数组中的某个索引进行完赋空值操作之后,还使用ipairs进行遍历,因为存在空洞,所以是不可能遍历整个数组的。
- 一次遍历删除数组中的多个值,这样子可能会导致删除不干净,当连续两个相同的值需要删除的时候,后面那个值是删除不掉的,因为他的索引值已经减一了,到了刚删除值的位置了。这样子是遍历不到它的。
要怎么解决这个问题呢?
如果删除之后不保留数组的特性,那么直接遍历一遍删除的赋值为nil就行了,但是一般很少不保留,所以应该使用下面这种方法,那就是创建一个新表,删除的不插入其中,不删除的插入其中,然后赋值给原来的变量。
可变长参数
在函数中,一个函数为了可以接受可变长的参数列表,一般采用三个点。
用这个三个点获取来的参数列表其实是一个表达式,和return回来多个值是一样的,可以选择接受一个或者多个,也可以通过表的形式全部接受。
但是如果可变长参数中包含无效的nill,那么{…}获得的表可能不再是一个有效的序列。这样会导致一个问题,就是table中存在nil的时候,元素就会被自动移除。假设参数为 1,nil,2,那个打包到table中就只剩下1,2了,table的长度为2,不是一个数组,因为table[2]没有这个键值。
这个时候我们可以使用table.pack来打包可变长参数。通过pack打包出来的表会存在一个键值n,表示原来 … 返回来的参数个数。
通过table.unpack可以解开表,返回内容类似于return表达式。
输入和输出
如果没有重定向io.lines(),默认会从控制台接收输入,运到换行符不会结束,会以CTR^Z结束。
io.input和io.output可以用于改变当前的输入输出流。调用io.input(file_name)会以只读模式打开指定的文件,并将文件设置为当前输入流。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
local file = io.open("a.txt","r")
io.read() –类似于c中的cin函数
io.write()–类似于c中cout函数
local t = {}
for line in io.lines() do
table.insert(t,line)
end
local temp = io.input() –保存当前的输入流
io.input("newinput") –打开一个新的当前输入流
对新的输入流进行某些操作
io.input():close() –关闭当前流
io.input(temp) –回复此前的当前输入流
print(os.execute("ls"))
io.read(args)实际上是io.input():read(args)的简写。
io.write((args)是io.output():write(args)的简写。
为了及时的获取输入流中的内容,可以使用io.flush()函数刷新输入流。
我们可以使用os.excute(“ls”),来展示目录中的文件。
lua运行一段程序
突然发现自己用多了编译器竟然不知道lua是怎么运行一段程序的了,一般lua运行程序分为两种:
1
2
3
lua -i prog --运行prog这个文件的带码,并进入交互模式
dofile("lib1.lua") –在交互模式下加载文件
函数dofile在开发阶段非常有用,我们可以通过它重新加载带码,这样就可以使用新的代码了。
使用方法如下:
- 加载一个文件: dofile(“hello.lua”)
- 调用文件中的函数
- 修改文件中的函数
- 重新加载文件: dofile(“hello.lua”)
- 调用函数:就会发现输入的内容使我们新修改的内容
而且lua存在独立的解释器类似于,这个就像是通过命令行执行一个c程序一样,lua命令的完整参数形式如:
lua [options] [script [args]]
- -e参数允许我们直接在命令行中输入代码
- -l参数用于加载库。
- -i参数用于在运行完其它命令行参数后进入交互模式
%lua -e “sin=math.sin” script a b
在上面的用例中,编译器在运行代码前会创建一个名为arg的边,其中存储了所有的命令行参数。索引0中保存的内容为脚本名,索引1保存的为第一个参数。所以上面的例子解释如下:
- arg[-3] = “lua”
- arg[-2] = “-e”
- arg[-1] = “sin=math.sin”
- arg[0] = “script”
- arg[1] = a
- arg[2] = b
1
2
3
4
5
6
7
8
9
10
11
12
local function printParams(arg)
for i, v in ipairs(arg) do
print(v)
end
end
printParams(arg)
print(sin(12))
–lua -e "sin=math.sin" hello.lua 1 2
<hr style="visibility: hidden;"/>
<hr style="visibility: hidden;"/>