0
  • 聊天消息
  • 系統(tǒng)消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會員中心
創(chuàng)作中心

完善資料讓更多小伙伴認識你,還能領取20積分哦,立即完善>

3天內(nèi)不再提示

Lua語法基礎教程(下篇)

合宙LuatOS ? 2024-10-26 11:41 ? 次閱讀

今天我們繼續(xù)學習Lua語法基礎教程,下篇。

九、函數(shù)

9.1 初識函數(shù)

函數(shù)是指一段在一起的、可以做某一件事兒的程序,也叫做子程序。

在前面的內(nèi)容中,我們已經(jīng)接觸過了函數(shù)的調(diào)用,這個函數(shù)就是前面用到了很多次的print(...)。

調(diào)用函數(shù)只需要按下面的格式即可:

函數(shù)名(參數(shù)1,參數(shù)2,參數(shù)3,......)

為何要使用函數(shù)?因為很多事情都是重復性操作,我們使用函數(shù),可以快速完成這些操作

下面我們舉一個最簡單的函數(shù)例子,這個函數(shù)沒有傳入?yún)?shù)、沒有返回值

它實現(xiàn)了一個簡單的功能,就是輸出Hello world!:


function hello()

print('Hello world!')

end

這個函數(shù)名為hello,我們可以按下面的方法進行調(diào)用(執(zhí)行):


function hello()

print('Hello world!')

end

hello()

這行代碼會輸出Hello world!。

同時,在Lua中,函數(shù)也是一種變量類型,也就是說,hello實際上也是一個變量,里面存儲的是一個函數(shù),我們可以用下面的代碼來理解:


function hello()

print('Hello world!')

end

a = hello

--把hello函數(shù)同時賦值給a變量

a()

hello()

--a和hello變量指向同一個函數(shù)

--所以執(zhí)行結(jié)果和hello()相同

因為函數(shù)只是個變量,你甚至在一開始可以這樣聲明hello函數(shù):


hello = function()

print('Hello world!')

end

hello()

下面你需要做一件簡單的事情:

  • 新建一個函數(shù)變量biu,使其執(zhí)行后會打印biubiubiu這個字符串
  • 新建一個函數(shù)變量pong,使其與biu指向的函數(shù)相同

--請在此處補全代碼

--請使下面的調(diào)用可以正常打印出biubiubiu

biu()

pong()

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

9.2 local變量

之前我們創(chuàng)建的變量,都是全局變量,這種變量在代碼運行周期從頭到尾,都不會被銷毀,而且隨處都可調(diào)用。

但是當我們代碼量增加,很多時候大量新建全局變量會導致內(nèi)存激增,我們需要一種可以臨時使用、并且可以自動銷毀釋放內(nèi)存資源的變量,要怎么解決呢?

我們可以使用local標志來新建臨時變量,使用local創(chuàng)建一個局部變量,與全局變量不同,局部變量只在被聲明的那個代碼塊內(nèi)有效。

參考下面的代碼:


a = 123

function add()

local n = a+2

print(n)

end

add()

print(n)

上面的代碼中,n就是一個局部變量,它只在這個funcion中有效,并且函數(shù)運行完后會自動回收這部分的內(nèi)存。

我們應該盡可能的使用局部變量,以方便lua虛擬機自動回收內(nèi)存空間,同時減少資源占用提高運行速度。

下面請閱讀以下代碼,思考一下,正確的輸出結(jié)果是什么:


str = 'abc'

function connect()

local s = str..'def'

end

print(s,str)

9.3 函數(shù)參數(shù)

在前幾章的使用中,我們知道函數(shù)是可以傳入?yún)?shù)的,如print(123)

那么,我們?nèi)绾尉帉懣梢詡魅雲(yún)?shù)的函數(shù)呢?可以按下面的模板來寫


function 函數(shù)名(參數(shù)1,參數(shù)2,...)

代碼內(nèi)容

end

這里傳入的參數(shù),等價于在函數(shù)內(nèi)部新建了一個local的變量,修改這些數(shù)據(jù)不會影響外部的數(shù)據(jù)(除了后面還沒有講到的table等類型)

