今天我们继续学习Lua语法基础教程,下篇。

9.4 函数返回值

在前面的代码中,我们实现了一个函数,输入变量a、b,函数会自动输出两个数值的和。

但是一般来说,我们的需求远远不止这些,我们可能需要一个如下功能的函数:

执行函数,输入两个值,获取这两个值的和

如果还是按上面几节的内容,我们只会输出这个值,并不能把这个值传递给其他的变量进行后续使用,如何解决这个需求呢?

我们可以使用函数的返回值来实现这个需求,结合上面的需求,我们可以用下面的代码实现:

 

function add(a,b)

return a+b

end

all = add(1,2)

--这里all的值就是3了

print(all)

这里的return表示返回一个值,并且立刻结束这个函数的运行

同时,和输入值可以有多个一样,返回值也可以有多个

 

function add(a,b)

return a+b,"ok"

end

all, result = add(1,2)

--这里all的值就是3了

--这里result的值就是string "ok"

print(all,result)

下面问题来了,请设计一个函数p,可以按下面的调用方式来返回出物体的密度,返回值为number类型:

 

function p(a,b,c,m)

--请补全代码

end

--一个长方体的长宽高分别为a、b、c(单位米)

a = 1

b = 2

c = 3

--这个物体重量为m(单位克)

m = 230

--下面返回密度值

--注:密度计算公式 密度 = 质量 / 体积

result = p(a,b,c,m)

print(result)

9.5 判断三角形合法性2(自测题)

你需要使用前面几章的知识,来完成下面的题目

  • 已知三个number类型的变量,分别代表三根木棒的长度

  • 请判断,使用这三根木棒,是否可以组成一个三角形(两短边之和大于第三边)

  • 请新建一个函数triangle,并可以用如下形式调用(如果可以组成,就返回true):

 

function triangle(a,b,c)

--请补全代码

end

result = triangle(1,2,3)--传入值为三边长度,多改几个测试下

print(result)

9.6 返回多个值(自测题)

你需要使用前面几章的知识,来完成下面的题目

  • 已知2个number类型的变量,分别代表一个长方体的长和宽

  • 请计算这个长方形的周长和面积

  • 请新建一个函数rectangle,并可以用如下形式调用:

 

function rectangle(a,b)

--补全代码

end

area,len = rectangle(1,2)

--结果:

--面积area为2

--周长len为6

print(area,len)

十、table

10.1 认识数组

数组,使用一个变量名,存储一系列的值

很多语言中都有数组这个概念,在Lua中,我们可以使用table(表)来实现这个功能

在Lua中,table是一个一系列元素的集合,使用大括号进行表示,其中的元素之间以逗号分隔,类似下面的代码:

 

t = {1,3,8,5,4}

我们可以直接使用元素的下标,来访问、或者对该元素进行赋值操作。

在上面的table变量t中,第一个元素的下标是1,第二个是2,以此类推。

我们可以用变量名+中括号,中括号里加上下标,来访问或更改这个元素,如下面的例子:

 

t = {1,3,8,5,4}

print(t[1]) --打印1

print(t[3]) --打印8

t[2] = 99 --更改第二个元素的值

print(t[2]) --打印99

t[6] = 2 --凭空新建第六个元素并赋值

print(t[6]) --打印2

print(t[10])

--因为不存在,打印nil

以上就是table最简单的一个例子了,就是当作数组来用(注意,一般语言中的数组基本都为不可变长度,这里的table为可变长度)

下面你需要完成:

  • 新建一个table,名为cards,存入1-10十个数字

  • 将第3个元素与第7个元素交换

  • 将第9个元素与第2个元素交换

  • 增加第11个变量,值为23

 

--请补全代码

cards =

10.2 简单table

上一节里,我们将table来表示数组,实际上,table中可以包括任意类型的数据

比如我们可以在table中放置number和string数据,类似下面的代码:

 

t = {"abc",223,",..a",123123}

我们甚至能在里面放function变量

 

t = {

function() return 123 end,

function() print("abc") end,

function(a,b) return a+b end,

function() print("hello world") end,

}

t[1]()

t[2]()

t[3](1,2)

t[4]()

这些table访问每个元素的方式仍然是直接用下标,并且也能用下标来进行修改

