笨木头Lua专栏 函数的几个特别之处

【笨木头Lua专栏】基础补充02:

【木头Cocos2d-x 029Lua篇(第04章):来点高难度的,获取Lua表结构数据

 

只是获取一个全局变量什么的太没意思了,今天我们来玩个高难度的——获取Lua表结构的数据。

(旁白:O O!我是不是该说点什么?)

 

上一章传送门:http://blog.csdn.net/musicvs/article/details/8445027

 

笨木头花心贡献,啥?花心?不呢,是用心~

转载请注明,原文地址
http://blog.csdn.net/musicvs/article/details/8445079

正文:

 

 

1. 什么是table

tableLua里最强大的数据类型,我们可以当成是数组,但是它又和数组有点不一样,建议大家看看Lua的语法教程,因为我对table也没有熟悉到可以给大家解释的程度。

(旁白:那你还写什么教程。。。)

 

2. 获取table变量

现在,我们给helloLua.lua文件添加一个table全局变量:

  1. -- helloLua.lua文件  
  2. myName = "beauty girl"  
  3.   
  4. helloTable = {name = "mutou", IQ = 125}  


 

我们看到,多了一个helloTable的变量,它和数组十分相似,又和HashMap有点类似,总之它很强大。

(旁白:我觉得亮点是,你的IQ125?我觉得乘以2的话,还有点可能~!)

话说,125乘以2等于多少?...250 ....O O

获取helloTable变量的方式和以前是一样的:

  1. /* 取得table变量,在栈顶 */  
  2.     lua_getglobal(pL, "helloTable");  


 

这样,helloTable变量就被存放到栈顶。

可我们并不是要取table变量,因为C++中是无法识别Luatable类型的,所以我们要取得table中具体的值,也就是nameIQ的值。

 

3. lua_gettable函数

有一个和lua_getglobal类似的函数,叫做lua_gettable,顾名思义,它是用来取得table相关的数据的。