舉個例子,比如下面的函數(shù),可以實現(xiàn)打印出兩個傳入值的和:


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()

下面問題來了,請設計一個函數(shù)p,可以按下面的調(diào)用方式來打印出物體的密度:


--補全這個函數(shù)的代碼,滿足題目要求

function p(a,b,c,m)

print()

end

--一個長方體的長寬高分別為a、b、c(單位米)

a = 1

b = 2

c = 3

--這個物體重量為m(單位克)

m = 230

--下面打印出密度

--注:密度計算公式 密度 = 質(zhì)量 / 體積

p(a,b,c,m)

9.4 函數(shù)返回值

在前面的代碼中,我們實現(xiàn)了一個函數(shù),輸入變量a、b,函數(shù)會自動輸出兩個數(shù)值的和。

但是一般來說,我們的需求遠遠不止這些,我們可能需要一個如下功能的函數(shù):

執(zhí)行函數(shù),輸入兩個值,獲取這兩個值的和

如果還是按上面幾節(jié)的內(nèi)容,我們只會輸出這個值,并不能把這個值傳遞給其他的變量進行后續(xù)使用,如何解決這個需求呢?

我們可以使用函數(shù)的返回值來實現(xiàn)這個需求,結(jié)合上面的需求,我們可以用下面的代碼實現(xiàn):


function add(a,b)

return a+b

end

all = add(1,2)

--這里all的值就是3了

print(all)

這里的return表示返回一個值,并且立刻結(jié)束這個函數(shù)的運行

同時,和輸入值可以有多個一樣,返回值也可以有多個


function add(a,b)

return a+b,"ok"

end

all, result = add(1,2)

--這里all的值就是3了

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

print(all,result)

下面問題來了,請設計一個函數(shù)p,可以按下面的調(diào)用方式來返回出物體的密度,返回值為number類型:


function p(a,b,c,m)

--請補全代碼

end

--一個長方體的長寬高分別為a、b、c(單位米)

a = 1

b = 2

c = 3

--這個物體重量為m(單位克)

m = 230

--下面返回密度值

--注:密度計算公式 密度 = 質(zhì)量 / 體積

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

print(result)

9.5 判斷三角形合法性2(自測題)

你需要使用前面幾章的知識,來完成下面的題目

  • 已知三個number類型的變量,分別代表三根木棒的長度
  • 請判斷,使用這三根木棒,是否可以組成一個三角形(兩短邊之和大于第三邊)
  • 請新建一個函數(shù)triangle,并可以用如下形式調(diào)用(如果可以組成,就返回true):

function triangle(a,b,c)

--請補全代碼

end

result = triangle(1,2,3)--傳入值為三邊長度,多改幾個測試下

print(result)

9.6 返回多個值(自測題)

你需要使用前面幾章的知識,來完成下面的題目

  • 已知2個number類型的變量,分別代表一個長方體的長和寬
  • 請計算這個長方形的周長和面積
  • 請新建一個函數(shù)rectangle,并可以用如下形式調(diào)用:

function rectangle(a,b)

--補全代碼

end

area,len = rectangle(1,2)

--結(jié)果:

--面積area為2

--周長len為6

print(area,len)

十、table

10.1 認識數(shù)組

數(shù)組,使用一個變量名,存儲一系列的值

很多語言中都有數(shù)組這個概念,在Lua中,我們可以使用table(表)來實現(xiàn)這個功能

在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最簡單的一個例子了,就是當作數(shù)組來用(注意,一般語言中的數(shù)組基本都為不可變長度,這里的table為可變長度)

下面你需要完成:

  • 新建一個table,名為cards,存入1-10十個數(shù)字
  • 將第3個元素與第7個元素交換
  • 將第9個元素與第2個元素交換
  • 增加第11個變量,值為23

--請補全代碼

cards =

10.2 簡單table

上一節(jié)里,我們將table來表示數(shù)組,實際上,table中可以包括任意類型的數(shù)據(jù)

比如我們可以在table中放置number和string數(shù)據(jù),類似下面的代碼:


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,

}

