02Lua入门
前言:
語言學起來其實相似點很多,簡單整理的知識點
目錄:
1.使用控制臺
2.Lua基礎
3.變量
4.運算符
5.控制結構
1.使用控制臺
Lua腳本是包含一系列Lua命令的簡單腳本(擴展名為.lua的文本文件)。Lua不關注格式,制表符,換行符或者其他讓腳本文件更具可讀性的轉換符號(不過Lua還是需要命令之間的空格符號,用來區別變量和函數調用)
簡單的Lua腳本:
for indx = 1,4 do
print("line:",indx )
end
也可以寫成:for indx = 1,4 do print("line:",indx ) end
注:
格式化后的腳本更容易閱讀,但不改變結果
可以把腳本放在本地文件夾通過dofile命令來在控制臺執行腳本,參數是字符串,指定文件的名字和路徑。使用dofile命令可以在命令行中運行腳本,如果腳本有什么錯誤的化,命令行會給出錯誤信息以便調試。
語法格式:
dofile<"c:\\file_name\\lua_scripts_name.lua">
2.Lua基礎
優勢:整合C++的模塊來擴展自身的功能。
語言定義
不以數字為標識符開頭(同C),避免下劃線接大寫字母(_NAME),因為這種格式是Lua自身保留的(保留字),如_Start。
Lua保留關鍵字
and??? local??? break??? nil??? do
not??? else??? or??? elseif??? repeat
end??? return??? false??? then??? for
true??? function??? until??? if??? while
in
變量,常量,函數名的格式和命名規則:
常用全大寫和下劃線(MY_NAME)
變量第一個字母小寫(myVariable)
全局變量第一個字母用小寫(gMyGlobal)
函數名第一個字母大寫(function? MyFunction)
--單行注釋
--[[
???? statements??? 塊注釋
--]]
使用技巧:--[[ 或者 --]]? 加一個 - 可以重新使用這段代碼? ---[[?? ---]]
3.變量
在Lua中,變量不需要在使用前聲明,這個稍微有些爭議。因為不需要聲明,所以可以才任何地方引入需要的變量。由于不是顯式聲明,所以很難追蹤變量(不造),或者在另一個函數中用了相同名字的變量而造成數據的混亂。因此,必須小心的使用變量,要保證變量是可追蹤的。同樣不需要指定變量類型,變量類型取決于給變量賦的值,靈活性較高。
變量賦值:
1.賦值改變
2.改變表域
多個變量同時賦值時賦值變量列表和值列表的各個元素用逗號分開,依次賦值。
a,b=1,2
遇到賦值語句Lua會先計算右邊所有的值然后在執行賦值操作,所以我們可以這樣進行交換變量的值。
x,y=y,x
當變量個數與值個數不一致時,Lua會以變量個數為基礎,采取不足補nil,多的忽略。
例:
a,b,c=0,1?? --->0,1,nil
a,b,c=0,1,2,3 --->0,1,2
多值賦值常用來交換變量,或將函數調用返回給變量。
例:
a, b = f()
f()返回兩個值,第一個賦給a,第二個賦給b。
應該盡可能的使用局部變量,有兩個好處:
1. 避免命名沖突。
2. 訪問局部變量的速度比全局變量更快。
索引
對 table 的索引使用方括號 []。Lua 也提供了 . 操作。
t[i]
t.i???????????????? -- 當索引為字符串類型時的一種簡化寫法
gettable_event(t,i) -- 采用索引訪問本質上是一個類似這樣的函數調用
例如:
> site = {}
> site["key"] = "www.w3cschool.cc"
> print(site["key"])
www.w3cschool.cc
> print(site.key)
www.w3cschool.cc
變量類型:
注:可以使用Type函數測試變量的類型。
3.1 nil
nil 表示沒賦值的變量,實際上可以表示刪除變量。
3.2Boolean
Boolean類型的變量只有兩種值 :true和false.
3.3string
3.3.1用兩個方括號也可以表示一塊字符串
特殊字符串:
\a??? 響鈴??? \v??? 垂直指標
\b??? 退格??? \\??? 反斜杠
\f??? 換頁符??? \"??? 雙引號
\n??? 換行符??? \'??? 單引號
\r??? 換行符??? \[??? 左方括號
\t??? 制表符??? \]??? 右方括號
\o??? 空字符??? \ddd??? 八進制
\xhh??? 十六進制
3.3.2在對一個數字字符串進行操作時,Lua會將這個數字字符串轉換成一個數字。
例子:
print(2+6)--8
print("2"+6)--8
print("2"+"6")--8
print("2+6")--2+6
print("abc"+6)--報錯,字符串連接不是用+而是兩點 ..
print("2"..6)--26
注:..(連接字符串)
?????? #(計算字符串長度,置于字符串前或者變量名前)
3.4Number
雙精度浮點數,無整數類型
myNumber=7
myNumber=0.765
myNumber=7.65e8(7.65x10^8,765 000 000)
myNumber=7.65e-2(7.65x10^-2,0.0765)
3.5table
3.5.1實質是關聯數組(associative arrays)索引為數字或字符串,初始索引為1.
3.5.2table的創建
3.5.2.1空表
local tab1={}
3.5.2.2初始表
local tab2={"apple","pear"}
注:table不會固定長度大小,有新數據添加時,table會自動增長,沒有初始值都為nil.
3.6局部變量和全局變量
Lua變量默認是全局的,也就是說,變量的值在整個會話中是保持不變的,除非腳本改變了它。
當使用全局變量時,變量名前加一個g字母會更加明確,便于調試。
局部變量可以給設定一個初始值,也可以不用賦值。
語法:
local 變量名
變量的有效范圍取決于聲明變量的位置。
4.運算符
4.1算術運算符
+-*/%^-
4.2關系運算符
==
~=
>
<
>=
<=
注:如果使用關系運算符比較兩個table,只有兩個table是同一個對象的時候才能得到預期的結果,因為變量只是table對象的引用(像指針一樣),不能直接比較存在于table中的值。
實例:
tableA={1,2,3}
tableB={1,2,3}
if tableA=tableB then
???? print("相等")
else
???? print("不相等")
end
-->不相等(結構不同)
tableA={1,2,3}
tableB=tableA
if tableA=tableB then
???? print("相等")
else
???? print("不相等")
end
-->相等(tableB指向了同樣的對象tableA)
4.3邏輯運算符
and(比較兩個參數時,第一個false則返回flase,否則返回第二個參數的值)
or
not
注:官方解釋的是一坨屎,就和C一樣理解就行。
4.4其他運算符
.. 連接字符串
#一元運算符,返回字符串或表的長度
4.5運算符的優先級
從高到低的順序:
^
not??? - (unary)
*????? /
+????? -
..
<????? >????? <=???? >=???? ~=???? ==
and
or
注:
除了^和..外所有的二元運算符都是左連接的。
a+i < b/2+1????????? <-->?????? (a+i) < ((b/2)+1)
5+x^2*8????????????? <-->?????? 5+((x^2)*8)
a < y and y <= z???? <-->?????? (a < y) and (y <= z)
-x^2???????????????? <-->?????? -(x^2)
x^y^z??????????????? <-->?????? x^(y^z)
實例
我們可以通過以下實例來更加透徹的了解 Lua 語言運算符的優先級:
a = 20
b = 10
c = 15
d = 5
e = (a + b) * c / d;-- ( 30 * 15 ) / 5
print("(a + b) * c / d 運算值為? :",e )
e = ((a + b) * c) / d; -- (30 * 15 ) / 5
print("((a + b) * c) / d 運算值為 :",e )
e = (a + b) * (c / d);-- (30) * (15/5)
print("(a + b) * (c / d) 運算值為 :",e )
e = a + (b * c) / d;? -- 20 + (150/5)
print("a + (b * c) / d 運算值為?? :",e )
以上程序執行結果為:
(a + b) * c / d 運算值為? :??? 90.0
((a + b) * c) / d 運算值為 :??? 90.0
(a + b) * (c / d) 運算值為 :??? 90.0
a + (b * c) / d 運算值為?? :??? 50.0
注:除了^和..外所有二元運算符都是左連接的。
筆記:
1.在Lua中實現C/C++中的三目運算。
condition?? result1:result2
|
if? condition then
return result1
else
return result2
end
三目運算
熟悉 C/C++ 的老司機都知道三目運算 a ? b : c,這種寫法替換簡單的條件判斷語句可以在不增加閱讀難度的情況下,使代碼盡量保持簡潔。
int a, b, ret;
//if-else
if (a > b)
???? ret = a;
else
???? ret = b;
//三目運算符
ret = a > b ? a : b;
Lua 中的三目運算
Lua 原生的語義并沒有實現三目運算,一般是通過邏輯運算符 and 和 or 來模擬三目運算符的。
Lua 中 and 和 or 都使用"短路求值(short_cur evaluation)",也就是說,它們只會在需要時才去評估第二個操作數。(《Lua程序設計》)
local a, b, ret;
ret = a > b and a or b
窮舉所有可能性:
a > b 時:
a > b and a –> true
a or b –> a
a <= b時:
a > b and a –> false
a or b –> b
完美!
Lua 中的三目運算符陷阱
按照從特殊到一般的原則:
三目運算的一般形式a ? b : c
a = true,結果為b
a = false,結果為c
對應Lua中的a and b or c
b = true
a = true
a and b –> true
b or c –> b
a = false
a and b –> false
b or c –> c
b = false
a = true
a and b –> false
b or c –> c
a = false
a and b –> false
b or c –> c
可以看到當 b = false 時,Lua模擬的 a and b or c 始終返回 c 并不能還原三目運算符的原貌。
《Lua程序設計》也建議這種情況使用 if-else 來避免。
一般化的 a and b or c
那么有沒有辦法可以解決 b = false 失效的問題呢?
由此我聯想到 C 語言有一道常規的考題:請使用宏定義寫一個返回兩個值中較小值的方法。
在校時第一次看到本題,第一反應如下:
#define MIN(A,B) A < B ? A : B
然而這種寫法在很多嵌套的使用環境中都不能返回正確的結果。比如:2 * MIN(3, 4)展開為 2 * 3 < 4 ? 3 : 4 = 6 < 4 ? 3 : 4,結果為4。
更"工程師"的寫法是:
#define MIN(A,B) ((A) < (B) ? (A) : (B))
還有好奇心的同學可以參考:宏定義的正確寫法,三目運算的宏定義
從這個示例中,我就在想如何能保證 a and b or c 中 b 為真或者 b 不產生歧義呢?
and的運算優先級高于or,簡單的改變運算順序并沒有用。
這時就想到了lua中萬能的table,能不能把a,b,c都放到table中來改變b的存在呢?要注意{nil}也是一個為true的對象。
a,b,c都替換為table:{a} and or {c}。
三目運算中a是條件,結果是b或者c。其實a并不需要放入table中,否則{a}就始終為true了,失去了條件的意義。而 or
{c}的結果也必然是一個table,該table只有一個元素。那么通過[1]即可訪問。
綜上所述,更一般化的Lua三目運算為:(a and or {c})[1]
2.其他運算符 —— #
在獲取表的長度時,根據的是表的最大索引的值:
tab1 = {"1","2"}
print("tab1長度"..#tab1)
tab2 = {key1="1","2"}
print("tab2長度"..#tab2)
tab3 = {}
tab3[1]="1"
tab3[2]="2"
tab3[4]="4"
print("tab3長度"..#tab3)
輸出:
tab1長度2
tab2長度1
tab3長度4
3. 下標越過 1 位以上,長度還是為 2:
tab3={}
tab3[1]="1"
tab3[2]="2"
tab3[5]="5"
print("tab3的長度",#tab3)
輸出:
tab3的長度??? 2
4.取長度操作符寫作一元操作 #
table t 的長度被定義成一個整數下標 n 。 它滿足 t[n] 不是 nil 而 t[n+1] 為 nil; 此外,如果 t[1] 為 nil ,n 就可能是零。 對于常規的數組,里面從 1 到 n 放著一些非空的值的時候, 它的長度就精確的為 n,即最后一個值的下標。 如果數組有一個“空洞” (就是說,nil 值被夾在非空值之間), 那么 #t 可能是指向任何一個是 nil 值的前一個位置的下標 (就是說,任何一個nil 值都有可能被當成數組的結束)。
tab4 = {}
tab4[1] = "1"
tab4[2] = nil
tab4[3] = "2"
tab4[4] = nil
print("tab4的長度", #tab4)
--tab4的長度??? 1
tab5 = {}
tab5[1] = "1"
tab5[2] = nil
tab5[3] = "2"
tab5[4] = "4"
print("tab5的長度", #tab5)
--tab5的長度??? 4
tab6 = {1, nil, 3}
print("tab6的長度", #tab6)
--tab6的長度??? 3
tab6 = {1, nil, 3, nil}
print("tab6的長度", #tab6)
--tab6的長度??? 1
5.控制結構
注:
控制結構的條件表達式結果可以是任何值,Lua認為false和nil為假,true和非nil為真。
要注意的是Lua中 0 為 true:
5.1if 語句
if 語句 由一個布爾表達式作為條件判斷,其后緊跟其他語句組成。
Lua if 語句語法格式如下:
if(布爾表達式)
then
??? --[ 在布爾表達式為 true 時執行的語句 --]
end
在布爾表達式為 true 時會if中的代碼塊會被執行,在布爾表達式為 false 時,緊跟在 if 語句 end 之后的代碼會被執行。
Lua認為false和nil為假,true 和非nil為真。要注意的是Lua中 0 為 true。
5.2if...else 語句
if 語句 可以與 else 語句搭配使用, 在 if 條件表達式為 false 時執行 else 語句代碼。
if...else 語句
Lua if 語句可以與 else 語句搭配使用, 在 if 條件表達式為 false 時執行 else 語句代碼塊。
Lua if...else 語句語法格式如下:
if(布爾表達式)
then
??? --[ 布爾表達式為 true 時執行該語句塊 --]
else
??? --[ 布爾表達式為 false 時執行該語句塊 --]
end
在布爾表達式為 true 時會if中的代碼塊會被執行,在布爾表達式為 false 時,else 的代碼塊會被執行。
Lua認為false和nil為假,true 和非nil為真。要注意的是Lua中 0 為 true。
if...elseif...else 語句
Lua if 語句可以與 elseif...else 語句搭配使用, 在 if 條件表達式為 false 時執行 elseif...else 語句代碼塊,用于檢測多個條件語句。
Lua if...elseif...else 語句語法格式如下:
if( 布爾表達式 1)
then
??? --[ 在布爾表達式 1 為 true 時執行該語句塊 --]
elseif( 布爾表達式 2)
then
??? --[ 在布爾表達式 2 為 true 時執行該語句塊 --]
elseif( 布爾表達式 3)
then
??? --[ 在布爾表達式 3 為 true 時執行該語句塊 --]
else
??? --[ 如果以上布爾表達式都不為 true 則執行該語句塊 --]
end
5.3if 嵌套語句
你可以在if 或 else if中使用一個或多個 if 或 else if 語句 。
if...else 語句
Lua if 語句允許嵌套, 這就意味著你可以在一個 if 或 else if 語句中插入其他的 if 或 else if 語句。
Lua if 嵌套語句語法格式如下:
if( 布爾表達式 1)
then
??? --[ 布爾表達式 1 為 true 時執行該語句塊 --]
??? if(布爾表達式 2)
??? then
?????? --[ 布爾表達式 2 為 true 時執行該語句塊 --]
??? end
end
你可以用同樣的方式嵌套 else if...else 語句。
注:Lua不支持case語句因此可以用elseif語句
5.4循環
Lua 語言提供了以下幾種循環處理方式:
while 循環
在條件為 true 時,讓程序重復地執行某些語句。執行語句前會先檢查條件是否為 true。
for 循環
重復執行指定語句,重復次數可在 for 語句中控制。
repeat...until
重復執行循環,直到 指定的條件為真時為止
循環嵌套
可以在循環內嵌套一個或多個循環語句(while do ... end;for ... do ... end;repeat ... until;)
5.4.1while
注:
while和repeat 控制結構非常相似,它們都可以循環執行一段腳本直到滿足某個條件。
Lua 編程語言中 while 循環語句在判斷條件為 true 時會重復執行循環體語句。
語法
Lua 編程語言中 while 循環語法:
while(condition)
do
??? statements
end
5.4.2repeat
repeat...until 循環的條件語句在當前循環結束后判斷。
語法
Lua 編程語言中 repeat...until 循環語法格式:
repeat
??? statements
until( condition )
5.4.3for
Lua 編程語言中 for 循環語句可以重復執行指定語句,重復次數可在 for 語句中控制。
Lua 編程語言中 for語句有兩大類:
數值for循環
泛型for循環
5.4.3.1數值for循環
Lua 編程語言中數值for循環語法格式:
for var=exp1,exp2,exp3 do?
???? <執行體>?
end
??
var從exp1變化到exp2,每次變化以exp3為步長遞增var,并執行一次"執行體"。exp3是可選的,如果不指定,默認為1。
示例:
for i=10,1,-1 do
???? print(i)
end
從10變到1,每次減1
結果:10,9,8,7,6,5,4,3,2,1
5.4.3.2泛型for循環
泛型for循環通過一個迭代器函數來遍歷所有值,類似java中的foreach語句。
Lua 編程語言中泛型for循環語法格式:
--打印數組a的所有值?
for i,v in ipairs(a)
???? do print(v)
end?
i是數組索引值,v是對應索引的數組元素值。ipairs是Lua提供的一個迭代器函數,用來迭代數組。
days ={"Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"}?
for i,v in ipairs(days) do?
print(v)
? end??
結果略(ipairs(為表達式列表),后面泛型for里有提到)
注:
1.循環次數只是在第一次執行時確定,因此就算用戶更改了參數的值也不會影響最終的循環次數。
2.循環結構中的變量是局部變量,一旦循環結束就會被清除。如果想保存它們的值
,那么必須使用全局變量或者更高級的局部變量。
筆記:
1.
在lua中pairs與ipairs兩個迭代器的用法相近,但有一點是不一樣的:
pairs可以遍歷表中所有的key,并且除了迭代器本身以及遍歷表本身還可以返回nil;
但是ipairs則不能返回nil,只能返回數字0,如果遇到nil則退出。它只能遍歷到表中出現的第一個不是整數的key
2.pairs遍歷表中全部key,value
ipairs從下標為1開始遍歷,然后下標累加1,如果某個下標元素不存在就終止遍歷。這就導致如果下標不連續或者不是從1開始的表就會中斷或者遍歷不到元素。
3.
首先,ipairs 這個迭代器只能遍歷所有數組下標的值,這是前提,也是和 pairs 的最根本區別,也就是說如果 ipairs 在迭代過程中是會直接跳過所有手動設定key值的變量。
特別注意一點,和其他多數語言不同的地方是,迭代的下標是從1開始的。
3.1
例如:
tab = {1,2,a= nil,"d"}
for i,v in ipairs(tab) do
???? print(i,v)
end
輸出結果為:
1? 1
2? 2
3? d
這里是直接跳過了a=nil這個變量
3.2
ipairs在迭代過程中如果遇到nil時會直接停止。
例如:
tab = {1,2,a= nil,nil,"d"}
for i,v in ipairs(tab) do
???? print(i,v)
end
輸出結果為:
1? 1
2? 2
4.
for 循環中,循環的索引 i 為外部索引,修改循環語句中的內部索引 i,不會影響循環次數:
for i=1,10 do
???? i = 10
???? print("one time,i:"..i)
end
仍然循環 10 次,只是 i 的值被修改了。
5.5嵌套循環
語法
Lua 編程語言中 for 循環嵌套語法格式:
for init,max/min value, increment
do
??? for init,max/min value, increment
??? do
?????? statements
??? end
??? statements
end
Lua 編程語言中 while 循環嵌套語法格式:
while(condition)
do
??? while(condition)
??? do
?????? statements
??? end
??? statements
end
Lua 編程語言中 repeat...until 循環嵌套語法格式:
repeat
??? statements
??? repeat
?????? statements
??? until( condition )
until( condition )
除了以上同類型循環嵌套外,我們還可以使用不同的循環類型來嵌套,如 for 循環體中嵌套 while 循環。
實例
以下實例使用了for循環嵌套:
j =2
for i=2,10 do
??? for j=2,(i/j) , 2 do
?????? if(not(i%j))
?????? then
????????? break
?????? end
?????? if(j > (i/j))then
????????? print("i 的值為:",i)
?????? end
??? end
end
以上代碼執行結果為:
i 的值為:??? 8
i 的值為:??? 9
i 的值為:??? 10
5.6循環控制語句
循環控制語句用于控制程序的流程, 以實現程序的各種結構方式。
Lua 支持以下循環控制語句:
break 語句
退出當前循環或語句,并開始腳本執行緊接著的語句。
5.7無限循環
在循環體中如果條件永遠為 true 循環語句就會永遠執行下去,以下以 while 循環為例:
while( true )
do
??? print("循環將永遠執行下去")
end
轉載于:https://www.cnblogs.com/fenqinearl/p/9249049.html
總結
- 上一篇: 手机屏幕外面钢化膜碎了怎么修复??
- 下一篇: JS继承的实现方式