文章目錄
- 3.3.1 if語句
- 3.3.2 while語句
- 3.3.3 repeat-until
- 3.3.4 for迴圈
- 3.3.5 break和return
Lua基礎學習
要學習tolua++的使用,首先也得先學會lua的基本文法和lua與c/c++之間的介面調用。本次總結意在把lua的一些基本的用法總結歸納一下,好讓大家可以在短時間內對lua有一個簡單的瞭解,達到可以看懂lua代碼的目的。
註:
注釋:單行注釋:--
多行注釋:--[[ --]]
lua大小寫敏感
1. 基本類型1.1 nil
它就相當於c++裡邊的NULL,但又與NULL不同,lua中的全域變數變數如果沒有賦初值,則它的值就預設等於nil,如果想要刪除一個全域變數變數,則可以給它賦值nil。
1.2 booleans
它的取值跟c++一樣,有true和false兩種。但是在lua中有一個特別的地方,在判斷語句的時候,除了false和nil為假,其它的值都為真,這點c++程式員應該格外注意,0和空串也為真。
1.3 numbers
在lua中number代表實數,他強大的可以代表任何你能想象到的數字(玩笑開大啦),在應用中去探索吧。例:整數、浮點、指數似乎還有複數等。
1.4 strings
lua中的string就類似c++中的const char[],不過人家是通過lua來自動分配記憶體和釋放記憶體的。另外注意那個const,它的值是不允許修改的;
它支援逸出字元,類似c++的逸出字元;
lua會自動在string和numbers之間自動進行類型轉換,當一個字串使用算術操作符時,string就會被轉成數字,如果string中的內容並非number的時候,可會報錯哦;
在lua中字串的串連符是..,如果要串連的是數字,則要在..和數字間留一個空格;
另外lua還提供tonumber()和tostring()函數,支援數字和字串間的轉換,不過在字串轉換數位時候,如果字串不是正確的數字tonumber()會返回nil。
1.5 functions
在lua中,函數也可以作為變數儲存,可以作為函數的參數和傳回值,瞭解到這個,你就可以在你的lua代碼中發揮自己的想象去實現一些強大的功能啦。
1.6 userdata
顧名思義,就是使用者自己定義的類型,其實就是在lua和c++互動過程中,c++定義的 類型。
2. 運算式2.1 算數運算子
跟c++一樣,加減乘除啥的。
2.2 關係運算子
跟c++類似,就是!=換為~=。
2.3 邏輯運算子
這個可比較特別哦,要多加註意,lua的邏輯運算子有not、and、or;
lua中只有false和nil為假,其它都為真;
not a: a為false,值為true,a為true,值為false;
a and b: 如果a為false,則取a值,否則取b值;
a or b: 如果a為true,則取a值,否則取b值;
c++中的三目運算子a?b:c在lua中的實現:(a and b) or c。
2.4 串連運算子
.. -- 這個前邊介紹過,就是串連兩個字串
2.5 優先順序
類似c++,按老套路用就行
2.6 表的構造
這是lua的重頭戲,它的建構函式是{}。
table = {} -- 建立一個空表
表裡邊可以存放任意類型的成員,就把它當做一個c++的類即可,以下聚幾個例子
test = {“a”,”b”,”c”,”d”,”e”,”f”,”g”}
print (test[4]) -- d // 這裡注意,lua的下標操作是從1開始計算的
test = {x=1,y=2,z=3}
print (test.x,test.y,test.z) -- 1 2 3
test[1] = "a"
test1 = {"b","c"}
test1.a = test
print (test[1],test.x,test.y,test.z) -- a 1 2 3
print (test1.a[1],test1.a.x,test1[1]) -- a 1 b
更多細節請參照lua官網
3. 基本文法3.1 賦值
lua可以對多個變數同時賦值,各變數和值用逗號分隔,指派陳述式右邊的值會依次賦給左邊的變數;
當變數個數比值多時,多出的變數會賦值nil;
當變數個數少於值時,多餘的值會忽略;
例:
x,y = y,x -- 交換x和y的值
a,b,c = 0,1 -- a=0,b=1,c=nil
a,b = 3,2,1 -- a=3,b=2
3.2 局部變數
lua使用local建立局部變數,它的範圍就跟c++類似,不過它沒有{},取而代之的是do..end,如果想要設定一個局部變數,則可以將它定義在do..end當中;
lua中使用局部變數有兩個好處:
例:
do
local a = 2
b = 4
print (a,b) -- 2 4
end
print (a,b) -- nil 4
3.3 控制語句3.3.1 if語句
if conditions then
then-part
end;
if conditions then
then-part
else
else-part
end;
if conditions then
then-part
elseif conditions then
elseif-part
.. --->多個elseif
else
else-part
end;
3.3.2 while語句
while condition do
statements;
end;
3.3.3 repeat-until
repeat
statements;
until conditions;
這個可能比較眼生,其實類似c++的do..while語句,即運行statements直到conditions為真。
3.3.4 for迴圈3.3.4.1 數值for迴圈
for var=exp1,exp2,exp3 do
loop-part
end
for將用exp3作為step從exp1(初始值)到exp2(終止值),執行loop-part。其中exp3可以省略,預設step=1.
3.3.4.2 範型for迴圈
遍曆表
for k in pairs(t) do print(k) end -- 遍曆表t中的所有元素
for i,v in ipairs(a) do print(v) end
--遍曆表a,i為其索引,v為其值。
3.3.5 break和return
這個文法與c++類似,break是用來退出控制語句,return是用來退出函數的。
註:在lua中,break和return必須在一個塊得結束部分出現,即它的後邊出現的必須是end、else、until,如果真的想要在某個語句位置使用它們,可以顯式的使用do..end來包含它們實現想要的功能。例:do return end;
4. 函數4.1 函數的定義
function name (param)
return value
end;
4.2 多傳回值
lua是允許返回多個值的,如果函數有多個傳回值,則對變數的賦值按照3.1賦值裡邊規定的方式賦值。
例:
function foo0 end
function foo1 return 'a' end
function foo2 return 'a' 'b' end
x,y = foo2() -- x='a', y='b'
x = foo2() -- x='a', 傳回值'b'廢棄
x,y,z = 10,foo2() -- x=10, y='a', z='b'、
x,y = foo0() -- x=nil, y=nil
x,y = foo1() -- x='a', y=nil
x,y,z = foo2() -- x='a', y='b', z=nil
4.3 可變參數
lua函數可以接受可變數目的參數,和C語言類似在函數參數列表中使用三點(...)表示函數有可變的參數。lua將函數的參數放在一個叫arg的表中,除了參數以外,arg表中還有一個域n表示參數的個數
例:
printResult = ""
function test(...)
print ("haveing " .. arg.n .. " param")
for i,v in ipairs(arg) do
printResult = printResult .. tostring(v)
end;
print (printResult)
end
test('a','b','c','d','e')
結果:
haveing 5 param
abcde
4.4 具名引數
lua的調用過程中,參數是依次把實參傳遞給相應的形參的。但如果有時候我們很難記清參數的前後順序,這個時候就可以使用具名引數。顧名思義,就是為每個參數起一個名字,調用的時候,只需要為這個名字的參數賦值即可。
例:
function rename (arg)
return os.rename(arg.old, arg.new)
end
rename(old="temp.lua", new="temp1.lua") –調用的時候為具名引數賦值
4.5 閉包
首先明確一個概念,詞法定界。當一個函數內部嵌套另一個函數定義時,內部的函數體可以訪問外部的函數的局部變數,這種特徵我們稱作詞法定界
所謂“閉包”,官方解釋指的是一個擁有許多變數和綁定了這些變數的環境的運算式(通常是一個函數),因而這些變數也是該運算式的一部分。
是不是有點糊塗呢?舉個例子:
function newCounter()
local i = 0
return function() -- 無名函數
i = i + 1
return i
end
end
c1 = newCounter()
print(c1()) --> 1
print(c1()) --> 2
c2 = newCounter()
print(c2()) --> 1
print(c1()) --> 3
print(c2()) --> 2
這段代碼有兩個特點,1. “匿名函數”嵌套在函數newCounter內,2. 函數newCounter把“匿名函數”返回了。
在執行完c1 = newCounter()後,其實c1指向的是“匿名函數”,當我們執行c1的時候,就可以操作函數newCounter的局部變數i,這個i我們稱之為外部的局部變數(external local variable)或者upvalue。我們再次聲明一個變數c2= newCounter()後,c1和c2其實是建立在同一個函數上的,但是他們的局部變數i確是兩個不同的執行個體,即我們建立了兩個閉包。就是說:當函數newCounter的內建函式(即上例的“匿名函數”)被函數newCounter外的變數c1引用的時候,就建立了一個閉包。
閉包的應用情境:
- 保護函數內的變數安全。以最開始的例子為例,函數a中i只有函數b才能訪問,而無法通過其他途徑訪問到,因此保護了i的安全性。
- 在記憶體中維持一個變數。依然如前例,由於閉包,函數a中i的一直存在於記憶體中,因此每次執行c(),都會給i自加1。
4.6 非全域函數
lua中函數可以作為全域變數也可以作為局部變數
1. 表和函數放在一起
Lib = {}
Lib.foo = function (x,y) return x + y end
Lib.goo = function (x,y) return x - y end
2. 使用表建構函式
Lib = {
foo = function (x,y) return x + y end,
goo = function (x,y) return x - y end
}
3. lua提供的另一種文法方式
Lib = {}
function Lib.foo (x,y)
return x + y
end
function Lib.goo (x,y)
return x - y
end
當我們將函數儲存在一個局部變數內時,我們得到一個局部函數,也就是說局部函數像局部變數一樣在一定範圍內有效。定義局部函數的兩種方式:
local f = function (...)
...
end
local function f (...)
...
end
看如下代碼:
local fact = function (n)
if n == 0 then
return 1
else
return n*fact(n-1) -- 此處lua不能識別fact,因為是局部函數,lua不能識別
end
end
修改為先聲明,如下:
local fact
fact = function (n)
if n == 0 then
return 1
else
return n*fact(n-1)
end
end