t1

t2

t3

t4

這些table訪問每個元素的方式仍然是直接用下標,并且也能用下標來進行修改

下面你需要完成:

  • 新建一個table,名為funcList,并實現(xiàn)以下功能
  • 調(diào)用funcList1,返回a和b的乘積
  • 調(diào)用funcList2,返回a減b的差
  • 調(diào)用funcList3,返回a的相反數(shù)(-a)

--請補全代碼

funcList = {

}

a,b = 1,2--提供兩個數(shù)

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

print("a和b的乘積:",funcList1)

print("a和b的差:",funcList2)

print("a和相反數(shù):",funcList3)

10.3 table下標

在前兩節(jié),我們的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 下標進階

在上一節(jié),我們學習了如何自定義下標,其實在Lua中,下標也可以是字符串,如下面的例子


t = {

["apple"] = 10,

banana = 12,

pear = 6,

}

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

--和 下標 = 值

--都是正確寫法

--當?shù)诙N方式有歧義時,應該用第一種方式

--可以用下面兩種方式訪問:

print(t["apple"])

--輸出10

print(t.apple)

--輸出10

--當?shù)诙N方式有歧義時,應該用第一種方式

可見,在使用string作為下標時,table的靈活性提升了一個數(shù)量級。

string作為下標時,也可以動態(tài)賦值:


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"

現(xiàn)在,你明白為什么說萬物基于table了吧?

你需要完成下面的任務:

  • 已知有一個全局變量,名為@#$
  • 請新建一個變量result
  • 將@#$變量里的值賦值給result

_G["@#$"] = 123

result = --請補全代碼

print("result值為",result)

10.8 table小測試3

請新建一個名為t的table,滿足以下要求

  • t[10]可獲得number類型數(shù)據(jù)100
  • t.num可獲得number類型數(shù)據(jù)12
  • t.abc[3]可獲得string類型數(shù)據(jù)abcd
  • t.a.b.c可獲得number類型數(shù)據(jù)789

--請補全代碼

t = {

}

print("t[10]可獲得number類型數(shù)據(jù)100:",t[10],type(t[10]))

print("t.num可獲得number類型數(shù)據(jù)12:",t.num,type(t.num))

print("t.abc[3]可獲得string類型數(shù)據(jù)abcd:",t.abc[3],type(t.abc[3]))

print("t.a.b.c可獲得number類型數(shù)據(jù)789:",t.a.b.c,type(t.a.b.c))

10.9 table.concat

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

將元素是string或者number類型的table,每個元素連接起來變成字符串并返回。

可選參數(shù)sep,表示連接間隔符,默認為空。

i和j表示元素起始和結(jié)束的下標。

下面是例子:


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

print(table.concat(a))

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

-->打印的結(jié)果:

--135hello

--1|3|5|hello

請完成下面的任務:

  • 已知table變量t,
  • 將t中的結(jié)果全部連起來
  • 間隔符使用,
  • 并使用print打印出來

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

print("連接結(jié)果:")

--補全代碼

10.10 table刪減

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

在(數(shù)組型)表 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])

-->打印的結(jié)果:

--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])

-->打印的結(jié)果:

--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])

十一、循環(huán)

11.1 while循環(huán)

在實際功能實現(xiàn)中,經(jīng)常會遇到需要循環(huán)運行的代碼,比如從1到100填充table數(shù)據(jù),我們可以直接用循環(huán)語句來實現(xiàn)

我們首先來學習while這個循環(huán)語法,整體的格式如下:


while 繼續(xù)循環(huán)判斷依據(jù) do

執(zhí)行的代碼

end

下面舉一個例子,我們計算從1加到100的結(jié)果:


local result = 0

local num = 1

while num <= 100 do

result = result + num

num = num + 1

end

print(result)

上面的代碼,就是當num≤100時,result不斷地加num,并且num每次循環(huán)后自己加1

理解了上面的代碼,我們來完成下面一個簡單的任務吧:

  • 已知兩個number類型的變量min和max
  • 請計算從min與max之間,所有3的倍數(shù)的和
  • 打印出結(jié)果