(旁白:废话少点好吧= =

 

lua_gettable函数会从栈顶取得一个值,然后根据这个值去table中寻找对应的值,最后把找到的值放到栈顶。

lua_pushstring()函数可以把C++中的字符串存放到Lua的栈里;

然后再用lua_gettable()取执行前面所说的步骤,lua_gettable的第二个参数是指定的table变量在栈中的索引。

(旁白:小笨木,我被你绕晕了。。。)

 

为了照顾旁白这个笨蛋,我们画个图来理解:

这是初始状态,堆栈里还没有任何东西,那么,现在要先把helloTable变量放到栈顶:

  1. /* 取得table变量,在栈顶 */  
  2.     lua_getglobal(pL, "helloTable");  


 

然后就变成了这样:

接着,我们要取得tablename对应的值,那么,先要做的就是把”name”字符串入栈:

  1. /* 将C++的字符串放到Lua的栈中,此时,栈顶变为“name”, helloTable对象变为栈底 */  
  2.     lua_pushstring(pL, "name");  


 

然后变成这样:

(旁白:不带这样啊,你偷偷加上了栈的索引~!)

 

注意了,我把栈的索引也加上了,因为我们即将要使用,这次我们用负数索引(不了解负数的索引的朋友请阅读第03章的教程哈~)。

由于”name”的入栈,现在helloTable变量已经不在栈顶了。

接着,我们调用要做最重要的一步了,取得nametable中对应的值:

  1. /*  
  2.         从table对象寻找“name”对应的值(table对象现在在索引为-2的栈中,也就是当前的栈底), 
  3.         取得对应值之后,将值放回栈顶 
  4.     */  
  5.     lua_gettable(pL, -2);  


 

此时,栈变成这样:

tupian1

(旁白:发生什么事?为什么“mutou”突然出现在栈顶?!为毛!是你自己画上去的吧!)

 

lua_gettable倒底做了什么事情?

首先,我们来解释一下lua_gettable的第二个参数,-2是什么意思,-2就是刚刚helloTable变量在栈中的索引。

然后,Lua会去取得栈顶的值(之前的栈顶是”name”),然后拿着这个值去helloTable变量中寻找对应的值,当然就找到”mutou”了。

最后,Lua会把找到的值入栈,于是”mutou”就到了栈顶了。

(旁白:你妹纸的。。。没事,我就骂骂人)

 

最后我们只需要取出栈顶的数据就可以了,完整代码如下:

  1. /* 初始化 */  
  2.     lua_State* pL = lua_open();  
  3.     luaopen_base(pL);  
  4.   
  5.     /* 执行脚本 */  
  6.     luaL_dofile(pL, "helloLua.lua");  
  7.   
  8.     /* 取得table变量,在栈顶 */  
  9.     lua_getglobal(pL, "helloTable");  
  10.   
  11.     /* 将C++的字符串放到Lua的栈中,此时,栈顶变为“name”, helloTable对象变为栈底 */  
  12.     lua_pushstring(pL, "name");  
  13.   
  14.     /*  
  15.         从table对象寻找“name”对应的值(table对象现在在索引为-2的栈中,也就是当前的栈底), 
  16.         取得对应值之后,将值放回栈顶 
  17.     */  
  18.     lua_gettable(pL, -2);  
  19.   
  20.     /* 现在表的name对应的值已经在栈顶了,直接取出即可 */  
  21.     const char* sName = lua_tostring(pL, -1);  
  22.     CCLOG("name = %s", sName);  


 

好了,本章到此结束。

 

 

.

版权声明:本文为博主原创文章,未经博主允许不得转载。

18


没想到距离上一篇基础补充已经过了1年多了,最近准备捡回Lua,把基础都补补,今天来聊聊Lua的函数吧~

 

 0.环境

我突然对Lua又大感兴趣的最主要原因是,Cocos Code IDE开始浮出水面了,它是Cocos2d-x官方出的一款专门针对Cocos2d-x+Lua或JS的IDE,试着用了,虽然不能说很完美,但,很值得期待。

 

所以,本文使用的Lua编辑器就选它了,大家就随意吧~

笨木头花心贡献,哈?花心?不,是用心~

转载请注明,原文地址:http://www.benmutou.com/archives/1702

文章来源:笨木头与游戏开发

 

1.扫盲——Lua的函数

Lua要创建和调用函数都十分简单,如代码:

  1. function mutou()
  2. print("这绝对不是广告:www.benmutou.com");
  3. end

这就创建了一个函数了,调用函数也十分简单:

  1. mutou();

然后运行,就能看到输出了,print也是一个函数,唉,不多唠叨了。

 

2.扫盲——函数的参数

刚刚的mutou函数,我们修改一下参数,如代码:

  1. function mutou(name, age)
  2. print(name);
  3. print(age);
  4. end

我们给mutou添加两个参数,一个是name,代表名字,一个是age,代表年龄。

顺便一提,Lua是没有变量类型这一说法的,变量会根据赋予的值而展现出不一样的类型。

 

我们试试这样调用mutou函数:

  1. mutou("木头", 25);

 
然后运行,输出如下:

[LUA-print] 木头

[LUA-print] 25
很正常,我喜欢~

 

3.海量的心——函数参数个数自适应

Lua的函数心胸比较宽广,对于我们传递进去的参数,全部都会忍受,但,它会按照它的规则进行筛选。

 

继续刚刚那个mutou函数,我们试试这样调用:

  1. mutou("木头");

少给了一个参数,但,这和C++或者Java等语言不一样,它不会造成编译错误,仍然可以正常运行。输出如下:

[LUA-print] 木头

[LUA-print] nil

对于缺少的参数,它会自动用nil来代替。

 

再然后,既然可以少给参数,那自然也可以多给参数了,试试这样调用:

  1. mutou("木头", 25, "旁白", 45);

(小若:你才45岁!你全身细胞都是45岁!)

输出如下:

[LUA-print] 木头

[LUA-print] 25

 

结果自然是,多出参数会被舍去。

至于这是好事还是坏事,就看是谁使用了~

 

4.多重返回值

没错,Lua似乎把我们想要的能偷懒的所有事情都给想到了,并且给实现了。

Lua的函数支持返回多个值,继续修改mutou函数,如下:

  1. function mutou(name, age)
  2. return name, age;
  3. end

把传进去的两个参数又给return回来了,试试这样调用:

  1. local name = mutou("木头", 25);
  2. print(name);

调用mutou函数,并且用一个变量保存返回值,输出结果为:

[LUA-print] 木头

 

因为我们只用了一个变量来保存返回值,所以即使函数返回了两个值,我们也只能获取到一个,要想获取到两个值,就十分简单了,如下:

  1. local name, age = mutou("木头", 25);
  2. print(name .. ":" .. age);

输入结果如下:

[LUA-print] 木头:25

又顺便一提,用符号“..”可以连接字符串,这里就不多说了~

 

返回值和参数一样,如果我们尝试用三个变量去获取函数返回值,也不会造成编译错误,如下:

  1. local name, age, hehe = mutou("木头", 25);
  2. print(name .. ":" .. age);
  3. print(hehe);

输入如下:

[LUA-print] 木头:25

[LUA-print] nil

 

对于多出的变量,会赋予nil值,虽然这不会造成编译错误,但是也可能会造成运行时错误。

比如,用“..”符号去连接nil值,就会报错。

 

5.多重返回值的特点1——必须是表达式的最后一个元素

对于有多个返回值的函数,不一定所有情况下都能返回多个值。

先来看这样一种特别的情况,仍然是刚刚的mutou函数,我们这样调用:

  1. local a, b, c = "first", mutou("木", 25);
  2. print(a);
  3. print(b);
  4. print(c);

输出结果如下:

[LUA-print] first

[LUA-print] 木

[LUA-print] 25

 

没错,Lua的赋值语句是支持逗号表达式的(也就是用多个值给多个变量赋值),排在前面的值自然就优先赋给变量,所以变量a的值就是”first”。

不过,这不是重点~(小若:那你还说个毛线啊!)

 

重点是,我们把顺序调换一下,如下:

  1. local a, b, c =  mutou("木", 25), "first";
  2. print(a);
  3. print(b);
  4. print(c);

输出结果会出乎大家的意料:

[LUA-print] 木

[LUA-print] first

[LUA-print] nil

 

没错,mutou函数的返回值变成只有一个了,这就是函数的特点之一:如果函数的调用不是在表达式的最后一个元素,则,最多只返回一个值。

 

什么?还不够清晰吗?那再来举个粒子(小若:粒子你个头啊!)

我们这样调用函数…额,那个,我们继续下一条内容。(小若:举不出例子那你刚刚还激动个毛线啊!)

 

6.多重返回值的特点2——强制返回一个值

某些情况下,我们可能会对于一个函数感到厌烦,没错,为什么你总是返回多个值?!(小若:还不是你自己写的函数吗!)

 

如果想让某个函数强制只返回一个值,可以这么做:

  1. local a, b = (mutou("木", 25));
  2. print(a);
  3. print(b);

输入结果如下:

[LUA-print] 木

[LUA-print] nil

 

我们只需要在函数调用时,把函数调用放在括号中就可以了。

 

7.名字参数/具名实参/named arguments

最后,我们来看看比较实用的一种函数参数——名字参数。

其实“名字参数”是我自己的叫法,《Lua程序设计》第二版中是称之为“具名实参”,但我看到英文单词以及用法之后,我还是比较倾向于称之为“名字参数”。

 

先来问大家一个问题,我们刚刚一直在讨论的mutou函数,有多少个参数,不要回去看,1秒钟内回答~(小若:2个!)

第二个问题,mutou函数的age和name参数哪个在前哪个在后?0.001秒内回答!(小若:回答你个头啊!)

 

没错,我们有时候并不记得一个函数的参数顺序,倒底age是第一个参数呢,还是name是第二个参数?(小若:好像哪里不对…)

 

于是,具名实参就派上用场了。

我们修改一下mutou函数:

  1. function mutou(args)
  2. return args.name, args.age;
  3. end

现在mutou函数的参数变成了一个table,它要求table中包含name和age两个值。

 

于是,我们调用mutou函数的方式就变成了这样:

  1. local args = {name = "木", age = 25};
  2. print(mutou(args));

没错,传递一个table变量给mutou函数就可以了,由于函数在取参数值的时候,是根据table的key值来获取的,根本就不需要考虑参数顺序,这就解决了我们刚刚所说的顺序问题了。

 

8.结束

好了,关于函数的基础特性,就这么多了,当然,还有一个变长参数我没有提到,因为这好像没什么好提的~

 

最近我在计划坚持一件事情,那就是:晚上不写游戏,哪怕遇到让人兴奋的Bug。

我想把晚上的时间都拿来充电,我的基本功实在是不够用了,有点摇摇欲坠的感觉。

 

近期是计划把《Lua程序设计》这本书过一遍,希望能坚持~

计划是每晚花一小时看书,花一小时整理教程。

 

今天是第一天,很累,写教程比写游戏累多了。

有句什么话来着,永远不要让自己处于舒适的范围里,好吧,坚持…

(小若:用个毛线的省略号啊!用感叹号啊!这样才代表你有决心…)

 

我说,小若,那为什么你最后也用了省略号…

 

版权声明:本文为博主原创文章,未经博主允许不得转载。

0

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值