下面你需要完成:

  • 新建一个table,名为funcList,并实现以下功能

  • 调用funcList[1](a,b),返回a和b的乘积

  • 调用funcList[2](a,b),返回a减b的差

  • 调用funcList[3](a),返回a的相反数(-a)

 

--请补全代码

funcList = {

}

a,b = 1,2--提供两个数

print("a,b值为",a,b)

print("a和b的乘积:",funcList[1](a,b))

print("a和b的差:",funcList[2](a,b))

print("a和相反数:",funcList[3](a))

10.3 table下标

在前两节,我们的table都只是一些简单的List(列表),每个元素的下标都是自动从1排列的

实际上,Lua中,下标可以直接在声明时进行指定,像下面这样:

 

t = {6,7,8,9}

--上面和下面的代码等价

t = {

[1] = 6,

[2] = 7,

[3] = 8,

[4] = 9,

}

--甚至你可以跳过某些下标

t = {

[1] = 6,

[3] = 7,

[5] = 8,

[7] = 9,

}

print(t[7])

--输出9

--在声明后赋予元素值也是可以的

t = {}--空的table

t[101] = 10

print(t[101])

--输出10

下面你需要:

  • 新建一个变量t,并按下面的格式声明

  • 下标为1的元素,值为123(number)

  • 下标为13的元素,值为"abc"(string)

  • 下标为666的元素,值为"666"(string)

 

--请补全代码

t = {

}

print("下标为1的元素:",t[1],type(t[1]))

print("下标为13的元素:",t[13],type(t[13]))

print("下标为666的元素:",t[666],type(t[666]))

10.4 下标进阶

在上一节,我们学习了如何自定义下标,其实在Lua中,下标也可以是字符串,如下面的例子

 

t = {

["apple"] = 10,

banana = 12,

pear = 6,

}

--使用["下标"] = 值

--和  下标 = 值

--都是正确写法

--当第二种方式有歧义时,应该用第一种方式

--可以用下面两种方式访问:

print(t["apple"])

--输出10

print(t.apple)

--输出10

--当第二种方式有歧义时,应该用第一种方式

可见,在使用string作为下标时,table的灵活性提升了一个数量级。

string作为下标时,也可以动态赋值:

 

t = {} -- 空table

t["new"] = "新的值"

print(t.new)

--输出 新的值

下面你需要完成:

  • 新建table变量t

  • 下标为apple的元素,值为123(number)

  • 下标为banana的元素,值为"abc"(string)

  • 下标为1@1的元素,值为"666"(string)

 

--请补全代码

t = {

}

print("下标为apple的元素:",t["apple"],type(t["apple"]))

print("下标为banana的元素:",t["banana"],type(t["banana"]))

print("下标为1@1的元素:",t["1@1"],type(t["1@1"]))

10.5 table小测验

下面的代码,将会打印什么?

 

t = {

apple = {

price = 7.52,

weight = 2.1,

},

banana = {

price = 8.31,

weight = 1.4,

year = '2018'

},

year = '2019'

}

print(

t.price,

t.apple.price,

t.banana.weight,

t.year

)

10.6 table小测验2

下面的代码,将会打印什么?

 

t = {

{

price = 7.52,

weight = 2.1,

},

{

price = 8.31,

weight = 1.4,

year = '2018'

},

year = '2019'

}

print(

t["price"],

t[1].price,

t[2].weight,

t["year"]

)

10.7 Lua全局变量与table

在前面我们知道了,在table中,可以直接用table名[下标]或table名.string下标来访问元素

实际上,在Lua中,所有的全局变量全部被存放在了一个大table中,这个table名为:_G

我们可以用下面的例子来示范:

 

n = 123--新建变量

print(n)--输出123

print(_G.n)--输出123

_G.abc = 1--相当于新建全局变量

print(abc)--输出1

_G["def"] = 23--相当于新建全局变量

print(def)--输出23

--甚至你可以像下面这样

_G.print("hello")

_G["print"]("world")

现在,你明白为什么说万物基于table了吧?

你需要完成下面的任务:

  • 已知有一个全局变量,名为@#$

  • 请新建一个变量result

  • 将@#$变量里的值赋值给result

 

_G["@#$"] = 123

result = --请补全代码

print("result值为",result)

10.8 table小测试3

请新建一个名为t的table,满足以下要求

  • t[10]可获得number类型数据100

  • t.num可获得number类型数据12

  • t.abc[3]可获得string类型数据abcd

  • t.a.b.c可获得number类型数据789

 

