1. 程式人生 > >Lua程式設計(初級入門)

Lua程式設計(初級入門)

1.什麼是lua語言

輕量的指令碼語言,使用標準c語言的原始碼形式開發,目的為了嵌入應用程式中,為應用程式提供靈活的拓展和定製功能

 

2.lua與C#區別

幾乎所有平臺os都可以編譯執行,可以很方便的更新程式碼。

C#只能在特定的作業系統中編譯成dll檔案,然後打包進安裝包執行,在移動平臺上不能更新替換已有的dll檔案,除非重新下載

 

3.Lua的第一行程式碼

下載Lua安裝之後有兩個可執行的程式

一個是Lua,輸入Lua的程式碼直接可以執行。

還有一個時SciTE的一個Lua的IDE,SciTE要先儲存到本地(儲存的檔案要加.lua字尾),才能進行編譯執行。

 

4.print方法、單行和多行註釋

--單行註釋

--[[
多行註釋
--]]

 

5.Lua中的識別符號命名規則

標示符以一個字母A到Z或a到z或下劃線開頭

Lua是一個區分大小寫的程式語言

 

6.全域性變數

在預設情況下,變數總是認為時全域性的

全域性變數不需要宣告,給一個值賦值後,及建立了這個全域性變數

 一個變數沒有賦值的時候,它是nil

 

7.Lua資料型別

nil一個空的

boolean包括false and true

number包含小數和整數

string字串由一對雙引號或者單引號來表示

function由c或Lua編寫的函式

userdata表示任意儲存在變數中的C資料結構

thread表示執行的獨立線路,用於執行協同程式

table表型別,其實是一個關聯陣列

 

print(type("Hello world"))
print(type(1.66))
print(type(print))
Lua中type方法返回一個string的值,表示引數的型別,上面列印的值

string
number
function

 

8.nil的用法

任何一個沒有定義的值,都會是nil

通過將nil賦值給某個變數,可以置空變數的值,讓變數的值從記憶體釋放

 

9.boolean布林

如果把nil當作boolean型別,會被視為false

if true then
print("true")
end

if nil then
print("nil is true")
else
print("nil is false")
end

輸出

true
nil is false

 

10.number數字型別的用法

既可以表示整數也可以表示小數

 

11.string字串型別的用法

字串組拼

print("2".."2")

多行字串

html =
[[
<html>
<head></head>
<body>
<a href = "baidu">ok</a>
</body>
</html>

]]

運算字串變數的長度

