关闭

Lua学习笔记(二)

标签: lua操作符控制结构泛型forlua基础
225人阅读 评论(0) 收藏 举报
分类:

一、操作符简介

如同C语言,Lua的操作符也是常见的那几个,比如,算数类的有:加减乘除,求模,指数,负号。关系类的有:大(等)于,小(等)于,等于和不等于。逻辑类的有:与或非。

算数类的都是常识,不赘述,我们先来看关系类

Lua的关系操作运算结果为true或false,其中,不等于用“~=”表示,这里应该注意的是:对于相等性比较的两边,应具有相同的类型,否则直接返回true。如果参与比较的两边类型相等,那么则根据两边的类型来进一步比较,例如,数值型按照数字大小对比,而table则是引用比较,即不比较内容,比较引用的对象,举个书上的例子:

a = {}
b = {}
a.x = 1; a.y = 0
b.x = 1; b.y = 0
c = a

--该例子的对比结果为:a等于c,a不等于b,b不等于c

对于大小比较,最好是是数值和数值,字符串和字符串这样的比较。Lua会按照字母顺序依次对字符串做比较,而数值和字符串对比则会引发错误。其他类型不能作为大小比对。

关于逻辑类,与或非,对应and,or,not。与和或操作,即a and b,a or b,在a和b都不等于nil的情况下,返回ture或false。有nil的情况下可能返回nil,nil和false称为“假”,其他统称为“真”。以下为测试用例:

a = 1
b = 6
c = false
print(a and b)
print(b and a)
print(a and c)
print(b and true)
print(a and nil)
print(c and a)
print(a or b)
print(b or a)
print(b or c)
print(c or b)
print(true or a)
print(c or nil)
print(nil or c)

--[[ 返回值:
6
1
false
true
nil
false
1
6
6
6
true
nil
false
--]]

可以看出:对于and操作,左边为真,则返回右边的值,左边为假,则跳过右边,返回左边的值;对于or操作,左边为真,则跳过右边,返回左边的值,左边为假,则返回右边的值。

而not操作则是取反,返回ture或false,需要注意的是,0是实数,在Lua中代表真,空字符串也是真,not 0的结果和not ” “的结果都是false,这点很容易搞混,我曾经在项目中碰到这样的bug,百思不得其解,最后主程告诉我”not 0 == false”,初学者判断时容易搞混,要记住!测试几个not用法:

a = 1
b = "x"
print(not a)
print(not false)
print(not nil)
print(not true)
print(not b)
print(not 0)

--[[ 返回值:
false
true
true
false
false
false
--]]

来看几个教程列出的技巧:

x = x or v

这段代码可以在没有设置x的时候给予其一个默认值v。分析:x or v,若x有赋值,且不为nil和false,则返回x,若x无赋值(=nil)或赋予false,则返回v。

(a and b) or c –b不为假

这段代码等价于C语言的a ? b : c,分析:在b为真的前提下,若a为假,a and b 为假且返回a,a or c返回c,因此表达式返回c;若a为真,a and b 为真且返回b,b or c返回b,则表达式返回b。符合a ? b : c的规则。

以上是Lua中的操作符基础,下面来看它们的优先级。(由高至低)


^(指数运算)

not,#(长度操作符),-(负号)

*,/,%

+,-(减号)

..(字符串连接)

<,>,<=,>=,~=,==

and

or


二、语句介绍

Lua和C差不多,赋值操作将等号右边的值给左边,也有if和while的控制语句,但应注意语法:

if控制结构:if 条件 then 结果 end,当有else时,if 条件 then 结果1 else 结果2 end,当有多重嵌套,表现为:

--伪代码

if 条件1 then

结果1

elseif 条件2 then

结果2

else 条件3 then

结果3

end

这里要注意几点:条件之后有个then不要忘了,整个控制结构结束时有个end别漏了。受C的影响,一开始是很容易忽略的,没有加上则会产生syntax error,久了习惯就好。嵌套时else和if是不分开的,如果写成else if是错的。