--请补全代码

t = {

}

print("t[10]可获得number类型数据100:",t[10],type(t[10]))

print("t.num可获得number类型数据12:",t.num,type(t.num))

print("t.abc[3]可获得string类型数据abcd:",t.abc[3],type(t.abc[3]))

print("t.a.b.c可获得number类型数据789:",t.a.b.c,type(t.a.b.c))

10.9 table.concat

table.concat (table [, sep [, i [, j ] ] ])

将元素是string或者number类型的table,每个元素连接起来变成字符串并返回。

可选参数sep,表示连接间隔符,默认为空。

i和j表示元素起始和结束的下标。

下面是例子:

 

local a = {1, 3, 5, "hello" }

print(table.concat(a))

print(table.concat(a, "|"))

-->打印的结果:

--135hello

--1|3|5|hello

请完成下面的任务:

  • 已知table变量t,

  • 将t中的结果全部连起来

  • 间隔符使用,

  • 并使用print打印出来

 

t = {"a","b","c","d"}

print("连接结果:")

--补全代码

10.10 table删减

table.insert (table, [pos ,] value)

在(数组型)表 table 的 pos 索引位置插入 value,其它元素向后移动到空的地方。pos 的默认值是表的长度加一,即默认是插在表的最后。

table.remove (table [, pos])

在表 table 中删除索引为 pos(pos 只能是 number 型)的元素,并返回这个被删除的元素,它后面所有元素的索引值都会减一。pos 的默认值是表的长度,即默认是删除表的最后一个元素。

下面是例子:

 

local a = {1, 8}             --a[1] = 1,a[2] = 8

table.insert(a, 1, 3)   --在表索引为1处插入3

print(a[1], a[2], a[3])

table.insert(a, 10)    --在表的最后插入10

print(a[1], a[2], a[3], a[4])

-->打印的结果:

--3    1    8

--3    1    8    10

local a = { 1, 2, 3, 4}

print(table.remove(a, 1)) --删除速索引为1的元素

print(a[1], a[2], a[3], a[4])

print(table.remove(a))   --删除最后一个元素

print(a[1], a[2], a[3], a[4])

-->打印的结果:

--1

--2    3    4    nil

--4

--2    3    nil    nil

请完成下面的任务:

  • 已知table变量t,

  • 去除t中的第一个元素

  • 然后这时,在t的第三个元素前,加上一个number变量,值为810

 

t = {1,2,3,4,5,6,7,8,9}

--补全代码

print("第一个元素应为2:",t[1])

print("第三个元素应为810:",t[3])

十一、循环

11.1 while循环

在实际功能实现中,经常会遇到需要循环运行的代码,比如从1到100填充table数据,我们可以直接用循环语句来实现

我们首先来学习while这个循环语法,整体的格式如下:

 

while 继续循环判断依据 do

执行的代码

end

下面举一个例子,我们计算从1加到100的结果:

 

local result = 0

local num = 1

while num <= 100 do

result = result + num

num = num + 1

end

print(result)

上面的代码,就是当num≤100时,result不断地加num,并且num每次循环后自己加1

理解了上面的代码,我们来完成下面一个简单的任务吧:

  • 已知两个number类型的变量min和max

  • 请计算从min与max之间,所有3的倍数的和

  • 打印出结果

 

min,max = 114,514 --这个结果应为42009

result = 0--结果存放到这个变量

while 请完善 do

--补全代码

end

print("结果:",result)

11.2 for循环

for循环在某些程度上,和while循环很相似,但是for循环可以更加简洁地表达中间累积的量

我们首先来学习for这个循环语法,整体的格式如下:

 

for 临时变量名=开始值,结束值,步长 do

循环的代码

end

其中,步长可以省略,默认为1

临时变量名可以直接在代码区域使用(但不可更改),每次循环会自动加步长值,并且在到达结束值后停止循环

下面举一个例子,我们计算从1加到100的结果:

 

local result = 0

for i=1,100 do

result = result + i

end

print(result)

上面的代码,就是当i≤100时,result不断地加i,并且i每次循环后增加1

理解了上面的代码,我们来完成下面一个简单的任务吧:

  • 已知两个number类型的变量min和max

  • 请计算从min与max之间,所有7的倍数的和

  • 打印出结果

 

