这篇文章将着重讲解Lua的 表(table),函数(Function) 和 输入/输出流。
5. Lua表
5.1 常见用法
(1): Lua中的表有两种常见用法,第一种类似于list,第二种类似于python中的字典dictionary。
例1: a = {2,3,4,5}
for k, v in pairs(a) do print(k,v) end
--> 1 2
2 3
3 4
4 5
例2:a = {hello = 1, no = 2}
for k, v in pairs(a) do print(k,v) end
--> hello 1
no 2
(2): Lua值的修改
例:e = {"a","b","c","d"}
e["a"] = "f" -->将a替换为f
(3):数字不能被当作key,可以将其放在[]内部,视其为string才可使用,如:
a = {[3] = "hello", [5] = "world"}
注:可以同时使用string和number作为表的key值,但如果以number作为key值遇到未声名对象,则会被覆盖,而使用string作为key值则不会,如:
a = {1,2,3,[3] = "hello", ["3"] = "world"}
for k, v in pairs(a) do print(k,v) end
--> 1 1
2 2
3 3
3 world
(4): 可以使用#a来获得表table的长度,但使用string作为key定义的构造器将不计入总长度中,同时若跳过某个自然数key值,后值将不计入总长度,如:
例1:a = {1,2,[3] = "hello", ["3"] = "world"}
print(#a) --> 3
例2:a = {1,2,[4] = "hello", ["3"] = "world"}
print(#a) --> 2
(5): 可以使用ipairs来顺序的获得当前序列,而pairs不行
5.2 表的标准库
(1): insert(t,p,v): 将表t的第p个元素插入v,如:
a = {1,2,3}
table.insert(a,4,4)
--> 1 1
2 2
3 3
4 4
(2): remove(t,p): 将表t的第p个位置删除,并可以作为返回值,如:
a = {1,2,3}
table.remove(a,3)
--> 1 1
2 2
(3): concat(a): 将表a的所有元素连接在一起,也可以添加一位,使得每次连接都会加上该元素
例1:a = {1,2,3}
table.concat(a)
--> 123
例2:a = {1,2,3}
table.concat(a,4)
--> 14243
(4): sort(a, [way]): 将表a排序,way为排序的方法(默认由小到大),如:
a = {5,4,3}
table.sort(a)
--> 1 3
2 4
3 5
6. Lua函数
6.1 函数的基础用法
(1): Lua中的函数基础表达式为:
function name1(name2)
return name3
end
其中return可以不写(类似于c++中可以return;)
(2): 调用Lua函数时使用的参数可以与函数的参数不一致,Lua会自动去除多余的调用数据,并将少的数据使用nil代替,如:
function add(a,b)
return a+b
end
add(3,5,7) --> 8
(3): Lua函数可以设置多个返回值,可以不完全被接受,多余的返回值将会被丢弃,如:
function add(a,b)
return a+b, a, b
end
d,f = add(3,5,7) --> 8 3
注:只有当调用函数是表示中最后一个表达式时才会返回多个值,否则只取第一个,后面的将被弃用,如:
function add(a,b)
return a+b, a
end
c = {add(3,4), add(5,6)} --> 7 11 5 (表构造器会完整的接受函数调用的返回值)
6.2 可变长参数函数(variadic)
(1): 可变长参数函数是指参数的长度是可变的,如:
function add(...)
return 0 end
此时...被视为是一个表达式,也称为可变长参表达式,可以将其放入表中,例如:
print(...) -->打印出所有参数
(2): 长参数的遍历:
select(n,...): 返回从第n个开始的...中的元素,即我们可以从1遍历:
for i = 1, select("#",...) do
a = select(i,...)
print(a)
end
(3): 尾调用消除:Lua语言中可以return一个函数,使得其不申请额外的栈空间,可以有效避免栈的溢出
7. Lua输入/输出流
Lua中的 I/O库 提供了两种模型,虚拟了输入流(input stream)和输出流 (output stream)。 在实际操作中,io.input用于改变输入流,io.output用于改变输出流。
7.1 数据读取:
-- io.lines(): 用于遍历文件的行,例如:
for line in io.lines() do ...
-- io.read("n"): 读取一个数字,如果存在则返回true,不存在则返回false。
-- io.read(0): 用于检查是否位于文件末尾,如果返回nil则表示后面没有内容可读(位于末尾)。
-- io.flush(): 将所有缓冲文件写入文件,用于刷新当前输入流。
-- io.exit(): 终止程序的进行
-- os.rename(): 重命名文件
-- os.remove(): 删除文件
-- io.seek(whence, offset): 用于获取和设置当前文件的位置。
7.2 练习
编写一个程序,读取一个文本文件然后将每行的内容按照首字母表顺序排序后再重新写入该文件。如果在调用时不带参数,则从标准输入流读取并向标准输出流写入。如果调用时传入一个文件名,则以该文件作为输入流。如果传入2个文件名,则前者作为输入流,后者作为输出流。
答案:
function sort(filename_1, filename_2)
--处理写入问题
local a = {}
if filename_1 ~= nil then
local file = io.input(filename_1,"r")
end
for line in io.lines() do
table.insert(a,line)
end
table.sort(a)
--处理读出问题
if filename_2 ~= nil then
io.output(filename_2,"w")
end
for _,line in ipairs(a) do
io.write(line, "\n")
end
end
到此本章节结束。下一章开始将正式启动Lua语言编程实操,大家可以多多练习,一起进步!