Lua学习笔记(总结Runoob.com)
概述
- 文章是对Rounoob.com所有的Lua文章进行学习的个人总结笔记,有些是Runoob.com抄写的内容,主要是自己看来一遍,把里面的东西都实现了,然后手打了一遍知识点,进行迁移到这里,由于文章比较长,所以对其进行拆分,这是第一篇。上篇主要内容有编译环境、基本语法数据类型、变量、循环、流程控制、函数、运算符、字符串、数组
一、基础
1、编译环境
-
使用源码包,并在终端解压编译后即可使用
-
在windows上面可以直接使用安装包进行安装,安装后得到两个exe,一个是控制台、一个是文本编辑器
2、基本语法
-
交互式编程
- 直接在命令行输入然后直接查看结果
-
脚本试编程
- 使用lua结尾的文件,进行执行即可编译
-
注释
- 单行注释使用
--
- 多行注释
--[[多行注释]]
- 单行注释使用
-
标识符
- 标识符用于定义个变量、函数获取其他用户定义的项,由:字母、下划线、数字组成
- 必须字母或下划线开头
- 最好不要使用下划线加大写字母,因为Lua保留字也是这样的
- 不允许出现特殊字符来定义标识符
-
关键词
- 不能作为变量、常量或其他用户自定义标识符
- 一般约定,以下划线开头链接大写字母的名字(如:_VERSION)被保留用于Lua内部全局变量。
-
全局变量
-
默认情况下,变量都是全局的。
-
全局变量不需要声明,给变量赋值后即成为全局变量,访问没有初始化的变量也不会报错,只会显示为nil。
-
如果需要删除一个全局变量直接使它赋值为nil。
-
当且仅当变量不等于nil时,这个变量即存在
print(b) -- nil b = 10 print(b) --10 b = nil print(b) --nil
-
3、数据类型
- Lua是动态类型语言,变量不要类型定义,只需要为变量赋值。值可以存储在变量中,作为参数传递或者结果返回。
- Lua中有8种基本类型分别为nil,boolean,number,string,userdata,function,thread,table
数据类型 | 描述 |
---|---|
nil | 只有值nil属于该类型,表示一个无效值(在条件表达式中相当于false) |
boolean | 包含两个值:false和true |
number | 表示双精度类型的实浮点数 |
string | 字符串类型 由一对引号或单引号来表示 |
function | 由C或Lua编程的函数 |
userdata | 表示任意存储在变量中的C数据结构 |
thread | 表示执行的独立线路,用于执行协同程序 |
table | Lua中的表(table)其实是一个“关联数组(associative arrays),数组的索引可以是数字(索引从1开始),或者是字符串,table的创建是通过”构造表达式“来完成的,最简单的构造表达式是{},用来表示创建一个空表 |
print(type("Hello world")) --> string
print(type(10.4*3)) --> number
print(type(print)) --> function
print(type(type)) --> function
print(type(true)) --> boolean
print(type(nil)) --> nil
print(type(type(X))) --> string
-
nil 表示一种没有任何有效值,对于全局变量和table来说nil还有一个“删除”的作用,nil作为比较时应该加上
“ ”
-
bolean(布尔),只有两个值true和false,Lua把false和nil看做为“假”
-
number(数字)默认只有一种类型为double类型,也可以在luaconf.h里面修改默认类型
-
string(字符串)
- string (字符串)由一对双引号或单引号来表示,
- 也可以使用
[[表示一块字符串]]
,在对数字字符串上进行算术操作时,Lua会先尝试将数字字符串转成一个数字, - 使用#号来计算字符串长度,放在字符串前面
-
table(表)
-
通过“构造表达式”来完成,最简单的构造表达式为{}表示创建一个空表,也可在里面添加数据,直接初始化表
-
表其实是一个“关联数组”数组的索引可以是数字或者字符串
-
Lua的索引从1开始
-
table不会固定长度,有新数据添加时table长度会自动增长。
a = {} a["key"] = "value" key = 10 a[key] = 22 a[key] = a[key] + 11 for k ,v in pairs(a)do print(k.. ":" .. v) end
-
-
function(函数)
- 函数被看做“第一类值(First_Class Value),函数可以存在变量里
- function可以是匿名函数(amonymous function)的方式通过参数传递
二、变量、循环、流程控制
1、变量
-
变量在使用前,必须在代码中进行声明,即创建变量
-
编译程序执行代码之前编译器需要知道如何给语句变量开辟存储区,用于存储变量
-
Lua变量有三种:全局变量、局部变量、表中的域。
-
Lua中的变量全是全局变量,语句块或者函数里也是,除非用local显示声明为局部变量。
-
局部变量的作用域为从声明位置开始到语句块结束。
-
变量默认值为nil
a = 5 --全局变量 local a = 5 --局部变量 function joke() c =5 --全局变量 local d = 6 --局部变量 end joke() print(c,d) -->5 nil do local a = 6 --局部变量 b = 6 --对局部变量重新赋值 print(a,b); -->6 6 end print(a,b) -->5 6
-
赋值语句
-
赋值是改变一个变量的值和改变表域的最基本的方法
a = "hellow" .. "world" ; t.n = t,n +1
-
也可以对多个变量同时赋值,变量列表和值列表的各个元素用逗号分开,赋值语句会依次赋给左边的变量
a,b = 10,2x -->a = 10;b =2*x
-
遇到赋值语句会计算右边所有的值,然后在执行赋值操作。
x,y = y,x --swap 'x' for 'y' a[i],a[j] = a[j]a[i] --swap'a[i]' for 'a[j]'
-
当变量个数不一致的时候,会以变量个数为基础采取
A、变量个数 > 值的个数 按变量个数不足nil B、变量个数 < 值的个数 多余的值会被忽略
-
多值赋值经常用来交换变量,或将函数调用返回变量
a,b = f()
f()返回两个值,第一个赋值给a,第二个赋值给b, -
应该尽可能的使用局部变量,
- 可以避免命名冲突
- 访问局部变量的速度比全局变量更快
-
-
索引
-
对于table的索引使用方括号[]
t[i] t.i --当索引为字符串类型的时的一种简化写法 gettable_event(t,i) --采用索引访问本质上是一个类似这样的函数调用
-
2、循环
循环类型 | 描述 |
---|---|
while循环 | 在条件为true时,让程序重复执行某些语句,执行语句前会先检查条件是否为true |
for循环 | 重复执行指定语句,重复次数可在for语句中控制 |
repeat …until | 重复执行循环,知道指定条件为真时为止 |
嵌套循环 | 可以在循环内嵌套一个或多个循环语句(while do,for do end,repeat…unitl |
-
while循环
- while 循环语句在判断条件为 true 时会重复执行循环体语句。
while(condition) --condition(条件)可以是任意表达式,在condition为true时执行循环体 do statements -- 可以是一条或者多条语句 end -- condition为false时会跳过当前循环并开始执行end后面的语句
-
for循环
-
主要分为数值for循环和泛型for循环
- 数值型for循环
for var = exp1,exp2,exp3 do -- var从从 exp1 变化到 exp2,每次变化以 exp3 为步长递增 var,并执行一次 "执行体"。exp3 是可选的,如果不指定,默认为1。 <执行体> end -- 三个表达式在循环开始前一次性求值,以后不再进行求值,
- 泛型for循环
- 泛型for循环通过一个迭代器函数来遍历所有值,类似C#里面的foreach语句
-- 打印数组a的所有值 a {"one","two","three"} for i,v in ipairs (a)do -- i是数组索引值,v是对于索引的数组元素值,ipairs是lua提供的一个迭代函数,用来迭代数组 print(i,v) end
-
-
Lua repeat…until 循环
- repeat…until 循环语句不同于 for 和 while循环,for 和 while 循环的条件语句在当前循环执行开始时判断,而 repeat…until 循环的条件语句在当前循环结束后判断。类似C# do while
repeat stantements until(condition) --判断condition在末尾,所以在条件进行判断前循环体都会执行一次,若果条件条件判断语句(condition)为 false,循环会重新开始执行,直到条件判断语句(condition)为 true 才会停止执行。
-
嵌套循环
-
for循环嵌套语法
for init,max/min value,increment do for init,max/min value,increment do statements end statements end
-
while循环嵌套循环
while(condition) do while(condition) do statements end statements end
-
repeat…until循环嵌套语法
repeat statements repeat statements until(condition) until(condition)
-
当然也可以三个循环中不同之间的嵌套也是可以的
-
-
循环控制语句
-
用于控制程序的流程,以实现程序的各种结构方式
控制语句 描述 break语句 退出当前循环或语句,并开始脚本执行紧接着的语句
-
-
无限循环
-
循环体一直执行
while(true) do print("循环将永远执行下去") end
-
3、流程控制
-
条件为 true 时执行指定程序代码,在条件为 false 时执行其他指定代码。Lua认为false和nil为假,true和非nil为真。**在Lua中0为true。
语句 描述 if语句 if 语句 由一个布尔表达式作为条件判断,其后紧跟其他语句组成。 if…else语句 if 语句 可以与 else 语句搭配使用, 在 if 条件表达式为 false 时执行 else 语句代码。 if嵌套语句 你可以在if 或 else if中使用一个或多个 if 或 else if 语句 。
三、函数、运算符、字符串、数组
1、函数
-
函数是对语句和表达式进行抽象的主要方法,可以用来做一些特殊处理,也可以计算一些值
-
主要有两个用图
-
完成指定的任务,这种情况下函数作为语句使用
-
计算并返回值,这种情况下函数作为赋值语句和表达式使用
-- 函数的定义格式如下 optional_function_scope function function_name(argument1,argument2,argument3....,atgumentn) function_body return result_oprams_comma_separated end -- optional_function_scope:该产生是可选的指定函数是全局函数还是局部函数,未设置的时候默认为全局函数,如果需要设置为局部函数则使用local -- function_name:指定函数的名字 --argument1,argument2,argument3....,atgumentn:函数参数,用逗号隔开,可以不设置 -- result_oprams_comma_separated:函数返回值,可以多个返回值,每个用逗号隔开 --我们还可以将函数作为参数传递给函数
-
-
多返回值
- 可以返回多个值,如果有些值不存在则返回nil
-
可变参数
-
在函数列表中使用三个点…表示函数有可变的参数
-
我们也可以将函数赋值给一个变量
-
同时也可以通过select(“#”,…)来获取可变函数的数量
-
我们可能需要几个固定参数加上可变参数,固定参数必须放在可变参数之前
-
通常在遍历变长参数的时候只需要使用 {…},然而变长参数可能会包含一些 nil,那么就可以用 select 函数来访问变长参数了:**select(’#’, …)**或者 select(n, …)
-
- select(’#’, …) 返回可变参数的长度
- select(n, …) 用于访问 n 到 select(’#’,…) 的参数
-
调用select时,必须传入一个固定实参selector(选择开关)和一系列变长参数。如果selector为数字n,那么select返回它的第n个可变实参,否则只能为字符串"#",这样select会返回变长参数的总数
-
2、运算符
-
主要分为:算术云算符、关系运算符、逻辑云算符、其他运算符
-
算法云算符
操作符 描述 实例 + 加法 A + B 输出结果 30 - 减法 A - B 输出结果 -10 * 乘法 A * B 输出结果 200 / 除法 B / A w输出结果 2 % 取余 B % A 输出结果 0 ^ 乘幂 A^2 输出结果 100 - 负号 -A 输出结果v -10 -
关系运算符
操作符 描述 实例 == 等于,检测两个值是否相等,相等返回 true,否则返回 false (A == B) 为 false。 ~= 不等于,检测两个值是否相等,相等返回 false,否则返回 true (A ~= B) 为 true。 > 大于,如果左边的值大于右边的值,返回 true,否则返回 false (A > B) 为 false。 < 小于,如果左边的值大于右边的值,返回 false,否则返回 true (A < B) 为 true。 >= 大于等于,如果左边的值大于等于右边的值,返回 true,否则返回 false (A >= B) 返回 false。 <= 小于等于, 如果左边的值小于等于右边的值,返回 true,否则返回 false (A <= B) 返回 true。 -
逻辑运算符
操作符 描述 实例 and 逻辑与操作符。 若 A 为 false,则返回 A,否则返回 B。 (A and B) 为 false。 or 逻辑或操作符。 若 A 为 true,则返回 A,否则返回 B。 (A or B) 为 true。 not 逻辑非操作符。与逻辑运算结果相反,如果条件为 true,逻辑非为 false。 not(A and B) 为 true。 -
其他运算符
操作符 描述 实例 … 连接两个字符串 a…b ,其中 a 为 "Hello " , b 为 “World”, 输出结果为 “Hello World”。 # 一元运算符,返回字符串或表的长度。 #“Hello” 返回 5 -
运算符优先级
- 终极法则——加括号
3、字符串
1、三种表现
-
单引号间的一串字符。
-
双引号间的一串字符。
-
[[和]]间的一串字符。
-
转义字符
转义字符 意义 ASCII码值(十进制) \a 响铃(BEL) 007 \b 退格(BS) ,将当前位置移到前一列 008 \f 换页(FF),将当前位置移到下页开头 012 \n 换行(LF) ,将当前位置移到下一行开头 010 \r 回车(CR) ,将当前位置移到本行开头 013 \t 水平制表(HT) (跳到下一个TAB位置) 009 \v 垂直制表(VT) 011 \ 代表一个反斜线字符’’’ 092 ’ 代表一个单引号(撇号)字符 039 " 代表一个双引号字符 034 \0 空字符(NULL) 000 \ddd 1到3位八进制数所代表的任意字符 三位八进制 \xhh 1到2位十六进制所代表的任意字符 二位十六进制
2、字符串操作
方法 | 用途 |
---|---|
string.upper(argument) | 字符串全部转为大写字母 |
string.lower(atgument) | 字符串全部转为小写字母 |
string.gsub(main String,find String,replace String ,num) | 在字符串中替换mainString为要替换的字符串,findString为被替换的字符,replaceString要替换的字符串,num替换的次数(可忽略,则为替换全部) |
string.find (str, substr, [init, [end]]) | 在一个指定的目标字符串中搜索指定的内容(第三个参数为索引),返回其具体位置。不存在则返回 nil。 |
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) | string.match()只寻找源字串str中的第一个配对. 参数init可选, 指定搜寻过程的起点, 默认为1。 在成功配对时, 函数将返回配对表达式中的所有捕获结果; 如果没有设置捕获标记, 则返回整个配对字符串. 当没有成功的配对时, 返回nil。 |
3、字符串格式化
- 跟C语言中的printf()类似
4、匹配模式
-
用于模式匹配函数 string.find, string.gmatch, string.gsub, string.match。
你还可以在模式串中使用字符类。
5、三个实用字符串操作
--阿拉伯站位汉字
local function NumToCN(num)
local size = #tostring(num)
local CN = ""
local StrCN = {"一","二","三","四","五","六","七","八","九"}
for i = 1 , size do
CN = CN .. StrCN[tonumber(string.sub(tostring(num), i , i))]
end
return CN
end
print(NumToCN(56665))
-- 移除中文
--function StrSplit(inputstr,sep)
function StrSplit(inputstr, sep)
if sep == nil then
sep = "%s"
end
local t = {}
local i = 1
for str in string.gmatch(inputstr,"([^"..sep.."]+)")do
t[i] = str
i = i+1
end
return t
end
local a = "312343242,莫莫"
local b = ":"
b = StrSplit(a,",")
print(b[1])
-- 去除字符串首位的空格
function trim(s)
return (string.gsub(s,"^%s*(.-)%s*$","%1"))
end
string6 = " Runoob"
string7 = trim(string6)
print (string7)
4、数组
1、相同数据类型的元素按一定顺序排列的集合,可以是一维数组和多维数组
- 数组的索引键值可以只用整数表示,数组的大小是不固定的
2、一维数组
-
一维数组的逻辑结构是线性表,可以用for循环读取里面所有的数据
-
数组索引从1开始,但是也可以手动设置为0开始,也可以动态的赋值,从负数开始也可以
array = {} for i = -2,2 do array[i] = i *2 end for i = -2,2 do print(array[i]) end
3、多维数组
-
数组中包含数组或者一维数组的索引键对应一个数组
--初始化数组 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 --不同索引键的三行三列阵多维数组 --初始化数组 array1 = {} maxRows = 3 maxColumns = 3 for row = 1,maxRows do for col =1 ,maxColumns do array1[row*maxColumns + col] = row * col end end --访问数组 for row = 1,maxRows do for col = 1, maxColumns do print (array1[row*maxColumns + col]) end end
- 上面最后一个实例中,数组设定了指定的索引值,这样可以避免出现nil值,有利于节省内存空间