min,max = 114,514 --这个结果应为17955

result = 0--结果存放到这个变量

for --补全代码

print("结果:",result)

11.3 中断循环

前面我们学习了循环语句,有些时候循环运行到一半,我们不想再继续运行了,怎么办呢?

我们可以在一个循环体中使用break,来立即结束本次循环,继续运行下面的代码

比如像下面这样,计算1-100相加途中,小于100的最大的和:

 

result = 0

for i=1,100 do

result = result + i

if result > 100 then

result = result - i

break

end

end

print(result)

可以看见,当发现和大于100后,代码立即把result的值还原到了加上当前数字之前的状态,并且调用break语句,立即退出了本次循环

在while中,我们也可以使用break:

 

result = 0

c = 1

while true do

result = result + c

if result > 100 then

result = result - c

break

end

c = c + 1

end

print(result)

我们在这里直接使用了死循环(因为while的继续运行判断依据始终为true),整体逻辑也和之前for的代码一致,当发现和大于100后,代码立即把result的值还原到了加上当前数字之前的状态,并且调用break语句,立即退出了本次循环

现在你需要完成一项任务:

  • 请求出小于变量max的13的倍数的最大值(max大于0)

  • 并将结果打印出来

  • 本题理论上不用循环就能实现,但是为了练习一下技巧,请用for循环来实现

 

max = 810 --结果应为806

result = 0

for --请补全代码

print(result)

11.4 循环测试题1(自测题)

前面我们学习了循环语句,我们需要完成下面的任务

我们知道,print函数可以打印一行完整的输出

那么,已知变量a,请打印出下面的结果:

(a为大于0的整数,且需要输出a行数据,数据从1开始,每行与上一行的差为2)

1

3

5

7

9

(上面例子为当a为5的情况)

做题区域:

a = 10

--需要用print输出要求的结果

print("输出结果:")

for --请补全代码

11.5 循环测试题2(自测题)

我们需要完成下面的任务

那么,已知变量a,请打印出下面的结果:

(a为大于0的整数,且需要输出a行数据,第一行为一个,后面每行多一个)

 

*

**

***

****

*****

(上面例子为当a为5的情况)

做题区域:

 

a = 10

--需要用print输出要求的结果

print("输出结果:")

for --请补全代码

11.6 循环测试题3(自测题)

我们需要完成下面的任务

那么,已知变量a,请打印出下面的结果:

(a为大于0的整数,且需要输出a行数据,按图示规律输出)

 

1

12

123

1234

12345

123456

1234567

12345678

123456789

12345678910

1234567891011

(上面例子为当a为11的情况)

做题区域:

 

a = 20

--需要用print输出要求的结果

print("输出结果:")

for --请补全代码

11.7 循环测试题4(自测题)

  • 有一只猴子,第一天摘了若干个桃子 ,当即吃了一半,但还觉得不过瘾 ,就又多吃了一个。

  • 第2天早上又将剩下的桃子吃掉一半,还是觉得不过瘾,就又多吃了两个。

  • 以后每天早上都吃了前一天剩下的一半加天数个(例如,第5天吃了前一天剩下的一半加5个)。

  • 到第n天早上再想吃的时候,就只剩下一个桃子了。

  • 那么,已知变量a为最后一天的天数,请打印出第一天的桃子数。

  • 如:a为5时,输出114

做题区域:

 

a = 6

--需要用print输出要求的结果

print("输出结果:")

for --请补全代码

十二、详解string库

12.1 string.sub

接下来几节会讲解string库的各种接口

 

string.sub(s, i [, j])

返回字符串 s 中,从索引 i 到索引 j 之间的子字符串。

i 可以为负数,表示倒数第几个字符。

当 j 缺省时,默认为 -1,也就是字符串 s 的最后位置。

当索引 i 在字符串 s 的位置在索引 j 的后面时,将返回一个空字符串。

下面是例子:

 

print(string.sub("Hello Lua", 4, 7))

print(string.sub("Hello Lua", 2))

print(string.sub("Hello Lua", 2, 1))

print(string.sub("Hello Lua", -3, -1))

-->打印的结果:

lo L

ello Lua

Lua

值得注意的是,我们可以使用冒号来简化语法,像下面这样:

 

s = "12345"

s1 = string.sub(s, 4, 7)

s2 = s:sub(4, 7)