min,max = 114,514 --這個結(jié)果應為42009

result = 0--結(jié)果存放到這個變量

while 請完善 do

--補全代碼

end

print("結(jié)果:",result)

11.2 for循環(huán)

for循環(huán)在某些程度上,和while循環(huán)很相似,但是for循環(huán)可以更加簡潔地表達中間累積的量

我們首先來學習for這個循環(huán)語法,整體的格式如下:


for 臨時變量名=開始值,結(jié)束值,步長 do

循環(huán)的代碼

end

其中,步長可以省略,默認為1

臨時變量名可以直接在代碼區(qū)域使用(但不可更改),每次循環(huán)會自動加步長值,并且在到達結(jié)束值后停止循環(huán)

下面舉一個例子,我們計算從1加到100的結(jié)果:


local result = 0

for i=1,100 do

result = result + i

end

print(result)

上面的代碼,就是當i≤100時,result不斷地加i,并且i每次循環(huán)后增加1

理解了上面的代碼,我們來完成下面一個簡單的任務吧:

  • 已知兩個number類型的變量min和max
  • 請計算從min與max之間,所有7的倍數(shù)的和
  • 打印出結(jié)果

min,max = 114,514 --這個結(jié)果應為17955

result = 0--結(jié)果存放到這個變量

for --補全代碼

print("結(jié)果:",result)

11.3 中斷循環(huán)

前面我們學習了循環(huán)語句,有些時候循環(huán)運行到一半,我們不想再繼續(xù)運行了,怎么辦呢?

我們可以在一個循環(huán)體中使用break,來立即結(jié)束本次循環(huán),繼續(xù)運行下面的代碼

比如像下面這樣,計算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)

可以看見,當發(fā)現(xiàn)和大于100后,代碼立即把result的值還原到了加上當前數(shù)字之前的狀態(tài),并且調(diào)用break語句,立即退出了本次循環(huán)

在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)

我們在這里直接使用了死循環(huán)(因為while的繼續(xù)運行判斷依據(jù)始終為true),整體邏輯也和之前for的代碼一致,當發(fā)現(xiàn)和大于100后,代碼立即把result的值還原到了加上當前數(shù)字之前的狀態(tài),并且調(diào)用break語句,立即退出了本次循環(huán)

現(xiàn)在你需要完成一項任務:

  • 請求出小于變量max的13的倍數(shù)的最大值(max大于0)
  • 并將結(jié)果打印出來
  • 本題理論上不用循環(huán)就能實現(xiàn),但是為了練習一下技巧,請用for循環(huán)來實現(xiàn)

max = 810 --結(jié)果應為806

result = 0

for --請補全代碼

print(result)

11.4 循環(huán)測試題1(自測題)

前面我們學習了循環(huán)語句,我們需要完成下面的任務

我們知道,print函數(shù)可以打印一行完整的輸出

那么,已知變量a,請打印出下面的結(jié)果:

(a為大于0的整數(shù),且需要輸出a行數(shù)據(jù),數(shù)據(jù)從1開始,每行與上一行的差為2)

1

3

5

7

9

(上面例子為當a為5的情況)

做題區(qū)域:

a = 10

--需要用print輸出要求的結(jié)果

print("輸出結(jié)果:")

for --請補全代碼

11.5 循環(huán)測試題2(自測題)

我們需要完成下面的任務

那么,已知變量a,請打印出下面的結(jié)果:

(a為大于0的整數(shù),且需要輸出a行數(shù)據(jù),第一行為一個,后面每行多一個)


**




(上面例子為當a為5的情況)

做題區(qū)域:


a = 10

--需要用print輸出要求的結(jié)果

print("輸出結(jié)果:")

for --請補全代碼

11.6 循環(huán)測試題3(自測題)

我們需要完成下面的任務

那么,已知變量a,請打印出下面的結(jié)果:

(a為大于0的整數(shù),且需要輸出a行數(shù)據(jù),按圖示規(guī)律輸出)


1

12

123

1234

12345

123456

1234567

12345678

123456789

12345678910

1234567891011