while控制结构:while 条件 do 循环体 end

和C一样,先检测条件,若为真,进入循环体一次,若为假,退出。这里要注意的是条件之后有个do不要忽略,最后结束有个end不要遗漏。

repeat控制结构:repeat 循环体 until 条件

即C语言的do-while结构,先执行循环体,再判定条件,若为真,继续循环,若为假,退出。这里要注意的是这个循环体至少都会执行一次,整个结构没有end,不要随意添加。若在循环体中有local声明的局部变量,在until的条件测试中也可以使用这个变量。

for循环(数字型):for var=exp1,exp2,exp3 do 循环体 end

这个的含义是变量var从exp1到exp2变化,每次变化的步长是exp3。其中exp3可以不指定,则默认为1。exp2可以设置为math.huge,则为不设上限。要注意的是这里for的条件内容不需要括号抱起来,跟在条件后面有个do,结尾有个end,都不要遗漏了。而for后面的三个表达式是在循环开始前一次求值,只执行一次,并且控制变量会自动声明为for的局部变量,循环结束后则不存在。

break和return:break是跳出包含它的内部循环,在多重循环中,会跳出内部后在外部一层继续执行。return是从函数返回结果,或结束一个函数执行。

以上是和C语言类似的几个语句,下面来看Lua的特殊语句:

首先,Lua支持多重赋值,并且会将等号右边的数量调整到和左边的个数一致,来看例子:

a,b,c,d,e = 1,2,3,4,5,6,7
print(a,b,c,d,e)

i,j,k,l,m,n = 1,2,3
print(i,j,k,l,m,n)

x=10
y=26
print(x,y)
x,y = y,x
print(x,y)

--[[返回值:
1   2   3   4   5
1   2   3   nil nil nil
10  26
26  10
--]]

可以看出,多重赋值情况下,若右边个数大于左边,则按顺序赋值后,抛弃多余的。若右边个数小于左边,则左边没赋值的置nil。第三个例子是交换操作,则不需要像C语言那样用temp中间数来交换两个数,因为多重赋值中,Lua会先对等号右边的元素求值,然后再赋值。

变量类型:Lua有全局变量和局部变量

声明一个变量,只需赋值即可,不需要诸如int,float,char之类的类型,Lua会根据你的赋值,自动判断这个变量的类型;若不赋值,则默认赋予nil。因此,Lua中只有全局和局部变量,局部变量是在变量前面加local,比如local x=0,这个x就是局部变量,若该声明在一个循环中,则循环退出后,变量就不可使用了。即局部变量的作用域是声明它的那个块。除了循环体,函数体,Lua还有程序块的概念,即可以使用以下语句来界定块:

do 程序体 end

在交互模式中用这种模式很方便,每当遇到do,解释器就不会单独执行一行一行的语句,直到遇到end,这样就可以很好地将local局部变量包括在内使用。而尽可能多使用局部变量也是Lua的作者所倡导的,毕竟这样做效率高,也避免污染全局环境,方便垃圾收集器回收无用变量。

最后我们来看下泛型for循环(与前面说的数字型for是不同的):

for i, v in ipairs(数组table) do 执行体 end

for k,v in pairs(通用table) do 执行体 end

泛型for是铜鼓迭代器函数来遍历table的所有值。这两个就是泛型for的语法,区别在于pairs是迭代table元素,key可以不是数值,每次循环,k赋值为索引,v赋值为索引对应值;而ipairs是迭代数组元素的,key是数值,每次循环,i赋值为索引值,v赋值为对应索引的数组元素值。泛型for看似简单,在Lua中的功能却非常强大,使用也很广泛,例如在做游戏项目的时候,寻路、遍历地图、碰撞检测等都可能要用到它。我们来看个简单的例子:

tbl={a = 6, b = 9, yes = 1, no = 0}
for k,v in pairs(tbl) do
print(k.." ".."=".." "..v)
end