--两种写法是等价关系

print(s1,s2)

请完成下面的任务:

  • 已知字符串变量s,请分别打印出(每种一行):

  • s从第4个字符开始,到最后的值

  • s从第1个字符开始,到倒数第3个字符的值

  • s从倒数第5个字符开始,到倒数第2个字符的值

 

s = "1919810"

--补全代码

print()

print()

print()

12.2 string.rep

string.rep(s, n)

返回字符串 s 的 n 次拷贝。

示例代码:

 

print(string.rep("abc", 3))

--输出结果:

--abcabcabc

请完成下面的任务:

打印一行数据,数据内容为810个114514

 

--补全代码

print()

12.3 string.len

string.len(s)

接收一个字符串,返回它的长度。

示例代码:

 

s = "hello lua"

print(string.len(s))

--输出结果:

9

--同时也可以使用简便语法

print(s:len())

请完成下面的任务:

  • 新建一个变量s,使数据内容为810个114514

  • 并打印出字符串s的长度

 

s = --补全代码

print()

12.4 大小写转换

string.lower(s)

接收一个字符串 s,返回一个把所有大写字母变成小写字母的字符串。

string.upper(s)

接收一个字符串 s,返回一个把所有小写字母变成大写字母的字符串。

示例代码:

 

s = "hello lua"

print(string.upper(s))

print(string.lower(s))

--输出结果:

HELLO LUA

hello lua

--同时也可以使用简便语法

print(s:upper())

print(s:lower())

请完成下面的任务:

已知一个变量s,打印出全是大写字母的s字符串

 

s = "asd8938KJjsidiajdl;(()k)"

print --补全代码

12.5 string.format

string.format(formatstring, ...)

按照格式化参数formatstring,返回后面...内容的格式化版本。

编写格式化字符串的规则与标准 c 语言中 printf 函数的规则基本相同:

它由常规文本和指示组成,这些指示控制了每个参数应放到格式化结果的什么位置,及如何放入它们。

一个指示由字符%加上一个字母组成,这些字母指定了如何格式化参数,例如d用于十进制数、x用于十六进制数、o用于八进制数、f用于浮点数、s用于字符串等。

示例代码:

 

print(string.format("%.4f", 3.1415926))     -- 保留4位小数

print(string.format("%d %x %o", 31, 31, 31))-- 十进制数31转换成不同进制

d,m,y = 29,7,2015

print(string.format("%s %02d/%02d/%d", "today is:", d, m, y))

--控制输出2位数字,并在前面补0

-->输出

-- 3.1416

-- 31 1f 37

-- today is: 29/07/2015

请完成下面的任务:

  • 已知一个变量n,为number类型整数

  • 打印出n:连上n值的字符串

 

n = 810

print --补全代码

12.6 string的本质

这一节我们来讲解字符串的本质

字符串,是用来存储一串字符的,但是它的本质就是一串数字。如何用一串数字来代表一串字符呢?

在计算机中,每一个符号都对应着一个数字,但是在讲解这个知识之前,我们了解一下补充知识:

 

在大多数编程语言中,我们使用0x开头来表示这个数字是16进制的。

比如

10等价于0x0a

256等价于0xff

接下来,你需要了解,每一个符号都对应着一个数字,比如:

0对应着0x30、1对应着0x31 a对应着0x61、b对应着0x62 A对应着0x41、B对应着0x42

上面的编码规则,我们称之为ascii码,具体想了解可以打开下面的网址查看:http://ascii.911cha.com/

当然,1字节最大为0xff,即256,只能存下一部分符号,大部分的中文按某些编码,一个中文占用2或3个字节

计算机如何解析这些数据,我们不需要了解,当你知道了上面的知识后,你应该可以理解下面的描述:

 

字符串"apple"实际上的内容就是下面的一串数字:

0x61,0x70,0x70,0x6c,0x65

同时,lua的字符串中可以保存任何数值,即使是0x00这种不代表任何含义的数,也可以保存

 

补充:在其他语言中(如C),0x00代表字符串结束,但是在lua中并不是这样。

lua的字符串每字节可以存储任意的一字节数据。

比如下面的描述:

 

有一串lua字符串中的数据为:

0x01,0x02,0x30,0x00,0x44

实际人能看到的(不可见字符用�代替):

��0�D

当然,你不能说你看不见的数据就不存在,他们都完好无损地在这个字符串中