(上面例子為當a為11的情況)

做題區(qū)域:


a = 20

--需要用print輸出要求的結(jié)果

print("輸出結(jié)果:")

for --請補全代碼

11.7 循環(huán)測試題4(自測題)

  • 有一只猴子,第一天摘了若干個桃子 ,當即吃了一半,但還覺得不過癮 ,就又多吃了一個。
  • 第2天早上又將剩下的桃子吃掉一半,還是覺得不過癮,就又多吃了兩個。
  • 以后每天早上都吃了前一天剩下的一半加天數(shù)個(例如,第5天吃了前一天剩下的一半加5個)。
  • 到第n天早上再想吃的時候,就只剩下一個桃子了。
  • 那么,已知變量a為最后一天的天數(shù),請打印出第一天的桃子數(shù)。
  • 如:a為5時,輸出114

做題區(qū)域:


a = 6

--需要用print輸出要求的結(jié)果

print("輸出結(jié)果:")

for --請補全代碼

十二、詳解string庫

12.1 string.sub

接下來幾節(jié)會講解string庫的各種接口


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

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

i 可以為負數(shù),表示倒數(shù)第幾個字符。

當 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))

-->打印的結(jié)果:

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個字符開始,到倒數(shù)第3個字符的值
  • s從倒數(shù)第5個字符開始,到倒數(shù)第2個字符的值

s = "1919810"

--補全代碼

print()

print()

print()

12.2 string.rep

string.rep(s, n)

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

示例代碼:


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

--輸出結(jié)果:

--abcabcabc

請完成下面的任務:

打印一行數(shù)據(jù),數(shù)據(jù)內(nèi)容為810個114514


--補全代碼

print()

12.3 string.len

string.len(s)

接收一個字符串,返回它的長度。

示例代碼:


s = "hello lua"

print(string.len(s))

--輸出結(jié)果:

9

--同時也可以使用簡便語法

print(s:len())

請完成下面的任務:

  • 新建一個變量s,使數(shù)據(jù)內(nèi)容為810個114514
  • 并打印出字符串s的長度

s = --補全代碼

print()

12.4 大小寫轉(zhuǎn)換

string.lower(s)

接收一個字符串 s,返回一個把所有大寫字母變成小寫字母的字符串。

string.upper(s)

接收一個字符串 s,返回一個把所有小寫字母變成大寫字母的字符串。

示例代碼:


s = "hello lua"

print(string.upper(s))

print(string.lower(s))

--輸出結(jié)果:

HELLO LUA

hello lua

--同時也可以使用簡便語法

print(s:upper())

print(s:lower())

請完成下面的任務:

已知一個變量s,打印出全是大寫字母的s字符串


s = "asd8938KJjsidiajdl;(()k)"

print --補全代碼

12.5 string.format

string.format(formatstring, ...)

按照格式化參數(shù)formatstring,返回后面...內(nèi)容的格式化版本。

編寫格式化字符串的規(guī)則與標準 c 語言中 printf 函數(shù)的規(guī)則基本相同:

它由常規(guī)文本和指示組成,這些指示控制了每個參數(shù)應放到格式化結(jié)果的什么位置,及如何放入它們。

一個指示由字符%加上一個字母組成,這些字母指定了如何格式化參數(shù),例如d用于十進制數(shù)、x用于十六進制數(shù)、o用于八進制數(shù)、f用于浮點數(shù)、s用于字符串等。

示例代碼:


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

print(string.format("%d %x %o", 31, 31, 31))-- 十進制數(shù)31轉(zhuǎn)換成不同進制

d,m,y = 29,7,2015

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

--控制輸出2位數(shù)字,并在前面補0

-->輸出

-- 3.1416

-- 31 1f 37

-- today is: 29/07/2015

請完成下面的任務:

  • 已知一個變量n,為number類型整數(shù)
  • 打印出n:連上n值的字符串

n = 810

print --補全代碼

12.6 string的本質(zhì)

這一節(jié)我們來講解字符串的本質(zhì)

字符串,是用來存儲一串字符的,但是它的本質(zhì)就是一串數(shù)字。如何用一串數(shù)字來代表一串字符呢?