--[[返回值:
a = 6
b = 9
yes = 1
no = 0
--]]


test={[1] = "yes", [2] = "Tuesday", [3] = "March"}
for i,v in ipairs(test) do
print(i.." ".."=".." "..v)
end

--[[返回值:
1 = yes
2 = Tuesday
3 = March
--]]

关于泛型for,后续在迭代器的介绍中还会有更详细的说明。本次学习笔记到此结束,下次将进入函数的学习。

0
0
查看评论
发表评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场

kafka学习笔记(2)

kafka的经典问题有这几个: 1.kafka节点之间如何备份? 2.kafka消息是否会丢失?为什么? 3.kafka最合理的配置是什么? 4.kafka的leader选举机制是什么? 5...
  • m0_37587447
  • m0_37587447
  • 2017-11-21 15:37
  • 21

PCIe 学习笔记(二)

pci note 2 -v0.1 2014.11.18 *** draft  本文继续pci note 1, 介绍pci_create_root_bus函数, 内核版本为3.18-rc1 ...
  • scarecrow_byr
  • scarecrow_byr
  • 2014-12-01 22:19
  • 1723

GreenSock动画平台学习笔记(一)TweenLite

转载:http://www.cnblogs.com/2050/archive/2010/10/10/1846983.html 静态属性 TweenLite.defaultEas...
  • happyrabbit456
  • happyrabbit456
  • 2013-01-31 11:19
  • 655

网络编程学习笔记整理(二)

摘录笔记 《TCP/IP高效编程 改善网络程序的44个技巧》socket的创建函数int socket (int domain,int type, int protocol)参数说明protocol需...
  • stecdeng
  • stecdeng
  • 2017-02-23 14:47
  • 189

密码学学习笔记

1.流密码每次加密数据流的一位或一个字节,分组密码是将一个明文分组作为整体加密并且通常得到的是与明文等长的密文分组。 2.现在使用的大多数对称分组加密算法都是基于Feistel分组密码结构的。
  • u011130578
  • u011130578
  • 2015-12-22 13:57
  • 794

Unity3D之Mecanim动画系统学习笔记(三):Animation View

动画组件之间的关系 我们先看一张图: 这里我们可以看到,我们在GameObject之上绑定的Animator组件是控制模型进行动画播放的。 而其属性Controller则对应一个Anim...
  • cbbbc
  • cbbbc
  • 2017-02-19 18:20
  • 318

Netty4学习笔记(一) 基础篇

在开始学习Netty之前,我们先对Unix系统常用的I/O模型进行介绍,然后对Java的I/O历史演进历史进行简单的说明。Linux 网络I/O模型简介Linux内核将所有外部设备都看做一个文件来操作...
  • FX_SKY
  • FX_SKY
  • 2016-03-15 01:38
  • 6229

比特币源码学习笔记(二)

第二章 本章继上一章交易创建之后介绍比特币客户端序列化数据的过程。 比特币客户端所有的序列化函数均在serliaze.h中实现。其中,CDataStream类是数据序列化的核心结构。 CDataStr...
  • g2com
  • g2com
  • 2017-03-22 07:57
  • 1291

nginx学习(十二)——nginx+lua入门

参考文章:http://www.111cn.net/sys/nginx/106730.htm 1.hello lua nginx通过content_by_lua和content_by_lua_file...
  • xxcupid
  • xxcupid
  • 2016-09-13 10:49
  • 1317

《数据挖掘》学习笔记——认识数据(1)

一、数据属性定义:属性即一个数据的字段,在不同的领域有不同的等价叫法,例如:维度、特征、变量。 从具体事例角度看,数据的属性就像Excel表格的列,比如:
  • qqmindyourwill
  • qqmindyourwill
  • 2016-05-19 20:42
  • 346
    个人资料
    • 访问:31927次
    • 积分:532
    • 等级:
    • 排名:千里之外
    • 原创:22篇
    • 转载:0篇
    • 译文:0篇
    • 评论:6条
    最新评论