下面你需要思考一个问题:一串字符串数据如下,它的实际内容是什么(指人能看见的字符串内容,如abcd)?

0x62,0x61,0x6e,0x61,0x6e,0x61

12.7 string.char

string.char (...)

接收 0 个或更多的整数(整数范围:0~255),返回这些整数所对应的 ASCII 码字符组成的字符串。当参数为空时,默认是一个 0。

如果上一章节有认真学习过了的话,这段话应该是很好理解的。实质上就是把计算机认识的一串数字,变成字符串变量,并且字符串内的数据就是要存的那串数据。

示例代码:

 

str1 = string.char(0x30,0x31,0x32,0x33)

str2 = string.char(0x01,0x02,0x30,0x03,0x44)

print(str1)

print(str2)

-->输出(不可见字符用�代替)

--0123

--��0�D

请完成下面的任务:

  • 已知一个字符串的每个字符在数组t中按顺序排列

  • 请根据t的值,打印出字符串内容(一行数据)

  • 注:这个字符串存储的不一定是可见的字符

 

t = {0x79,0x6F,0x75,0x20,0x61,0x72,0x65,0x20,0x72,0x69,0x67,0x68,0x74}

print("真正的字符串内容:")

--补全代码

12.8 string.byte

string.byte(s [, i [, j ] ])

返回字符 s[i]、s[i + 1]、s[i + 2]、······、s[j] 所对应的 ASCII 码。i 的默认值为 1,即第一个字节,j 的默认值为 i 。

这个函数功能刚好和前面的string.char相反,是提取字符串中实际的数值。

示例代码:

 

str = "12345"

print(string.byte(str,2))

print(str:byte(2))--也可以这样

print(str:byte())--不填默认是1

-->输出(十进制数据)

--50

--50

--49

请完成下面的任务:

  • 已知字符串s

  • 请把s中代表的数据,全部相加,并打印出来

 

s = string.char(1,2,3,4,5,6,7,8,9)

print("s内数据的和是:")

--补全代码

12.9 string.find

string.find(s, p [, init [, plain] ])

这个函数会在字符串s中,寻找匹配p字符串的数据。如果成功找到,那么会返回p字符串在s字符串中出现的开始位置和结束位置;如果没找到,那么就返回nil。

第三个参数init默认为1,表示从第几个字符开始匹配,当init为负数时,表示从s字符串的倒数第-init个字符处开始匹配。

第四个参数plain默认为false,当其为true时,只会把p看成一个字符串对待。

可能你会奇怪,第四个参数有什么存在的必要吗?p不是本来就应该是个字符串吗? 实际上,lua中的匹配默认意义是正则匹配,同时,这里的正则与其它语言也有些许不同。

由于篇幅有限,本节和下面的几节涉及匹配内容时,均不会考虑正则的使用方法,Lua正则教程将会在最后几节单独详细地列出来。

第四个参数为true时,便不会使用正则功能。

示例代码:

 

--只会匹配到第一个

print(string.find("abc abc", "ab"))

-- 从索引为2的位置开始匹配字符串:ab

print(string.find("abc abc", "ab", 2))

-- 从索引为5的位置开始匹配字符串:ab

print(string.find("abc abc", "ab", -3))

-->输出

--1  2

--5  6

--5  6

请完成下面的任务:

  • 已知字符串s,里面有很多相同的字符串

  • 请找出字符串s中,所有字符串awsl的位置

  • 使用print打印结果,结果一行一个

  • 如字符串12awslawslaw,输出3和7

 

s = "12awsaslwlaawsllslllswasllalssawwlawslaw"

print("两个awsl的位置分别是:")

--补全代码

12.10 string.gsub

string.gsub(s, p, r [, n])

将目标字符串s中所有的子串p替换成字符串r。

可选参数n,表示限制替换次数。

返回值有两个,第一个是被替换后的字符串,第二个是替换了多少次。

特别提示:这个函数的目标字符串s,也是支持正则的

下面是例子:

 

print(string.gsub("Lua Lua Lua", "Lua", "hello"))

print(string.gsub("Lua Lua Lua", "Lua", "hello", 2)) --指明第四个参数

-->打印的结果:

-- hello hello hello   3

-- hello hello Lua     2

同样的,我们也可以使用冒号来简化语法,像下面这样:

 

