首页 > 其他分享 >Lua语法基础教程(下篇)

Lua语法基础教程(下篇)

时间:2024-10-26 10:42:22浏览次数:1  
标签:下篇 string -- Lua 字符串 result 基础教程 print table

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

九、函数

9.1 初识函数

函数是指一段在一起的、可以做某一件事儿的程序,也叫做子程序。

在前面的内容中,我们已经接触过了函数的调用,这个函数就是前面用到了很多次的print(...)。

调用函数只需要按下面的格式即可:

函数名(参数1,参数2,参数3,......)

为何要使用函数?因为很多事情都是重复性操作,我们使用函数,可以快速完成这些操作

下面我们举一个最简单的函数例子,这个函数没有传入参数、没有返回值

它实现了一个简单的功能,就是输出Hello world!:

 

function hello()

   print('Hello world!')

end

这个函数名为hello,我们可以按下面的方法进行调用(执行):

 

function hello()

   print('Hello world!')

end

hello()

这行代码会输出Hello world!。

同时,在Lua中,函数也是一种变量类型,也就是说,hello实际上也是一个变量,里面存储的是一个函数,我们可以用下面的代码来理解:

 

function hello()

   print('Hello world!')

end

a = hello

--把hello函数同时赋值给a变量

a()

hello()

--a和hello变量指向同一个函数

--所以执行结果和hello()相同

因为函数只是个变量,你甚至在一开始可以这样声明hello函数:

 

hello = function()

   print('Hello world!')

end

hello()

下面你需要做一件简单的事情:

  • 新建一个函数变量biu,使其执行后会打印biubiubiu这个字符串

  • 新建一个函数变量pong,使其与biu指向的函数相同

 

--请在此处补全代码

--请使下面的调用可以正常打印出biubiubiu

biu()

pong()

print("biu和pong相等吗?",biu==pong)

9.2 local变量

之前我们创建的变量,都是全局变量,这种变量在代码运行周期从头到尾,都不会被销毁,而且随处都可调用。

但是当我们代码量增加,很多时候大量新建全局变量会导致内存激增,我们需要一种可以临时使用、并且可以自动销毁释放内存资源的变量,要怎么解决呢?

我们可以使用local标志来新建临时变量,使用local创建一个局部变量,与全局变量不同,局部变量只在被声明的那个代码块内有效。

参考下面的代码:

 

a = 123

function add()

   local n = a+2

   print(n)

end

add()

print(n)

上面的代码中,n就是一个局部变量,它只在这个funcion中有效,并且函数运行完后会自动回收这部分的内存。

我们应该尽可能的使用局部变量,以方便lua虚拟机自动回收内存空间,同时减少资源占用提高运行速度。

下面请阅读以下代码,思考一下,正确的输出结果是什么:

 

str = 'abc'

function connect()

   local s = str..'def'

end

print(s,str)

9.3 函数参数

在前几章的使用中,我们知道函数是可以传入参数的,如print(123)

那么,我们如何编写可以传入参数的函数呢?可以按下面的模板来写

 

function 函数名(参数1,参数2,...)

   代码内容

end

这里传入的参数,等价于在函数内部新建了一个local的变量,修改这些数据不会影响外部的数据(除了后面还没有讲到的table等类型)

举个例子,比如下面的函数,可以实现打印出两个传入值的和:

 

function add(a,b)

   print(a+b)

end

add(1,2)

--会输出3

这段代码其实等价于:

 

function add()

   local a = 1

   local b = 2

   print(a+b)

end

add()

下面问题来了,请设计一个函数p,可以按下面的调用方式来打印出物体的密度:

 

--补全这个函数的代码,满足题目要求

function p(a,b,c,m)

   print()

end

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

a = 1

b = 2

c = 3

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

m = 230

--下面打印出密度

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

p(a,b,c,m)

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,只有第一次会执行。

标签:下篇,string,--,Lua,字符串,result,基础教程,print,table
From: https://www.cnblogs.com/luatos/p/18503745

