【1】Lua数据类型
Lua语言共有8种基本类型
[1] nil 空。最简单,有且仅有值nil,表示一个无效值(在条件表达式中相当于false)
[2] boolean 布尔。包含两个值:false和true
[3] number 数字。double(双精度)类型(默认类型可以修改 luaconf.h 里的定义)
[4] string 字符串。字符串由一对双引号或单引号来表示
[5] function 函数。由C或Lua编写的函数
[6] userdata 自定义类型。表示任意存储在变量中的C数据结构
[7] thread 线程。表示执行的独立线程,用于执行协同程序
[8] table 表。Lua中的表(table)其实是一个“关联数组”(associative arrays),数组的索引可以是数字或者是字符串。
在Lua里,table的创建是通过“构造表达式”来完成,最简单构造表达式是{},用来创建一个空表。
【2】各种数据类型示例
(1)各种数据类型
1.1 打印各种数据类型
1 print(type("Good Good Study")) --> string 2 print(type(12.34)) --> number 3 print(type(print)) --> function 4 print(type(type)) --> function 5 print(type(true)) --> boolean 6 print(type(nil)) --> nil 7 print(type(type(X))) --> string
1.2 打印各种数据类型
1 print(type(a)) --> nil 2 a = 100 3 print(type(a)) --> number 4 a = "Day Day Up" 5 print(type(a)) --> string 6 a = print 7 print(type(a)) --> function 8 a(type(a)) --> function
1.3 待续
(2)nil
2.1 nil类型表示一种没有任何有效值,它只有一个值nil。例如:打印一个没有赋值的变量,结果为nil值。
1 print(type(X)) --> nil
2.2 nil 作比较时应该加上双引号:
1 print(type(X) == nil) --> false 2 print(type(X) == "nil") --> true
type(X) == nil结果为false,因为:
1 print(type(type(X))) --> string
2.3 对于全局变量和table,nil还有一个“删除”作用。如下示例:
1 luaTable = {10, 20, 30, 40, 50} 2 for k, v in pairs(luaTable) do 3 print(k .. " - " .. v) 4 end 5 6 luaTable[2] = nil 7 print("After set nil :: ") 8 for k, v in pairs(luaTable) do 9 print(k .. " - " .. v) 10 end 11 12 --[[ 13 1 - 10 14 2 - 20 15 3 - 30 16 4 - 40 17 5 - 50 18 After set nil :: 19 1 - 10 20 3 - 30 21 4 - 40 22 5 - 50 23 --]]
2.4 读入行数据作为数组元素
1 --[[读入行 作为数组元素]] 2 a = {} 3 for i = 1, 5 do 4 a[i] = io.read() 5 end 6 7 for i, v in pairs(a) do 8 print(i .. " ---> " .. v) 9 end 10 11 print(a) 12 13 --[[ 执行结果 14 10 15 11 16 12 17 13 18 14 19 1 ---> 10 20 2 ---> 11 21 3 ---> 12 22 4 ---> 13 23 5 ---> 14 24 ]]
2.5 待续
(3)boolean
3.1 lua语言中nil和false均是属于假,true和其他任何东西都属于真。
C++语言中0、NULL和false均是属于假,true其他任何非空的东西都属于真。
尤其注意:lua中0被视为真。
示例如下:
1 print(0) --> 0 2 print(0 == false) --> false 3 4 b = 0; 5 print(b == true) --> false 6 7 if(0 and b) then 8 print("0 and b is true") --> 0 and b is true 9 else 10 print("0 and b id false") 11 end 12 13 if(nil) then 14 print("nil is true") 15 else 16 print("nil is false") --> nil is false 17 end 18 19 print(nil) --> nil 20 print(false == nil) --> false 21 print(true == nil) --> false 22 print(true == "nil") --> false 23 print(false == "nil") --> false 24 print(false == "") --> false 25 print(100 == 100) --> true
3.2 待续
(4)number
4.1 待续
(5)string
5.1 字符串由一对双引号或单引号来表示:
1 string1 = "this is string1" 2 print(string1) --> this is string1 3 4 string2 = 'this is string2' 5 print(string2) --> this is string2
5.2 除过以上两种表示方式,还可以使用方括号“[[]]”来表示“一块”字符串:
1 html = [[ 2 <html> 3 <head></head> 4 <body> 5 <a href="http://www.baidu.com/">百度首页</a> 6 </body> 7 </html> 8 ]] 9 print(html) 10 11 --执行结果: 12 --[[ 13 <html> 14 <head></head> 15 <body> 16 <a href="http://www.baidu.com/">百度首页</a> 17 </body> 18 </html> 19 --]]
5.3 在对一个数字字符串进行算术操作时,Lua会尝试将这个数字字符串转换为一个数字:
1 print("1" + 2) --> 3 2 print("3" + "4") --> 7 3 print("5 + 6") --> 5 + 6 4 print("8" * "8") --> 64 5 --print("nil" + 1) --> syntax error
5.4 如上代码中“nil”+ 1执行报错了,字符串连接使用的是 ..,如下所示:
1 print("a"..'b'.."cdefg".." ".."hijk") --> abcdefg hijk 2 print(112 .. 110 .. 119) --> 112110119
5.5 使用 # 来计算字符串的长度,放在字符串前面。如下示例:
1 strLength = "www.baidu.com" 2 print(#strLength) -- 13 3 print(#"www.baidu.com") -- 13 4 print(#"www.bai du.com") -- 14 5 print(#"www.bai du.com") -- 14
5.6 字符串函数的应用示例
1 --1 大小写转换 2 --[[ 3 string.upper(argument) 4 string.lower(argument) 5 ]] 6 str = "abcdefghijklmnopqrstuvwxyz" 7 STR = string.upper(str) 8 str1 = string.lower(STR) 9 print(str) -- abcdefghijklmnopqrstuvwxyz 10 print(string.upper(str)) -- ABCDEFGHIJKLMNOPQRSTUVWXYZ 11 print(STR) -- ABCDEFGHIJKLMNOPQRSTUVWXYZ 12 print(str1) -- abcdefghijklmnopqrstuvwxyz 13 14 15 16 --2 在字符串中替换 17 --[[ 18 string.gsub(main string, find string, replace string, num) 19 main string 要替换的字符串 20 find string 被替换的字符 21 relace string 要替换的字符 22 num 替换次数 备注:可以忽略,默认是全部替换 23 ]] 24 25 str2 = "aaaaaaa" 26 print(string.gsub(str2, "a", "b", 3)) -- bbbaaaa 3 27 print(string.gsub(str2, "a", "c")) -- ccccccc 7 28 29 30 31 --3 搜索指定字符串 32 --[[ 33 在一个指定的目标字符串中搜索指定的内容(第三个参数为起始索引),返回其具体位置。不存在则返回nil。 34 ]] 35 str3 = "Welcome to Beijing" 36 print(string.find(str3, "Beijing")) -- 12 18 37 38 local index = string.find(str3, "Beijing") 39 print(index) -- 12 40 41 print(string.find(str3, "Beijing", 12)) -- 12 18 42 print(string.find(str3, "Beijing", 13)) -- nil 43 44 --4 字符串反转 45 --[[ 46 string.reverse(argument) 47 ]] 48 str4 = "Welcome to xian." 49 print(string.reverse(str4)) -- .naix ot emocleW 50 51 52 --5 格式化字符串 53 --[[返回一个类似于printf的格式化字符串 54 string.format(...) 55 ]] 56 57 str5 = "the value is :: %d" 58 print(string.format(str5, 10)) -- the value is :: 10 59 60 61 --6 整型数值与字符相互转换 62 --[[将整型数字转成字符并连接string.char(argument) 63 将字符转成整型数字值(可以指定某个字符,默认是第一个字符) 64 ]] 65 print(string.char(97, 98, 99, 100)) -- abcd 66 str6 = "ABCDE" 67 print(string.byte("ABCD", 4)) -- 68 68 print(string.byte("ABCD")) -- 65 69 70 --7 计算字符串长度 71 --[[ 72 string.len(argument) 73 ]] 74 print(string.len("abcde")) -- 5 75 76 77 --8 返回字符串string的n个拷贝 78 --[[ 79 string.rep(string, n) 80 ]] 81 print(string.rep("abcde ", 3)) -- abcde abcde abcde 82 83 --9 链接两个字符串 84 --[[ 85 .. 86 ]] 87 print("Welcome ".."to ".."Beijing") -- Welcome to Beijing 88 89 90 --10 gmatch接口 91 --[[string.gmatch(str, pattern) 92 返回一个迭代器函数,每一次调用这个函数,返回一个在字符串str找到的下一个符合pattern描述的子串。如果参数pattern描述的字符串没有找到,迭代函数返回nil 93 ]] 94 local str10_1 = "Hello World By Lua" 95 for word in string.gmatch(str10_1, "%a+") do 96 print(word) 97 end 98 99 --[[执行结果 100 Hello 101 World 102 By 103 Lua 104 ]] 105 106 local str10_2 = "110abc119,def,120,ghij" 107 local ret_func_itor = string.gmatch(str10_2, "%d+") 108 109 -- 查看func_itor类型 110 print("ret_func_itor is", ret_func_itor) -- func_itor is function: 02D1DAC8 111 112 -- 第一次调用函数func_itor 113 print("ret_func_itor ret is ", ret_func_itor()) -- ret_func_itor ret is 110 114 115 -- 再次调用函数func_itor 116 print("ret_func_itor ret is ", ret_func_itor()) -- ret_func_itor ret is 119 117 118 -- 再次调用函数func_itor 119 print("ret_func_itor ret is ", ret_func_itor()) -- ret_func_itor ret is 120 120 121 -- 再次调用函数func_itor 122 print("ret_func_itor ret is ", ret_func_itor()) -- ret_func_itor ret is 123 124 125 -- 使用循环来打印 126 local str10_3 = "hello world by Lua" 127 local index = 1 128 print(" output capture using loop:") 129 for word in string.gmatch(str10_3, "%a+") do 130 print(index, word) 131 index = index + 1 132 end 133 134 --[[执行结果 135 output capture using loop: 136 1 hello 137 2 world 138 3 by 139 4 Lua 140 ]] 141 142 -- 查找属性对 143 local str10_4 = "from=world, to=Lua, name=kaizen" 144 print(" output attr pair capture using loop:") 145 for k, v in string.gmatch(str10_4, "(%w+)=(%w+)") do 146 print(k, v) 147 end 148 149 --[[执行结果 150 output attr pair capture using loop: 151 from world 152 to Lua 153 name kaizen 154 ]] 155 156 local str10_5 = "fadfasd,.;p[];'asd" 157 local func_numitor = string.gmatch(str10_5, "%d+") 158 local numret = func_numitor() 159 print(" numret ret is", numret) 160 161 --[[执行结果 162 numret ret is nil 163 ]]
5.7 可以通过数值来指定字符串中的字符
1 --[[可以通过数值来指定字符串中的字符。 2 数值以转义序列“<ddd>”给出,其中<ddd>是一个至多3个十进制数字组成的序列]] 3 4 print("97bcdefg10hijklmn49") 5 6 --[[执行结果 7 abcdefg 8 hijklmn1 9 ]]
5.8 字符串格式化format函数
1 str = string.format("字符串:%s 整数:%d 小数:%f 十六进制数:%X", "zhongguorenmin", 1, 1.23, 456) 2 print(str) 3 4 --[[ 5 字符串:zhongguorenmin 6 整数:1 7 小数:1.230000 8 十六进制数:1C8 9 ]]
5.9 待续
(6)function
6.1 在Lua中,函数可以存在变量里:
1 function factorial1(n) 2 if n == 0 then 3 return 1 4 else 5 return n * factorial1(n - 1) 6 end 7 end 8 9 print(factorial1(5)) --> 120 10 11 factorial2 = factorial1 12 print(factorial2(5)) --> 120
6.2 function可以以匿名函数(anonymous function)的方式通过参数传递
1 function testFun(tab, fun) 2 for k, v in pairs(tab) do 3 print(fun(k, v)); 4 end 5 end 6 7 8 tab = {key1 = "val1", key2 = "val2"}; 9 testFun(tab, 10 function(key, val) --匿名函数 11 return key .. " = " .. val; 12 end 13 ); 14 --执行结果 15 --[[ 16 key1 = val1 17 key2 = val2 18 --]]
6.3 待续
(7)userdata
7.1 待续
(8)thread
8.1 待续
(9)table
9.1 创建一个空表
1 --1.创建一个空表 2 local tab1 = {}
9.2 初始化表,且遍历表
1 --2.直接初始化表 2 local tal2 = {"apple", "pear", "orange", "grape"} 3 --遍历表 4 for k, v in pairs(tal2) do 5 print("key", k, ": value", v) 6 end 7 8 --执行结果 9 --[[ 10 key 1 : value apple 11 key 2 : value pear 12 key 3 : value orange 13 key 4 : value grape 14 ]]
9.3 关联数组,数组的索引可以是数字或字符串
1 array = {} 2 array["key"] = "value" 3 key = 10; 4 array[key] = 20 5 array[key] = array[key] + 11; 6 for k, v in pairs(array) do 7 print(k .. " : " .. v) 8 end 9 10 --执行结果 11 --[[ 12 key : value 13 10 : 31 14 --]] 15 16 ar = {} 17 for i = 1, 10 do 18 ar[i] = i 19 end 20 21 ar["key"] = "val" 22 print(ar["key"]) 23 print(ar["none"]) 24 25 for k, v in pairs(ar) do 26 print(k .. " : " .. v) 27 end 28 29 --执行结果 30 --[[ 31 val 32 nil 33 1 : 1 34 2 : 2 35 3 : 3 36 4 : 4 37 5 : 5 38 6 : 6 39 7 : 7 40 8 : 8 41 9 : 9 42 10 : 10 43 key : val 44 ]]
9.4 注意观察以上几个示例,Lua里表的初始索引一般以1开始。不同于其他语言把0作为数组的开始索引。
1 local tbl = {"apple", "pear", "orange", "grape"} 2 for key, val in pairs(tbl) do 3 print("Key", key) 4 end 5 6 --执行结果 7 --[[ 8 Key 1 9 Key 2 10 Key 3 11 Key 4 12 ]]
9.5 表的值置为nil,表示移除引用。
1 --当我们定义table a 并设置元素,然后将 a 赋值给 b,则 a 与 b 都指向同一个内存。 2 --如果 a 设置为 nil ,则 b 同样能访问 table 的元素。 3 --如果没有指定的变量指向a,Lua的垃圾回收机制会清理相对应的内存。 4 5 -- 简单的 table 6 mytable = {} 7 print("mytable 的类型是 ", type(mytable)) 8 9 mytable[1] = "Lua" 10 mytable["wow"] = "修改前" 11 print("mytable 索引为 1 的元素是 ", mytable[1]) 12 print("mytable 索引为 wow 的元素是 ", mytable["wow"]) 13 14 -- alternatetable和mytable的是指同一个 table 15 alternatetable = mytable 16 print("alternatetable 索引为 1 的元素是 ", alternatetable[1]) 17 print("mytable 索引为 wow 的元素是 ", alternatetable["wow"]) 18 19 alternatetable["wow"] = "修改后" 20 print("mytable 索引为 wow 的元素是 ", mytable["wow"]) 21 22 -- 释放变量 23 mytable = nil 24 print("mytable 是 ", mytable) 25 --print("mytable[1]", mytable[1]) --> syntax error 26 27 -- alternatetable 仍然可以访问 28 print("alternatetable 索引为 wow 的元素是 ", alternatetable["wow"]) 29 30 alternatetable = nil 31 print("alternatetable 是 ", alternatetable) 32 33 --执行结果 34 --[[ 35 mytable 的类型是 table 36 mytable 索引为 1 的元素是 Lua 37 mytable 索引为 wow 的元素是 修改前 38 alternatetable 索引为 1 的元素是 Lua 39 mytable 索引为 wow 的元素是 修改前 40 mytable 索引为 wow 的元素是 修改后 41 mytable 是 nil 42 alternatetable 索引为 wow 的元素是 修改后 43 alternatetable 是 nil 44 ]]
9.6 表操作
[1] concat方法
1 --table.concat (table [, sep [, start [, end]]]): 2 --concat是concatenate(连锁, 连接)的缩写. 3 --table.concat()函数列出参数中指定table的数组部分从start位置到end位置的所有元素, 元素间以指定的分隔符(sep)隔开 4 5 fruits = {"banana","orange","apple"} 6 -- 返回 table 连接后的字符串 7 print("连接后的字符串 ",table.concat(fruits)) 8 9 -- 指定连接字符 10 print("连接后的字符串 ",table.concat(fruits, ", ")) 11 12 -- 指定索引来连接 table 13 print("连接后的字符串 ",table.concat(fruits, ", ", 2, 3)) 14 15 --执行结果 16 --[[ 17 连接后的字符串 bananaorangeapple 18 连接后的字符串 banana, orange, apple 19 连接后的字符串 orange, apple 20 --]]
[2] 插入和移除
1 --table.insert (table, [pos,] value): 2 --在table的数组部分指定位置(pos)插入值为value的一个元素. pos参数可选, 默认为数组部分末尾. 3 --table.remove (table [, pos]) 4 --返回table数组部分位于pos位置的元素. 其后的元素会被前移. pos参数可选, 默认为table长度, 即从最后一个元素删起。 5 6 7 fruits = {"banana", "orange", "apple"} 8 9 -- 在末尾插入 10 table.insert(fruits, "mango") 11 print("索引为 4 的元素为 ", fruits[4]) 12 13 -- 在索引为 2 的键处插入 14 table.insert(fruits, 2, "grapes") 15 print("索引为 2 的元素为 ", fruits[2]) 16 17 print("最后一个元素为 ", fruits[5]) 18 19 table.remove(fruits) 20 print("移除后, 最后一个元素为 ", fruits[5]) 21 22 table.remove(fruits, 1) 23 print("移除后, 索引为 1 的元素为 ", fruits[1]) 24 25 --[[ 26 索引为 4 的元素为 mango 27 索引为 2 的元素为 grapes 28 最后一个元素为 mango 29 移除后, 最后一个元素为 nil 30 移除后, 索引为 1 的元素为 grapes 31 --]]
[3] 排序
1 -table.sort (table [, comp]) 2 --对给定的table进行升序排序。 3 4 --3.1 默认排序示例 5 fruits = {"banana", "orange", "apple", "grapes", "melon"} 6 print("排序前") 7 for k, v in ipairs(fruits) do 8 print(k, v) 9 end 10 --排序 11 table.sort(fruits) 12 print("排序后") 13 for k, v in ipairs(fruits) do 14 print(k, v) 15 end 16 17 --执行结果 18 --[[ 19 排序前 20 1 banana 21 2 orange 22 3 apple 23 4 grapes 24 5 melon 25 排序后 26 1 apple 27 2 banana 28 3 grapes 29 4 melon 30 5 orange 31 --]] 32 33 --3.2 键值排序 34 local test1 = {a = 1, f = 9, d = 2, c = 8, b = 5} 35 local key_test = {} 36 for val in pairs(test1) do 37 table.insert(key_test, val) --提取test1中的键值插入到key_test表中 38 end 39 40 table.sort(key_test) 41 for i, v in pairs(key_test) do 42 print(v, test1[v]) 43 end 44 45 --执行结果 46 --[[ 47 a 1 48 b 5 49 c 8 50 d 2 51 f 9 52 ]] 53 54 --3.3 值排序之数组模式 55 local test0 = {1, 9, 2, 8, 3, 7, 4, 6} 56 table.sort(test0) --从小到大排序,默认方式 57 for i, v in pairs(test0) do 58 io.write(v.." ") 59 end 60 61 print(""); 62 63 table.sort(test0, function(a, b) return a > b end) --从大到小排序 64 for i, v in pairs(test0) do 65 io.write(v.." ") 66 end 67 print(" ") 68 69 --[[ 70 1 2 3 4 6 7 8 9 71 9 8 7 6 4 3 2 1 72 ]] 73 74 --3.4 值排序之表单模式 75 local test2 = 76 { 77 {id = 1, name = "zhao"}, 78 {id = 9, name = "liu"}, 79 {id = 2, name = "wang"}, 80 {id = 8, name = "xi"}, 81 {id = 5, name = "qin"}, 82 } 83 table.sort(test2, function(a,b) return a.id < b.id end) 84 for i in pairs(test2) do 85 print(test2[i].id, test2[i].name) 86 end 87 --[[ 88 1 zhao 89 2 wang 90 5 qin 91 8 xi 92 9 liu 93 ]]
[4] 待续
9.7 计算表长度
1 fruits = {"banana", "orange", "apple", "grapes", "melon", nil, "peach"} 2 print(#fruits) --> 7 3 print(table.getn(fruits)) --> 7 4 5 local myTable1 = {1, 2, 3} 6 print("table1 length :: ", table.getn(myTable1)) --> 3 7 8 local myTable2 = {1, a = 2, 3} 9 print("table2 length :: ", table.getn(myTable2)) --> 2 10 print(myTable2.a) --> 2 11 12 13 local myTable3 = {[1] = 2, [2] = 3, [3] = 10} 14 print("table3 length :: ", table.getn(myTable3)) --> 3 15 16 local myTable4 = {[1] = 1, [2] = 2, [4] = 4} 17 print("table4 length :: ", table.getn(myTable4)) --> 4 18 19 local myTable5 = {[1] = 1, [2] = 2, [5] = 5} 20 print("table5 length :: ", table.getn(myTable5)) --> 2 21 22 local myTable6 = {1, [3] = 3, 4} 23 print("table6 length :: ", table.getn(myTable6)) --> 3 24 25 local myTable7 = {1, nil} 26 print("table7 length :: ", table.getn(myTable7)) --> 1 27 28 local myTable8 = {1, nil, 2} 29 print("table8 length :: ", table.getn(myTable8)) --> 3 30 31 local myTable9 = {1, nil, 2, nil} 32 print("table9 length :: ", table.getn(myTable9)) --> 1 33 34 local myTable10 = {1, nil, 2, nil, 3, nil} 35 print("table10 length :: ", table.getn(myTable10)) --> 3 36 37 local myTable11 = {1, nil, 2, nil, 3, nil, 4, nil} 38 print("table11 length :: ", table.getn(myTable11)) --> 1
Lua里计算表长度可以使用“#”或者getn接口。示例如下:
你看懂了?你看不懂?难道真看不懂?难道我写错了?
唉~ 看不懂就对了。。。。我也看不懂。。。待剖析源码。
9.8 表其他待续
(10)总结
每种数据类型都各有特点,掌握得熟练还需多应用与摸索学习。
【3】总结
Lua是动态类型语言,变量不要类型定义,只需要为变量赋值。值可以存储在变量中,作为参数传递或结果返回。
Good Good Study, Day Day Up.
顺序 选择 循环 总结