s = "12345"

r = s:gsub("2","b")

print(r)

请完成下面的任务:

  • 已知字符串变量s,请分别打印出(每种一行):

  • 把字符串s中,前5个a,替换为b

  • 把字符串s中,前3个c,替换为xxx

  • 把结果打印出来,一行数据

 

s = "asdicagydausckfugdaflgscdabgsdbahhacbshbsd"

print("s变换前的值:",s)

--补全代码

十三、跨文件调用

在编写代码时,随着逻辑逐渐复杂,我们的代码量也会变大。虽然有函数可以把一部分代码逻辑封装起来,但是所有代码都放到一个文件里,显然也不是个好办法。

所以我们需要将一些代码放到不同文件中,通过文件来区分这些代码的功能。

比如我们有下面这个函数:

 

---函数功能:

-- 生成从1-max的table

-- @输入值:table的最大值

-- @返回:  table结果

-- @例子:  local list = getNumberList(10)

function getNumberList(max)

local t = {}

for i=1,max do

table.insert(t,i)

end

return t

end

我们新建一个文件叫tools.lua,把这个函数放进去,现在,整个文件如下面这样:

tools.lua

 

---函数功能:

-- 生成从1-max的table

-- @输入值:table的最大值

-- @返回:  table结果

-- @例子:  local list = getNumberList(10)

local function getNumberList(max)

local t = {}

for i=1,max do

table.insert(t,i)

end

return t

end

--手动返回一个table,包含了上面的函数

return {

getNumberList = getNumberList,

}

现在,我们封装的这个函数就能在其他文件里被调用了,具体代码如下:

 

--引用tools.lua文件,并加载

local tool = require("tools")

local list = tool.getNumberList(12)

当调用了require接口后,Lua虚拟机会自动加载你调用的文件,执行文件的内容,然后返回你文件里return的结果。

为了更好地理解这段话,我们可以看下面两个文件,其中run.lua是被运行的那个入口文件

test.lua

 

--以便一会儿返回使用的table

local temp = {}

--把全局变量a更改了

a = 1

--local变量无法被外部调用

--但是可以在文件内被调用

local b = 2

--文件在被require的时候,会被执行

--把全局变量c更改了

c = a + b

--使函数在table里

function temp.addB()

--文件内部可以调用变量b

b = b + 1

return b

end

--返回table

return temp

run.lua

 

local test = require("test")

print(a)--输出1

print(b)--输出nil,因为b是local变量

print(c)--输出3

print(test.addB())--输出3

print(test.addB())--输出4

print(test.addB())--输出5

同时,每个文件最多只会被require一次,如果有多个require,只有第一次会执行。

条理清晰,浅显易懂:Lua语法技术知识详解(第三部分)的更多相关文章

  1. Cisco路由技术基础知识详解

    第一部分 请写出568A的线序(接触网络第一天就应该会的,只要你掐过,想都能想出来) .网卡MAC地址长度是(  )个二进制位(16进制与2进制的换算关系,只是换种方式问,不用你拿笔去算) A.12  ...

  2. Markdown语法说明(详解版)

    ####date: 2016-05-26 20:38:58 tags: Markdown tags && Syntax ##Markdown语法说明(详解版)杨帆发表于 2011-11 ...

  3. 前端技术之_CSS详解第三天

    前端技术之_CSS详解第三天 二.权重问题深入 2.1 同一个标签,携带了多个类名,有冲突: <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 ...

  4. RabbitMQ,Apache的ActiveMQ,阿里RocketMQ,Kafka,ZeroMQ,MetaMQ,Redis也可实现消息队列,RabbitMQ的应用场景以及基本原理介绍,RabbitMQ基础知识详解,RabbitMQ布曙

    消息队列及常见消息队列介绍 2017-10-10 09:35操作系统/客户端/人脸识别 一.消息队列(MQ)概述 消息队列(Message Queue),是分布式系统中重要的组件,其通用的使用场景可以 ...

  5. Python基础知识详解 从入门到精通(七)类与对象

    本篇主要是介绍python,内容可先看目录其他基础知识详解,欢迎查看本人的其他文章Python基础知识详解 从入门到精通(一)介绍Python基础知识详解 从入门到精通(二)基础Python基础知识详 ...

  6. 新手入门:史上最全Web端即时通讯技术原理详解

    前言 有关IM(InstantMessaging)聊天应用(如:微信,QQ).消息推送技术(如:现今移动端APP标配的消息推送模块)等即时通讯应用场景下,大多数都是桌面应用程序或者native应用较为 ...

  7. Web端即时通讯技术原理详解

    前言 有关IM(InstantMessaging)聊天应用(如:微信,QQ).消息推送技术(如:现今移动端APP标配的消息推送模块)等即时通讯应用场景下,大多数都是桌面应用程序或者native应用较为 ...

  8. nginx入门与实战 安装 启动 配置nginx Nginx状态信息(status)配置 正向代理 反向代理 nginx语法之location详解

    nginx入门与实战 网站服务 想必我们大多数人都是通过访问网站而开始接触互联网的吧.我们平时访问的网站服务 就是 Web 网络服务,一般是指允许用户通过浏览器访问到互联网中各种资源的服务. Web ...

  9. RabbitMQ基础知识详解

    什么是MQ? MQ全称为Message Queue, 消息队列(MQ)是一种应用程序对应用程序的通信方法.MQ是消费-生产者模型的一个典型的代表,一端往消息队列中不断写入消息,而另一端则可以读取队列中 ...

  10. L009文件属性知识详解小节

    本堂课分为5部分内容 1.linux下重要目录详解 2.PATH变量路径内容 3.linux系统中文件类型介绍 4.linux系统中文件属性详细介绍 5.linux系统文件属性inode与block知 ...

