Lua笔记

.

基础知识

使用-i可以让Lua在执行完指定的程序后进入交互模式

调用函数可以用dofile,如在交互模式下,使用dofile(“test.lua”),可以将test.lua中的函数加载到当前环境中

注释用--

多行注释:

1
2
3
--[[多行
长注释
]]

常用方法(不执行语句)

1
2
3
--[[
print(10)
--]]

当想要执行时

1
2
3
---[[
print(10)
--]]

全局变量

变量未赋值默认为nil,Lua不区分赋值为nil的变量和未初始化变量

类型和值

Lua有8种基本类型

  1. nil(空)
  2. boolean(布尔)
  3. number(数值)
  4. string(字符串)
  5. userdata(用户数据)
  6. function(函数)
  7. thread(线程)
  8. table(表)

使用type()可以获取值对应的类型

Boolean

Lua语言将falsenil视作假,其他视为真

逻辑操作

and

如果第一个操作数为假,返回第一个操作数,否则返回第二个

or

如果第一个操作数不为假,返回第一个,否则返回第二个

not永远返回Boolean类型的值

解释器

参数

-e直接在命令行输入代码

1
lua -e "print(10)"

数值

Lua5.2及之前的版本数值均以双精度浮点格式表示

Lua5.3可以采用64位int或双精度浮点类型

type(3)type(3.0)都是number

可以用math.type(3)math.type(3.0)区分整型与浮点型

整除法//恒向负无穷取整

关系运算

< > <= >= == ~=

数学库

包含三角函数,指数函数,取整函数,最大和最小函数,随机数,pi以及huge,所有三角函数均以弧度为单位

math.random

不带参数返回[0,1)内的均匀分布,带1个参数m,返回[1,m]的伪随机整数,两个参数l和m返回[l,m]的伪随机整数。

math.randomseed()

用于设置伪随机数发生器的种子

取整

floor(向下取整)ceil(向上取整)modf(向零取整)

可以用浮点值与零进行按位或运算,将浮点值强制转换为整型值

image-20220203154955309

或用math.tointeger(),当参数含有小数或超出2^53时返回nil

字符串

与python相同,字符串是不可变量,可以用#获取字符串的长度,可以用..拼接字符串,可以用单引号或双引号创建字符串,与python相同

三种方式

image-20220203172336366

\ddd\xhh\u{h...h}

多行字符

1
2
3
4
5
6
7
8
9
10
11
12
13
14
page=[[
1
2
3
4
]]
--或
--两个中括号间等号数量相同
page=[====[
1
2
3
4
]====]

\z跳过所有空白字符

类型转换

tonumber()将字符串转换为数值

1
tonumber("100101",2)--可以使用2到36指明任意进制

tostring()将数值转换为字符串

字符库方法

1
2
3
4
5
6
7
8
9
10
string.rep(s,n)
string.len(s)
string.upper(s)
string.lower(s)
string.reverse(s)
string.sub(s,i,j)--索引字符串中从i到j的字符,包括第i个和第j个,下标从1开始,最后一个为-1,=
string.char(97)
string.byte("abc")--返回第一个字符的数值表示
string.byte("abc",i)--返回第i个字符的数值表示
string.byte("abc",i,j)--返回第i到j个字符的数值表示

格式化字符串

1
string.format("%x",a)--格式与c语言printf类似,x代表十六进制整数

s是一个字符串,可以用s:sub(i,j)来代替string.sub(s,i,j)

string.find(“hello world”,”wor”)寻找子串

string.gsub(“hello world”,”l”,”.”)替换子串

utf8.char()utf8.codepoint()等价于string.char()string.byte()

utf8.codepoint()中的位置采用的是字节索引,可以用utf8.offset()获取字符在字符串中的索引

utf8.codes()

1
2
3
4
a={}
a["x"]=10
a=nil
a.x==a["x"] --True
1
2
3
4
5
days={"Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"}
print(day[4]) --Wednesday
a={x=10,y=20}
--等价于
a={};a.x=10;a.y=20
1
{x=0,y=0}--{["x"]=0,["y"]=0}

可以使用#获取序列(索引为{1,n}形成的表,值为nil的键实际不在表中)的长度

可以用pairs()遍历表中的元素,不过出现的键值对随机

