Lua数据类型

【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\0du.com")  -- 14
5 print(#"www.bai\ndu.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("\noutput 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("\noutput 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("\nnumret ret is", numret)
160 
161 --[[执行结果
162 numret ret is    nil
163 ]]

5.7 可以通过数值来指定字符串中的字符

1 --[[可以通过数值来指定字符串中的字符。
2 数值以转义序列“\<ddd>”给出,其中<ddd>是一个至多3个十进制数字组成的序列]]
3 
4 print("\97bcdefg\10hijklmn\49")
5 
6 --[[执行结果
7 abcdefg
8 hijklmn1
9 ]]

5.8 字符串格式化format函数

1 str = string.format("字符串:%s\n整数:%d\n小数:%f\n十六进制数:%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.

顺序 选择 循环 总结