相关文章

  • Altium Designer 入门基础教程(六)
    本文章继续接着《Altium Designer入门基础教程(五)》的内容往下介绍:七、AD画板的整个流程步骤 L.板层数和设计规则的设置a.板层数的设置开始画板前,根据板框大小和元器件的多少可以大概评估一下要用到几层板,先设置好层数,再开始布局画板工作;或者在布局画板的过程中,发现实在......
  • Altium Designer 入门基础教程(七)
    本文章继续接着《Altium Designer入门基础教程(六)》的内容往下介绍: M.元器件的布局布线设计规则设置完成之后,就开始元器件的布局与布线。把整个原理图的元器件拖到板框上方,然后选中红色框框区域删除掉。把输入法切换到美式键盘   设置布局栅格,一般默认即可  a......
  • 【优选算法】——滑动窗口(下篇)
    目录1、水果成篮2、找到字符串中所有字母异位词3、串联所有单词的子串4、最小覆盖子串1、水果成篮你正在探访一家农场,农场从左到右种植了一排果树。这些树用一个整数数组 fruits 表示,其中 fruits[i] 是第 i 棵树上的水果 种类 。你想要尽可能多地收集水果......
  • Java-继承与多态-下篇
    ......
  • 【JVM神秘大门】Java虚拟机原理保姆式教学,零基础速成GC机制(下篇)
    本篇会加入个人的所谓鱼式疯言❤️❤️❤️鱼式疯言:❤️❤️❤️此疯言非彼疯言而是理解过并总结出来通俗易懂的大白话,小编会尽可能的在每个概念后插入鱼式疯言,帮助大家理解的.......
  • Windows系统lua51.dll文件丢失?Windows用户必看lua51.dll文件丢失的解决之道
    当Windows系统中的lua51.dll文件丢失时,可能会导致依赖它的软件或游戏无法正常运行。以下是一些针对Windows用户解决lua51.dll文件丢失问题的详细步骤:一、使用系统文件检查器(SFC)打开管理员命令行:按下Windows键+X,选择“命令提示符(管理员)”或“WindowsPowerShell(管理员)”。运......
  • H7-TOOL的LUA小程序教程第15期:电压,电流,NTC热敏电阻以及4-20mA输入(2024-10-21,已经发布
    LUA脚本的好处是用户可以根据自己注册的一批API(当前TOOL已经提供了几百个函数供大家使用),实现各种小程序,不再限制Flash里面已经下载的程序,就跟手机安装APP差不多,所以在H7-TOOL里面被广泛使用,支持在线调试运行,支持离线运行。TOOL的LUA教程争取做到大家可以无痛调用各种功能函数,不需......
  • Altium Designer 入门基础教程(一)
     有将近一个半月没有更新过博客了,最近在整理AltiumDesigner 入门基础教程,希望喜欢本系列教程的小伙伴可以点点关注和订阅!下面我们开始进入AltiumDesigner课程的介绍。一、AltiumDesigner快捷键1.原理图快捷键: 2.PCB快捷键:  3.自定义快捷键(原理图、......
  • Lua与C#交互原理
    c#调用lua,是c#通过Pinvoke(Platform Invoke (平台调用))方式调用了lua的底层的C代码,然后这个执行了lua脚本。如果一个C#方法要被Lua调用,则首先要将其注册到Lua虚拟机中。如果C#要调用Lua中的函数,则首先要在Lua虚拟机中加载该函数(LuaState.DoFile)。拿到目标函数(LuaState.Ge......
  • 在Lua中实现Rust对象的绑定tT
    合集-算法(7)1.TimerWheel(计时轮)在Rust中的实现及源码解析06-122.Rust性能分析之测试及火焰图,附(lru,lfu,arc)测试06-183.Lru-k在Rust中的实现及源码解析06-214.带有ttl的Lru在Rust中的实现及源码解析06-24:westworld加速5.Lfu缓存在Rust中的实现及源码解析06-276.Rust宏之der......