1
2
3
4
> for k,v in pairs(arg) do
>> print(k,v)
>> end
0 lua

对于列表,可以用ipairs()

1
2
3
4
5
6
7
> for u,v in ipairs(t) do
>> print(u,v)
>> end
1 10
2 function: 0000000065b9cff0
3 12
4 hi

遍历一定是按照顺序进行的

表标准库

1
2
3
4
5
6
table.insert(t,1,x)--在列表第一个位置插入x
table.insert(t,x)--在列表最后插入x
table.remove(t)--删除列表最后一个元素
table.remove(t,x)--删除列表第x个元素
table.move(a,f,e,t)--将a表中从f到e的元素移动到t位置上
table.move(a,f,e,t,b)--将上述元素移动到b表中

函数

当函数参数只有一个且为字符串或表构造器时,括号可选

1
2
print"HelloWorld"
type{}

当输入参数不够时,其他的参数被赋值为nil,当输入的参数过多时,多余的参数被丢弃

当一个函数作为表达式的最后一个参数时才会返回所有的返回值,否则只会返回第一个值,如

1
2
3
4
5
6
function foo()
return "a","b"
end
x,y,z=foo(),20
print(x,y,z)
a 20 nil

将函数调用用一个圆括号括起来可以强制只返回一个结果

...表示可变长度参数

1
2
3
4
5
6
7
8
9
function sum(...)
local s=0
for _,v in ipairs{...} do
s=s+v
end
return s
end
print(sum(3,4,5,6,7,8,9))
42

此外,还可用table.pack(...)返回一个表,这个表中保存了参数n

还可用select,select返回selector后的所有参数,当selector为#号时,返回额外参数的总数

1
2
3
print(select(1,"a","b","c")) --a b c
print(select(2,"a","b","c")) --b c
print(select("#","a","b","c")) --3

还有一个函数为table.unpack()与table.pack()相反,其参数时一个数组,返回数组中的所有元素

1
table.unpack({"sun","mon","tue","wed"},2,3) --mon tue

尾调用

尾调用是指在一个函数的结尾递归调用一个函数,此后不进行任何操作,称为尾调用

1
2
3
function test()
return g(x)
end

好处是无论递归多少层,栈都不会溢出

输入输出

io.write()可以读取任意数量的字符串并将其写入到当前输入流,可以有多个参数,应避免使用io.write(a..b..c),而是使用io.write(a,b,c)

io.read()

参数 作用
“a” 读取整个文件
“l” 读取下一行(丢弃换行符)
“L” 读取下一行(保留换行符)
“n” 读取一个数值
num 以字符串读取num个字符

io.read(0)是一个特例,用于测试是否到达了末尾,如果没有到达末尾,返回空字符串,若到达了末尾,返回nil

io.open()打开文件,与C语言相同,r只读,w只写,a附加

可以用io.input()io.output()设置输入流和输出流

打开文件

可以使用io.open()打开文件,有两个参数,一个参数是打开的文件的名称,另一个是模式,r,w,a,b,若打开错误返回nil和错误码

1
2
3
local f=assert(io.open(filename,"r"))
local t=f:read("a")
f:close()

io.popen("command","mode")这个函数有两个参数,第一个为在命令行所执行的指令,第二个为模式,可以为r(读取)或w(写入)

其他知识

lua变量默认是全局变量,局部变量使用前必须用local声明,在交互模式下每行代码就是个代码段,所以要想连续输入多行代码,可以将其放入do...end

控制结构

if...then...else...end

1
2
3
4
5
6
7
8
if a<0 then
a=0
end
if a<b then
return a
else
return b
end

if...then...elseif...then...else...end

while

1
2
3
4
5
local i=1
while a[i] do
print(a[i])
i=i+1
end

repeat...until...

1
2
3
4
5
local line
repeat
line=io.read()
until line~=""
print(line)

循环内声明的变量作用域包括until后面

for

1
2
3
for var=exp1,exp2,exp3 do
something
end

初始exp1,结束exp2,步长exp3[可选],默认步长为1,若不想设置上限可以使用常量math.huge

goto

标签格式为:::label::

1
2
3
4
5
a=1
goto test
a=2
::test::
print(a)