print(#html)

 

12.table表的用法

表的使用

tab1 = {}
tab2 = {key = 100,key2 = "value2"}--初始化一個表
print(tab1)
print(tab2.key2)
print(tab2["key"])

輸出結果

table: 00A59270
value2
100

直接輸出得到的是table的記憶體地址,表中的值有兩種呼叫方式用點或者中括號,中括號中間要加雙引號

 

  在Lua中陣列是從1開始的

tab3 ={"test001","test200"}

print(tab3[1])
print(tab3["2"])

輸出結果

test001
nil

兩種索引的結果不一樣加上雙引號,就會索引雙引號之中的key的value

 

迴圈遍歷

for key,val in pairs(tab3) do
print(key..":"..val)
end

pairs是一個方法,將tab3中的鍵和值分別賦值給key和val,直到tab3中沒有值為止

 

table表中修改

通過點或者中括號來新增新的值給table

將鍵值對中的值設定為nil,就相當於直接刪除了這個鍵值對

在table中索引是不連續的,如果刪除了一個,後面的值不會向前移動

 

13.function函式的用法

階乘的Lua實現

在建立方法的時候,不用定義返回值和引數型別,引數在呼叫的時候決定型別,返回值也是在呼叫的時候直接返回

function fact(n)
	if n ==1 then
	return n;
	else
	return n*fact(n-1)
	end
end

print(fact(3))

 

function函式作為引數傳遞和匿名函式的用法

將定義的函式作為引數進行傳遞

function testFun(tab,fun)
	for k,v in pairs(tab) do
		fun(k,v)
	end
end
tab = {key1 = "val1",key2 = "val2"}

function	f1(k,v)
	print(k..":"..v)
end

testFun(tab,f1)

匿名函式

只能使用一次,在其他地方無法呼叫這個函式。一般情況下匿名函式程式碼比較短

testFun(tab,function(k,v) print(k.."  "..v)end)

 

14.字串常見操作

字串的替換和查詢


str = "sss.baid.com"
str4 = string.gsub(str,"s","w")

print(str,str4)

str5 = string.find(str,"com")
print(str5)

列印結果

sss.baid.com    www.baid.com
10

 

字串的組拼 %d代表數字型別,%s代表字串型別

n1=1
n2=1
str6 = string.format("add:%d+%d = %d",n1,n2,(n1+n2))
print(str6)

列印結果

add:1+1 = 2

 

將byte轉換成char型

mychar = string.char(98)
print(mychar)

將char型轉換成byte型

將字串中的第四個轉換成byte型別

mybyte = string.byte("abcd",4)
print(mybyte)

求一個字串的長度

length1 = string.len("abc")
print(length1)

返回一個字串的n次拷貝

str = string.rep("abc",4)
print(str)

匹配正則表示式

string.gmatch(str,pattern)

每一次使用這個函式,返回一個在字串str找到的下一個符合pattern描述的子串

 

15.Lua中陣列的基本特性和定義

Lua中陣列的遍歷

array = {"Lua","C#"}

for i = 1,2 do
	print(array[i])
end

Lua中多維陣列的實現

在一個表中再建立一個的表,這樣就是二維的陣列了

array = {}
for i =1,3 do
	array[i] = {}
	for j =1,2 do
		array[i][j] = i*j
		print(array[i][j])
	end
end

 

16.Lua中的迭代器函式

pairs就是一個迭代器,用來取得數組裡的每一個數據

ipairs按照索引從1開始,遞增遍歷,遇到nil值就停止

自定義迭代函式

不斷迭代直到control達到state的值

function square(state,control)
	if(control>=state) then
		return nil
	else
		control = control + 1
		return control,control*control
	end
end

for i,j in square,9,0 do
	print(i,j)
end

 

17.Lua中的表

Lua中的表如果有兩個引用

一個置為空,另一個表還在引用,那麼這個表就不會被釋放,直到兩個引用都置為空,這個表才會被置為空

表中的元素可以使用table.concat()方法進行拼接,方法返回值是一個字串

insert方法在table插入新的值

mytable = {"Lua","c#"}
table.insert(mytable,"java")

print(table.concat(mytable," "))

使用table中的remove方法移除指定位置的table的元素,insert在插入的時候出傳入一個值,就會在指定的位置插入元素

table.insert(mytable,1,"python")
table.remove(mytable,3)

表的排序

使用table中的sort方法對table中的元素進行排序,如果是字元,會根據ASCII碼進行排序

 

18.Lua中的模組和包

定義一個module

mytable = {"Lua","c#"}

mytable.func1 = function()
	print("this is module func")
end

return mytable
--引用模組
require "01"

mytable.func1()

C包

C包指用C語言寫的C包,一些c語言寫成的拓展的包

 

19.Lua中的元表(Metatable)

在普通表中拓展出來的,元表用來定義一些非常規的操作,是對普通表進行行為的擴充套件

mytable = {"Lua","java"}

mymetatable = {}--元表

mytable = setmetatable(mytable,mymetatable)--設定元表,返回普通表

print(getmetatable(mytable))--得到普通表對應的元表

使用setmetatable方法將元表和普通表關聯

使用getmetatable方法得到元表

 

元表中的__index鍵,設定了__index,在表中呼叫不存在的元素的時候,就會呼叫__index指定的相應方法

mymetatable = {
__index = function(tab,key)
	print("index func")
end
}--元表

mytable = setmetatable(mytable,mymetatable)--設定元表,返回普通表

print(mytable[10])

輸出結果

index func
nil

__index用來處理訪問到的索引不存在的時候,怎麼辦,不僅可以指向一個函式,也可以指向一個表。

 

__newindex在我們給表新增新的鍵值對的時候呼叫

mytable = {"Lua","java"}

mymetatable = {
__newindex = function(tab,key,value)
	print("key"..key..": get value "..value)
end
}--元表

mytable = setmetatable(mytable,mymetatable)--設定元表,返回普通表

mytable[5] = "python"

輸出結果:key5: get value python

 

__call鍵,在給表傳入一個值的時候呼叫

mytable = {"Lua","java"}

mymetatable = {
__call = function(tab,arg)
	print(arg)
end
}--元表

mytable = setmetatable(mytable,mymetatable)--設定元表,返回普通表

mytable(34)

輸出結果34

 

20.Lua協同程式

協程:有獨立的堆疊、獨立的區域性變數、獨立的指令指標

掛起一個函式也叫做暫停一個函式

定義和啟動協同程式

 coroutine.create定義協同函式

coroutine.resume啟動協同函式

--定義協同函式
co = coroutine.create(
	function (a,b)
		print(a+b)
	end
)
--啟動協同函式
coroutine.resume(co,23,1)

第二種定義和啟動方法

--定義協同函式
co = coroutine.wrap(
	function (a,b)
		print(a+b)
	end
)
--啟動協同函式
co(23,1)

停止協同函式,繼續執行主執行緒的情況。呼叫coroutine.yield()方法,掛起協同函式

--定義協同函式
co = coroutine.wrap(
	function (a,b)
		print(a+b)
		coroutine.yield()
		print(a-b)
	end
)
--啟動協同函式
co(23,1)

print("test")

輸出結果

23

test

再使用coroutine.resume()繼續函式執行,但是不用再給函式傳遞引數

 

resume方法返回第一個值為是否啟動了執行緒,第二個值是協同函式的返回值

--定義協同函式
co = coroutine.create(
	function (a,b)
		return a*b
	end
)
--啟動協同函式
res1,res2 = coroutine.resume(co,23,1)

print(res1,res2)

輸出結果:true    23

yield方法有多少個引數,都會傳遞出去

--定義協同函式
co = coroutine.create(
	function (a,b)
	coroutine.yield(a*b,a/b)
		return a+b
	end
)
--啟動協同函式
res1,res2,res3 = coroutine.resume(co,20,2)

print(res1,res2,res3 )

res1,res2 = coroutine.resume(co,20,2)

print(res1,res2 )

輸出結果:

true    40    10
true    22

 

協程程式和內部和外部(主程式)的資料傳輸

輸出當前協程的狀態

print(coroutine.status(co))

獲取當前正在執行的執行緒

print(coroutine.running())

resume和yield配合可以再主程式和開的子執行緒中進行資料的傳輸

 

23.Lua中的簡單模式下檔案的I/O

檔案讀取

file = io.open("data.txt","r")
io.input(file)

print(io.read())--讀取一行
print(io.read())

io.close(file)

檔案寫入

"w" 寫入檔案之前清空檔案中的原有內容,寫入檔案新的內容

"a" 在原有的內容的後面,新增新的內容

 

24.完全模式下的檔案讀取和寫入

通過file來進行檔案的讀取

file = io.open("data.txt","r")

print(file:read())

file:close()

 

25.Lua中的面向物件怎麼實現

面向物件特徵:封裝、繼承、多型、抽象

Lua中使用table+function來實現面向物件

--對於一個物件來說 屬性、方法

person = {name = "RP"}
person.eat = function ()
	print(person.name.." is eating")
end

person.eat()

另一種定義方法的方法,這種方法可以在內部呼叫self來呼叫自己的屬性

person = {name = "RP"}

function person:eat()
	print(self.name.." is eating")
end

person:eat()

當通過:呼叫的時候,系統過自動傳遞當前的table給self。

當通過. 呼叫方法的時候,self不會自動賦值,必須通過傳遞當前table給self

 

建立建構函式,用於構造擁有相同屬性和函式的物件

通過new()方法來建立很多個相同的物件

person = {name = "RP"}

function person:new()
	local t = {}
	--呼叫一個屬性的時候,如果t中不存在,那麼會在__index所指定的table中查詢
	setmetatable(t,{__index = self})
	return t
end

person1 = person:new()
person2 = person:new()
print(person1.name)
print(person1.name)

輸出結果:

RP

RP

 

繼承的實現

將new()方法建立的物件傳遞給student,student繼承了person的屬性、方法,stu繼承student(也可以呼叫person的屬性方法)

person = {name = "RP"}

function person:new()
	local t = {}
	--呼叫一個屬性的時候,如果t中不存在,那麼會在__index所指定的table中查詢
	setmetatable(t,{__index = self})
	return t
end

student = person:new()
student.grade = 1

stu = student:new()

print(stu.grade)