LUA腳本語言語法-學習筆記二

Lua 循環

很多情況下我們需要做一些有規律性的重複操作,因此在程序中就需要重複執行某些語句。

一組被重複執行的語句稱之爲循環體,能否繼續重複,決定循環的終止條件。

循環結構是在一定條件下反覆執行某段程序的流程結構,被反覆執行的程序被稱爲循環體。

循環語句是由循環體及循環的終止條件兩部分組成的。

Lua 語言提供了以下幾種循環處理方式:

循環類型 描述
while 循環 在條件爲 true 時,讓程序重複地執行某些語句。執行語句前會先檢查條件是否爲 true。
for 循環 重複執行指定語句,重複次數可在 for 語句中控制。
repeat...until 重複執行循環,直到 指定的條件爲真時爲止
循環嵌套 可以在循環內嵌套一個或多個循環語句(while do ... end;for ... do ... end;repeat ... until;)

循環控制語句

循環控制語句用於控制程序的流程, 以實現程序的各種結構方式。

Lua 支持以下循環控制語句:

控制語句 描述
break 語句 退出當前循環或語句,並開始腳本執行緊接着的語句。
goto 語句 將程序的控制點轉移到一個標籤處。

無限循環

在循環體中如果條件永遠爲 true 循環語句就會永遠執行下去,以下以 while 循環爲例:

實例

while( true )
do
   print("循環將永遠執行下去")
end

Lua 流程控制

Lua 編程語言流程控制語句通過程序設定一個或多個條件語句來設定。在條件爲 true 時執行指定程序代碼,在條件爲 false 時執行其他指定代碼。

以下是典型的流程控制流程圖:

控制結構的條件表達式結果可以是任何值,Lua認爲false和nil爲假,true和非nil爲真。

要注意的是Lua中 0 爲 true:

--[ 0 爲 true ]
if(0)
then
    print("0 爲 true")
end

以上代碼輸

出結果爲:

0 爲 true

Lua 提供了以下控制結構語句:

語句 描述
if 語句 if 語句 由一個布爾表達式作爲條件判斷,其後緊跟其他語句組成。
if...else 語句 if 語句 可以與 else 語句搭配使用, 在 if 條件表達式爲 false 時執行 else 語句代碼。
if 嵌套語句 你可以在ifelse if中使用一個或多個 ifelse if 語句 。

Lua 函數

在Lua中,函數是對語句和表達式進行抽象的主要方法。既可以用來處理一些特殊的工作,也可以用來計算一些值。

Lua 提供了許多的內建函數,你可以很方便的在程序中調用它們,如print()函數可以將傳入的參數打印在控制檯上。

Lua 函數主要有兩種用途:

  • 1.完成指定的任務,這種情況下函數作爲調用語句使用;
  • 2.計算並返回值,這種情況下函數作爲賦值語句的表達式使用。
--[[ 函數返回兩個值的最大值 --]]
function max(num1, num2)

   if (num1 > num2) then
      result = num1;
   else
      result = num2;
   end

   return result; 
end
-- 調用函數
print("兩值比較最大值爲 ",max(10,4))
print("兩值比較最大值爲 ",max(5,6))

Lua 中我們可以將函數作爲參數傳遞給函數,如下實例:

myprint = function(param)
   print("這是打印函數 -   ##",param,"##")
end

function add(num1,num2,functionPrint)
   result = num1 + num2
   -- 調用傳遞的函數參數
   functionPrint(result)
end
myprint(10)
-- myprint 函數作爲參數傳遞
add(2,5,myprint)

多返回值

Lua函數可以返回多個結果值,比如string.find,其返回匹配串"開始和結束的下標"(如果不存在匹配串返回nil)。

> s, e = string.find("www.runoob.com", "runoob") 
> print(s, e)
5    10

Lua函數中,在return後列出要返回的值的列表即可返回多值,如:

function maximum (a)
    local mi = 1             -- 最大值索引
    local m = a[mi]          -- 最大值
    for i,val in ipairs(a) do
       if val > m then
           mi = i
           m = val
       end
    end
    return m, mi