在計算機中,每一個符號都對應著一個數(shù)字,但是在講解這個知識之前,我們了解一下補充知識:


在大多數(shù)編程語言中,我們使用0x開頭來表示這個數(shù)字是16進制的。

比如

10等價于0x0a

256等價于0xff

接下來,你需要了解,每一個符號都對應著一個數(shù)字,比如:

0對應著0x30、1對應著0x31 a對應著0x61、b對應著0x62 A對應著0x41、B對應著0x42

上面的編碼規(guī)則,我們稱之為ascii碼,具體想了解可以打開下面的網(wǎng)址查看:http://ascii.911cha.com/

當然,1字節(jié)最大為0xff,即256,只能存下一部分符號,大部分的中文按某些編碼,一個中文占用2或3個字節(jié)

計算機如何解析這些數(shù)據(jù),我們不需要了解,當你知道了上面的知識后,你應該可以理解下面的描述:


字符串"apple"實際上的內(nèi)容就是下面的一串數(shù)字:

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

同時,lua的字符串中可以保存任何數(shù)值,即使是0x00這種不代表任何含義的數(shù),也可以保存


補充:在其他語言中(如C),0x00代表字符串結(jié)束,但是在lua中并不是這樣。

lua的字符串每字節(jié)可以存儲任意的一字節(jié)數(shù)據(jù)。

比如下面的描述:


有一串lua字符串中的數(shù)據(jù)為:

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

實際人能看到的(不可見字符用?代替):

??0?D

當然,你不能說你看不見的數(shù)據(jù)就不存在,他們都完好無損地在這個字符串中

下面你需要思考一個問題:一串字符串數(shù)據(jù)如下,它的實際內(nèi)容是什么(指人能看見的字符串內(nèi)容,如abcd)?

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

12.7 string.char

string.char (...)

接收 0 個或更多的整數(shù)(整數(shù)范圍:0~255),返回這些整數(shù)所對應的 ASCII 碼字符組成的字符串。當參數(shù)為空時,默認是一個 0。

如果上一章節(jié)有認真學習過了的話,這段話應該是很好理解的。實質(zhì)上就是把計算機認識的一串數(shù)字,變成字符串變量,并且字符串內(nèi)的數(shù)據(jù)就是要存的那串數(shù)據(jù)。

示例代碼:


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

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

print(str1)

print(str2)

-->輸出(不可見字符用?代替)

--0123

--??0?D

請完成下面的任務:

  • 已知一個字符串的每個字符在數(shù)組t中按順序排列
  • 請根據(jù)t的值,打印出字符串內(nèi)容(一行數(shù)據(jù))
  • 注:這個字符串存儲的不一定是可見的字符

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

print("真正的字符串內(nèi)容:")

--補全代碼

12.8 string.byte

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

返回字符 s[i]、s[i + 1]、s[i + 2]、······、s[j] 所對應的 ASCII 碼。i 的默認值為 1,即第一個字節(jié),j 的默認值為 i 。

這個函數(shù)功能剛好和前面的string.char相反,是提取字符串中實際的數(shù)值。

示例代碼:


str = "12345"

print(string.byte(str,2))

print(str:byte(2))--也可以這樣

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

-->輸出(十進制數(shù)據(jù))

--50

--50

--49

請完成下面的任務:

  • 已知字符串s
  • 請把s中代表的數(shù)據(jù),全部相加,并打印出來

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

print("s內(nèi)數(shù)據(jù)的和是:")

--補全代碼

12.9 string.find

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

這個函數(shù)會在字符串s中,尋找匹配p字符串的數(shù)據(jù)。如果成功找到,那么會返回p字符串在s字符串中出現(xiàn)的開始位置和結(jié)束位置;如果沒找到,那么就返回nil。

第三個參數(shù)init默認為1,表示從第幾個字符開始匹配,當init為負數(shù)時,表示從s字符串的倒數(shù)第-init個字符處開始匹配。

第四個參數(shù)plain默認為false,當其為true時,只會把p看成一個字符串對待。