随机推荐

  1. JavaScript设计模式样例二十 —— 中介者模式

    中介者模式(Mediator Pattern) 定义:用来降低多个对象和类之间的通信复杂性.目的:用一个中介对象来封装一系列的对象交互,中介者使各对象不需要显式地相互引用,从而使其耦合松散,而且可以独 ...

  2. 【工程应用十一】基于PatchMatch算法的图像修复研究(inpaint)。

      这个东西是个非常古老的算法了,大概是2008年的东西,参考资料也有很多,不过基本上都是重复的.最近受一个朋友的需求,前后大概用了二十多天时间去研究,也有所成果,在这里简单的予以记录.    图像修 ...

  3. Kafka Topic 中明明有可拉取的消息,为什么 poll 不到

    开心一刻 今天小学女同学给我发消息她:你现在是毕业了吗我:嗯,今年刚毕业她给我发了一张照片,怀里抱着一只大橘猫她:我的眯眯长这么大了,好看吗我:你把猫挪开点,它挡住了,我看不到她:你是 sb 吗,滚我 ...

  4. CD、VCD、DVD、BD 傻傻分不清楚?

    CD 激光唱片(Compact Disk, CD),于 1982 年面世,最初用于存储数字音频.容量约 700 MB(80 分钟音频). 激光唱片 | 维基百科 VCD 影音光盘(Video Comp ...

  5. Seata 1.3.0 Oracle 回滚测试验证 报错 ORA-02289: 序列不存在

    使用Seata 1.3.0版本,测试A服务调用B服务,且A方法中,手动写了一个异常,测试是否正常回滚(Mysql已经测试过) 发现报错:ORA-02289: 序列不存在 一看就是undo_log这张表 ...

  6. springboot 大文件切片上传

    1. 前端(vue element ui & 原生) 初始变量声明: currentFile: {}, // 当前上传的文件 bigFileSliceCount: 20, // 大文件切片后的 ...

  7. Dash 2.18版本新特性介绍

    本文示例代码已上传至我的Github仓库:https://github.com/CNFeffery/dash-master Gitee同步仓库地址:https://gitee.com/cnfeffer ...

  8. elementUI 时间线居左显示

    elementUI 时间线居左显示 一.vue + elementUI 实现时间线 Timellne 中时间戳居左显示 二.效果图 三.实现方法 关键代码: <el-timeline> & ...

  9. JavaScript – 类型转换

    介绍 JS 是弱类型语言, 在编程时, 有许多自动类型转换的技巧, 虽然大家都不太鼓励, 尤其是用了 TypeScript 之后, 但无可否认自动转换很方便, 看上去也很干净. 所以这篇还是要介绍一些 ...

  10. SQL Server 冗余维护

    介绍 冗余是维护的魔鬼, 是性能优化的天使 常见的冗余有 1. computed column 2. principal 的识别字段 3. cross computed 4. cascade soft ...