end

print(maximum({8,10,23,12,5}))
23    3

可變參數

Lua 函數可以接受可變數目的參數,和 C 語言類似,在函數參數列表中使用三點 ... 表示函數有可變的參數。

function add(...)  
local s = 0  
  for i, v in ipairs{...} do   --> {...} 表示一個由所有變長參數構成的數組  
    s = s + v  
  end  
  return s  
end  
print(add(3,4,5,6,7))  --->25

我們可以將可變參數賦值給一個變量。

例如,我們計算幾個數的平均值:

function average(...)
   result = 0
   local arg={...}    --> arg 爲一個表,局部變量
   for i,v in ipairs(arg) do
      result = result + v
   end
   print("總共傳入 " .. #arg .. " 個數")
   return result/#arg
end

print("平均值爲",average(10,5,3,4,5,6))
總共傳入 6 個數
平均值爲    5.5

通常在遍歷變長參數的時候只需要使用 {…},然而變長參數可能會包含一些 nil,那麼就可以用 select 函數來訪問變長參數了:select('#', …) 或者 select(n, …)

調用select時,必須傳入一個固定實參selector(選擇開關)和一系列變長參數。如果selector爲數字n,那麼select返回它的第n個可變實參,否則只能爲字符串"#",這樣select會返回變長參數的總數。例子代碼:

select('#', …) 返回可變參數的長度

select(n, …) 用於訪問 nselect('#',…) 的參數

do  
    function foo(...)  
        for i = 1, select('#', ...) do  -->獲取參數總數
            local arg = select(i, ...); -->讀取參數
            print("arg", arg);  
        end  
    end  
  
    foo(1, 2, 3, 4);  
end
arg    1
arg    2
arg    3
arg    4

Lua 運算符

運算符是一個特殊的符號,用於告訴解釋器執行特定的數學或邏輯運算。Lua提供了以下幾種運算符類型:

  • 算術運算符
  • 關係運算符
  • 邏輯運算符
  • 其他運算符
操作符 描述 實例
+ 加法 A + B 輸出結果 30
- 減法 A - B 輸出結果 -10
* 乘法 A * B 輸出結果 200
/ 除法 B / A w輸出結果 2
% 取餘 B % A 輸出結果 0
^ 乘冪 A^2 輸出結果 100
- 負號 -A 輸出結果 -10
a = 21
b = 10
c = a + b
print("Line 1 - c 的值爲 ", c )
c = a - b
print("Line 2 - c 的值爲 ", c )
c = a * b
print("Line 3 - c 的值爲 ", c )
c = a / b
print("Line 4 - c 的值爲 ", c )
c = a % b
print("Line 5 - c 的值爲 ", c )
c = a^2
print("Line 6 - c 的值爲 ", c )
c = -a
print("Line 7 - c 的值爲 ", c )

關係運算符

下表列出了 Lua 語言中的常用關係運算符,設定 A 的值爲10,B 的值爲 20:

操作符 描述 實例
== 等於,檢測兩個值是否相等,相等返回 true,否則返回 false (A == B) 爲 false。
~= 不等於,檢測兩個值是否相等,相等返回 false,否則返回 true (A ~= B) 爲 true。
> 大於,如果左邊的值大於右邊的值,返回 true,否則返回 false (A > B) 爲 false。
< 小於,如果左邊的值大於右邊的值,返回 false,否則返回 true (A < B) 爲 true。
>= 大於等於,如果左邊的值大於等於右邊的值,返回 true,否則返回 false (A >= B) 返回 false。
<= 小於等於, 如果左邊的值小於等於右邊的值,返回 true,否則返回 false (A <= B) 返回 true。
a = 21
b = 10

if( a == b )
then
   print("Line 1 - a 等於 b" )
else
   print("Line 1 - a 不等於 b" )
end

if( a ~= b )
then
   print("Line 2 - a 不等於 b" )
else
   print("Line 2 - a 等於 b" )
end

if ( a < b )
then
   print("Line 3 - a 小於 b" )
else
   print("Line 3 - a 大於等於 b" )
end

if ( a > b ) 
then
   print("Line 4 - a 大於 b" )
else
   print("Line 5 - a 小於等於 b" )
end

-- 修改 a 和 b 的值
a = 5
b = 20
if ( a <= b ) 
then
   print("Line 5 - a 小於等於  b" )
end

if ( b >= a ) 
then
   print("Line 6 - b 大於等於 a" )
end

邏輯運算符

下表列出了 Lua 語言中的常用邏輯運算符,設定 A 的值爲 true,B 的值爲 false:

操作符 描述 實例
and 邏輯與操作符。 若 A 爲 false,則返回 A,否則返回 B。 (A and B) 爲 false。
or 邏輯或操作符。 若 A 爲 true,則返回 A,否則返回 B。 (A or B) 爲 true。
not 邏輯非操作符。與邏輯運算結果相反,如果條件爲 true,邏輯非爲 false。 not(A and B) 爲 true。
a = true
b = true

if ( a and b )
then
   print("a and b - 條件爲 true" )
end

if ( a or b )
then
   print("a or b - 條件爲 true" )
end

print("---------分割線---------" )

-- 修改 a 和 b 的值
a = false
b = true

if ( a and b )
then
   print("a and b - 條件爲 true" )
else
   print("a and b - 條件爲 false" )
end

if ( not( a and b) )
then
   print("not( a and b) - 條件爲 true" )
else
   print("not( a and b) - 條件爲 false" )
end

其他運算符

下表列出了 Lua 語言中的連接運算符與計算表或字符串長度的運算符:

操作符 描述 實例
.. 連接兩個字符串 a..b ,其中 a 爲 "Hello " , b 爲 "World", 輸出結果爲 "Hello World"。
# 一元運算符,返回字符串或表的長度。 #"Hello" 返回 5
a = "Hello "
b = "World"

print("連接字符串 a 和 b ", a..b )

print("b 字符串長度 ",#b )

print("字符串 Test 長度 ",#"Test" )

print("菜鳥教程網址長度 ",#"www.runoob.com" )

Lua 字符串

字符串或串(String)是由數字、字母、下劃線組成的一串字符。

Lua 語言中字符串可以使用以下三種方式來表示:

  • 單引號間的一串字符。
  • 雙引號間的一串字符。
  • [[和]]間的一串字符。

以上三種方式的字符串實例如下:

string1 = "Lua"
print("\"字符串 1 是\"",string1)
string2 = 'runoob.com'
print("字符串 2 是",string2)

string3 = [["Lua 教程"]]
print("字符串 3 是",string3)
string1 = "Lua"
print("\"字符串 1 是\"",string1)
string2 = 'runoob.com'
print("字符串 2 是",string2)

string3 = [["Lua 教程"]]
print("字符串 3 是",string3)

轉義字符用於表示不能直接顯示的字符,比如後退鍵,回車鍵,等。如在字符串轉換雙引號可以使用 "\""。

所有的轉義字符和所對應的意義:

轉義字符

意義

ASCII碼值(十進制)

\a

響鈴(BEL)

007

\b

退格(BS) ,將當前位置移到前一列

008

\f

換頁(FF),將當前位置移到下頁開頭

012

\n

換行(LF) ,將當前位置移到下一行開頭

010

\r

回車(CR) ,將當前位置移到本行開頭

013

\t

水平製表(HT) (跳到下一個TAB位置)

009

\v

垂直製表(VT)

011

\\

代表一個反斜線字符''\'

092

\'

代表一個單引號(撇號)字符

039

\"

代表一個雙引號字符

034

\0

空字符(NULL)

000

\ddd

1到3位八進制數所代表的任意字符

三位八進制

\xhh

1到2位十六進制所代表的任意字符

二位十六進制

字符串的操作

序號 方法 & 用途
1 string.upper(argument):
字符串全部轉爲大寫字母。
2 string.lower(argument):
字符串全部轉爲小寫字母。
3 string.gsub(mainString,findString,replaceString,num)

在字符串中替換。

mainString 爲要操作的字符串, findString 爲被替換的字符,replaceString 要替換的字符,num 替換次數(可以忽略,則全部替換),如:
> string.gsub("aaaa","a","z",3);

zzza    3

 

4 string.find (str, substr, [init, [end]])
在一個指定的目標字符串中搜索指定的內容(第三個參數爲索引),返回其具體位置。不存在則返回 nil。
> string.find("Hello Lua user", "Lua", 1) 
7    9

 

5 string.reverse(arg)
字符串反轉
> string.reverse("Lua")
auL

 

6 string.format(...)
返回一個類似printf的格式化字符串
> string.format("the value is:%d",4)
the value is:4

 

7 string.char(arg) 和 string.byte(arg[,int])
char 將整型數字轉成字符並連接, byte 轉換字符爲整數值(可以指定某個字符,默認第一個字符)。
> string.char(97,98,99,100)
abcd
> string.byte("ABCD",4)
68
> string.byte("ABCD")
65
>

 

8 string.len(arg)
計算字符串長度。
string.len("abc")
3
9 string.rep(string, n)
返回字符串string的n個拷貝
> string.rep("abcd",2)
abcdabcd
10 ..
鏈接兩個字符串
> print("www.runoob.".."com")
www.runoob.com
11 string.gmatch(str, pattern)
回一個迭代器函數,每一次調用這個函數,返回一個在字符串 str 找到的下一個符合 pattern 描述的子串。如果參數 pattern 描述的字符串沒有找到,迭代函數返回nil。
> for word in string.gmatch("Hello Lua user", "%a+") do print(word) end
Hello
Lua
user
12 string.match(str, pattern, init)
string.match()只尋找源字串str中的第一個配對. 參數init可選, 指定搜尋過程的起點, 默認爲1。
在成功配對時, 函數將返回配對表達式中的所有捕獲結果; 如果沒有設置捕獲標記, 則返回整個配對字符串. 當沒有成功的配對時, 返回nil。
> = string.match("I have 2 questions for you.", "%d+ %a+")
2 questions

> = string.format("%d, %q", string.match("I have 2 questions for you.", "(%d+) (%a+)"))
2, "questions"

字符串格式化輸出

Lua 提供了 string.format() 函數來生成具有特定格式的字符串, 函數的第一個參數是格式 , 之後是對應格式中每個代號的各種數據。

由於格式字符串的存在, 使得產生的長字符串可讀性大大提高了。這個函數的格式很像 C 語言中的 printf()。

以下實例演示瞭如何對字符串進行格式化操作:

格式字符串可能包含以下的轉義碼:

  • %c - 接受一個數字, 並將其轉化爲ASCII碼錶中對應的字符
  • %d, %i - 接受一個數字並將其轉化爲有符號的整數格式
  • %o - 接受一個數字並將其轉化爲八進制數格式
  • %u - 接受一個數字並將其轉化爲無符號整數格式
  • %x - 接受一個數字並將其轉化爲十六進制數格式, 使用小寫字母
  • %X - 接受一個數字並將其轉化爲十六進制數格式, 使用大寫字母
  • %e - 接受一個數字並將其轉化爲科學記數法格式, 使用小寫字母e
  • %E - 接受一個數字並將其轉化爲科學記數法格式, 使用大寫字母E
  • %f - 接受一個數字並將其轉化爲浮點數格式
  • %g(%G) - 接受一個數字並將其轉化爲%e(%E, 對應%G)及%f中較短的一種格式
  • %q - 接受一個字符串並將其轉化爲可安全被Lua編譯器讀入的格式
  • %s - 接受一個字符串並按照給定的參數格式化該字符串

爲進一步細化格式, 可以在%號後添加參數. 參數將以如下的順序讀入:

  • (1) 符號: 一個+號表示其後的數字轉義符將讓正數顯示正號. 默認情況下只有負數顯示符號.
  • (2) 佔位符: 一個0, 在後面指定了字串寬度時佔位用. 不填時的默認佔位符是空格.
  • (3) 對齊標識: 在指定了字串寬度時, 默認爲右對齊, 增加-號可以改爲左對齊.
  • (4) 寬度數值
  • (5) 小數位數/字串裁切: 在寬度數值後增加的小數部分n, 若後接f(浮點數轉義符, 如%6.3f)則設定該浮點數的小數只保留n位, 若後接s(字符串轉義符, 如%5.3s)則設定該字符串只顯示前n位.
string.format("%c", 83)                 -- 輸出S
string.format("%+d", 17.0)              -- 輸出+17
string.format("%05d", 17)               -- 輸出00017
string.format("%o", 17)                 -- 輸出21
string.format("%u", 3.14)               -- 輸出3
string.format("%x", 13)                 -- 輸出d
string.format("%X", 13)                 -- 輸出D
string.format("%e", 1000)               -- 輸出1.000000e+03
string.format("%E", 1000)               -- 輸出1.000000E+03
string.format("%6.3f", 13)              -- 輸出13.000
string.format("%q", "One\nTwo")         -- 輸出"One\
                                        --   Two"
string.format("%s", "monkey")           -- 輸出monkey
string.format("%10s", "monkey")         -- 輸出    monkey
string.format("%5.3s", "monkey")        -- 輸出  mon

字符與整數相互轉換

以下實例演示了字符與整數相互轉換:

-- 字符轉換
-- 轉換第一個字符
print(string.byte("Lua"))
-- 轉換第三個字符
print(string.byte("Lua",3))
-- 轉換末尾第一個字符
print(string.byte("Lua",-1))
-- 第二個字符
print(string.byte("Lua",2))
-- 轉換末尾第二個字符
print(string.byte("Lua",-2))

-- 整數 ASCII 碼轉換爲字符
print(string.char(97))
76
97
97
117
117
a

匹配模式

Lua 中的匹配模式直接用常規的字符串來描述。 它用於模式匹配函數 string.find, string.gmatch, string.gsub, string.match

你還可以在模式串中使用字符類。

字符類指可以匹配一個特定字符集合內任何字符的模式項。比如,字符類 %d 匹配任意數字。所以你可以使用模式串 %d%d/%d%d/%d%d%d%d 搜索 dd/mm/yyyy 格式的日期:

s = "Deadline is 30/05/1999, firm"
date = "%d%d/%d%d/%d%d%d%d"
print(string.sub(s, string.find(s, date)))    --> 30/05/1999

Lua 數組

數組,就是相同數據類型的元素按一定順序排列的集合,可以是一維數組和多維數組。

Lua 數組的索引鍵值可以使用整數表示,數組的大小不是固定的。

array = {"Lua", "Tutorial"}

for i= 0, 2 do
   print(array[i])
end
nil
Lua
Tutorial

正如你所看到的,我們可以使用整數索引來訪問數組元素,如果知道的索引沒有值則返回nil。

在 Lua 索引值是以 1 爲起始,但你也可以指定 0 開始。

除此外我們還可以以負數爲數組索引值:

array = {}

for i= -2, 2 do
   array[i] = i *2
end

for i = -2,2 do
   print(array[i])
end
-4
-2
0
2
4

多維數組即數組中包含數組或一維數組的索引鍵對應一個數組。

以下是一個三行三列的陣列多維數組:

-- 初始化數組
array = {}
for i=1,3 do
   array[i] = {}
      for j=1,3 do
         array[i][j] = i*j
      end
end

-- 訪問數組
for i=1,3 do
   for j=1,3 do
      print(array[i][j])
   end
end
1
2
3
2
4
6
3
6
9

Lua table(表)

table 是 Lua 的一種數據結構用來幫助我們創建不同的數據類型,如:數組、字典等。

Lua table 使用關聯型數組,你可以用任意類型的值來作數組的索引,但這個值不能是 nil。

Lua table 是不固定大小的,你可以根據自己需要進行擴容。

Lua也是通過table來解決模塊(module)、包(package)和對象(Object)的。 例如string.format表示使用"format"來索引table string。

table(表)的構造

構造器是創建和初始化表的表達式。表是Lua特有的功能強大的東西。最簡單的構造函數是{},用來創建一個空表。可以直接初始化數組:

-- 初始化表
mytable = {}

-- 指定值
mytable[1]= "Lua"

-- 移除引用
mytable = nil
-- lua 垃圾回收會釋放內存

當我們爲 table a 並設置元素,然後將 a 賦值給 b,則 a 與 b 都指向同一個內存。如果 a 設置爲 nil ,則 b 同樣能訪問 table 的元素。如果沒有指定的變量指向a,Lua的垃圾回收機制會清理相對應的內存。

以下實例演示了以上的描述情況:

-- 簡單的 table
mytable = {}
print("mytable 的類型是 ",type(mytable))

mytable[1]= "Lua"
mytable["wow"] = "修改前"
print("mytable 索引爲 1 的元素是 ", mytable[1])
print("mytable 索引爲 wow 的元素是 ", mytable["wow"])

-- alternatetable和mytable的是指同一個 table
alternatetable = mytable

print("alternatetable 索引爲 1 的元素是 ", alternatetable[1])
print("mytable 索引爲 wow 的元素是 ", alternatetable["wow"])

alternatetable["wow"] = "修改後"

print("mytable 索引爲 wow 的元素是 ", mytable["wow"])

-- 釋放變量
alternatetable = nil
print("alternatetable 是 ", alternatetable)

-- mytable 仍然可以訪問
print("mytable 索引爲 wow 的元素是 ", mytable["wow"])

mytable = nil
print("mytable 是 ", mytable)
mytable 的類型是     table
mytable 索引爲 1 的元素是     Lua
mytable 索引爲 wow 的元素是     修改前
alternatetable 索引爲 1 的元素是     Lua
mytable 索引爲 wow 的元素是     修改前
mytable 索引爲 wow 的元素是     修改後
alternatetable 是     nil
mytable 索引爲 wow 的元素是     修改後
mytable 是     nil

able 操作

以下列出了 Table 操作常用的方法:

序號 方法 & 用途
1 table.concat (table [, sep [, start [, end]]]):

concat是concatenate(連鎖, 連接)的縮寫. table.concat()函數列出參數中指定table的數組部分從start位置到end位置的所有元素, 元素間以指定的分隔符(sep)隔開。

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

在table的數組部分指定位置(pos)插入值爲value的一個元素. pos參數可選, 默認爲數組部分末尾.

3 table.maxn (table)

指定table中所有正數key值中最大的key值. 如果不存在key值爲正數的元素, 則返回0。(Lua5.2之後該方法已經不存在了,本文使用了自定義函數實現)

4 table.remove (table [, pos])

返回table數組部分位於pos位置的元素. 其後的元素會被前移. pos參數可選, 默認爲table長度, 即從最後一個元素刪起。

5 table.sort (table [, comp])

對給定的table進行升序排序。

--表的連接
fruits = {"banana","orange","apple"}
-- 返回 table 連接後的字符串
print("連接後的字符串 ",table.concat(fruits))

-- 指定連接字符
print("連接後的字符串 ",table.concat(fruits,", "))

-- 指定索引來連接 table
print("連接後的字符串 ",table.concat(fruits,", ", 2,3))
--表的移除
fruits = {"banana","orange","apple"}

-- 在末尾插入
table.insert(fruits,"mango")
print("索引爲 4 的元素爲 ",fruits[4])

-- 在索引爲 2 的鍵處插入
table.insert(fruits,2,"grapes")
print("索引爲 2 的元素爲 ",fruits[2])

print("最後一個元素爲 ",fruits[5])
table.remove(fruits)
print("移除後最後一個元素爲 ",fruits[5])
索引爲 4 的元素爲     mango
索引爲 2 的元素爲     grapes
最後一個元素爲     mango
移除後最後一個元素爲     nil
--表的排序
fruits = {"banana","orange","apple","grapes"}
print("排序前")
for k,v in ipairs(fruits) do
        print(k,v)
end

table.sort(fruits)
print("排序後")
for k,v in ipairs(fruits) do
        print(k,v)
end
排序前
1    banana
2    orange
3    apple
4    grapes
排序後
1    apple
2    banana
3    grapes
4    orange

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章