可能你會奇怪,第四個參數(shù)有什么存在的必要嗎?p不是本來就應該是個字符串嗎? 實際上,lua中的匹配默認意義是正則匹配,同時,這里的正則與其它語言也有些許不同。

由于篇幅有限,本節(jié)和下面的幾節(jié)涉及匹配內(nèi)容時,均不會考慮正則的使用方法,Lua正則教程將會在最后幾節(jié)單獨詳細地列出來。

第四個參數(shù)為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中,所有字符串a(chǎn)wsl的位置
  • 使用print打印結(jié)果,結(jié)果一行一個
  • 如字符串12awslawslaw,輸出3和7

s = "12awsaslwlaawsllslllswasllalssawwlawslaw"

print("兩個awsl的位置分別是:")

--補全代碼

12.10 string.gsub

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

將目標字符串s中所有的子串p替換成字符串r。

可選參數(shù)n,表示限制替換次數(shù)。

返回值有兩個,第一個是被替換后的字符串,第二個是替換了多少次。

特別提示:這個函數(shù)的目標字符串s,也是支持正則的

下面是例子:


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

print(string.gsub("Lua Lua Lua", "Lua", "hello", 2)) --指明第四個參數(shù)

-->打印的結(jié)果:

-- 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
  • 把結(jié)果打印出來,一行數(shù)據(jù)

s = "asdicagydausckfugdaflgscdabgsdbahhacbshbsd"

print("s變換前的值:",s)

--補全代碼

十三、跨文件調(diào)用

在編寫代碼時,隨著邏輯逐漸復雜,我們的代碼量也會變大。雖然有函數(shù)可以把一部分代碼邏輯封裝起來,但是所有代碼都放到一個文件里,顯然也不是個好辦法。

所以我們需要將一些代碼放到不同文件中,通過文件來區(qū)分這些代碼的功能。

比如我們有下面這個函數(shù):


---函數(shù)功能:

-- 生成從1-max的table

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

-- @返回: table結(jié)果

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

function getNumberList(max)

local t = {}

for i=1,max do

table.insert(t,i)

end

return t

end

我們新建一個文件叫tools.lua,把這個函數(shù)放進去,現(xiàn)在,整個文件如下面這樣:

tools.lua


---函數(shù)功能:

-- 生成從1-max的table

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

-- @返回: table結(jié)果

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

local function getNumberList(max)

local t = {}

for i=1,max do

table.insert(t,i)

end

return t

end

--手動返回一個table,包含了上面的函數(shù)

return {

getNumberList = getNumberList,

}

現(xiàn)在,我們封裝的這個函數(shù)就能在其他文件里被調(diào)用了,具體代碼如下:


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

local tool = require("tools")

local list = tool.getNumberList(12)

當調(diào)用了require接口后,Lua虛擬機會自動加載你調(diào)用的文件,執(zhí)行文件的內(nèi)容,然后返回你文件里return的結(jié)果。

為了更好地理解這段話,我們可以看下面兩個文件,其中run.lua是被運行的那個入口文件

test.lua


--以便一會兒返回使用的table

local temp = {}

--把全局變量a更改了

a = 1

--local變量無法被外部調(diào)用

--但是可以在文件內(nèi)被調(diào)用

local b = 2

--文件在被require的時候,會被執(zhí)行

--把全局變量c更改了

c = a + b

--使函數(shù)在table里

function temp.addB()

--文件內(nèi)部可以調(diào)用變量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,只有第一次會執(zhí)行。

聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場。文章及其配圖僅供工程師學習之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問題,請聯(lián)系本站處理。 舉報投訴
  • 函數(shù)
    +關注

    關注

    3

    文章

    4263

    瀏覽量

    62250
  • Lua
    Lua
    +關注

    關注

    0

    文章

    78

    瀏覽量

    10517
收藏 人收藏

    評論

    相關推薦

    基于Core的Lua編程語言相關資料分享

    十分鐘上手基于Core的Lua編程語言一、函數(shù)、變量二、數(shù)組、表(table)三、流程控制:if、elseif、else四、循環(huán)控制:for、while五、結(jié)語前言:無論您擅長什么語言,C
    發(fā)表于 01-18 07:30

    光耦新手入門必讀下篇

    光耦新手入門必讀下篇
    發(fā)表于 07-21 10:08 ?1652次閱讀

    MOC3041的應用下篇

    MOC3041的應用下篇
    發(fā)表于 08-06 12:15 ?1.5w次閱讀
    MOC3041的應用<b class='flag-5'>下篇</b>

    Programming in Lua 3ed

    Lua語言的編程學習手冊。Lua是一個小巧的腳本語言。Lua腳本可以很容易的被C/C++ 代碼調(diào)用,也可以反過來調(diào)用C/C++的函數(shù),這使得Lua在應用程序中可以被廣泛應用。不僅僅作為
    發(fā)表于 10-26 17:21 ?11次下載

    MATLAB 7.0 基礎教程

    MATLAB 7.0 基礎教程 介紹MATLAB7.0的基礎教程,非常實用的教程
    發(fā)表于 12-18 11:44 ?6次下載

    Matlab基礎教程2

    Matlab基礎教程2Matlab基礎教程2Matlab基礎教程2Matlab基礎教程2
    發(fā)表于 12-24 16:33 ?2次下載

    Java編程語言基礎教程免費下載

    本文檔的主要內(nèi)容詳細介紹的是Java編程語言基礎教程免費下載包括了:第一單元基本語法,第二單元基本語法,第三單元面向?qū)ο缶幊蹋谒膯卧嫦驅(qū)ο缶幊?,第五單元面向?qū)ο缶幊?/div>
    發(fā)表于 10-23 08:00 ?18次下載
    Java編程語言<b class='flag-5'>基礎教程</b>免費下載

    LabVIEW基礎教程

    LabVIEW基礎教程說明。
    發(fā)表于 04-20 14:03 ?135次下載

    Lua在單片機中的移植

    Lua代碼符合ANSI C標準,只要有C編譯器的開發(fā)環(huán)境就能跑Lua。雖說只要有C編譯器就能跑Lua,但是單片機的環(huán)境太簡單,有些C標準的內(nèi)容仍舊無法支持。Lua的官網(wǎng)是:www.
    發(fā)表于 11-13 17:36 ?11次下載
    <b class='flag-5'>Lua</b>在單片機中的移植

    stm32應用:lua在Keil上的移植和使用

    stm32應用:lua在Keil上的移植和使用Lua的簡介Lua的移植關于Lua的應用舉例Lua 是一種輕量小巧的腳本語言,用標準C語言編寫
    發(fā)表于 12-20 18:51 ?16次下載
    stm32應用:<b class='flag-5'>lua</b>在Keil上的移植和使用

    Labview基礎教程

    Labview基礎教程
    發(fā)表于 12-13 11:51 ?2次下載

    【串口屏LUA教程】lua基礎學習(借鑒)

    【串口屏LUA教程】lua基礎學習(借鑒)
    發(fā)表于 04-29 13:02 ?4次下載

    【串口屏LUA教程】Lua腳本語言中文教程

    【串口屏LUA教程】Lua腳本語言中文教程
    發(fā)表于 04-29 13:03 ?26次下載

    Lua語法基礎教程(上篇)

    今天我們來學習Lua語法基礎教程。由于篇幅過長,將分為上中下三篇進行講解,本篇為上篇。 一、初識Lua Lua 是一種輕量小巧的腳本語言,它
    的頭像 發(fā)表于 10-24 07:17 ?65次閱讀

    Lua語法基礎教程(中篇)

    今天我們繼續(xù)學習Lua語法基礎教程,中篇。 五、變量 5.1 number變量 變量,可以看作是一個桶,在里面裝你想要裝的內(nèi)容。這些內(nèi)容可以是Lua包含的所有合法類型。 例如:我想要新
    的頭像 發(fā)表于 10-26 11:39 ?120次閱讀
    <b class='flag-5'>Lua</b><b class='flag-5'>語法</b><b class='flag-5'>基礎教程</b>(中篇)