--lua中的语法简介1:--[[
1. lua可以没有分号结尾,有也不影响。这个看个人习惯了。
2. lua中所有的额变量都不需要声明,直接写变量名就可以用,且变量类型取决于赋值的类型,这一点很像C#中的var。
3. 需要清楚:lua是动态语言,即和javascript一样,虽然变量类型的获取方面很像var但不完全一样。体现在C#中的var类型变量在初始赋值后类型就定死了,而lua中的变量类型可以改变。
4. 对于从未使用过的变量其值为nil,因此可以理解为nil是lua变量的默认值。
5. 变量名、函数名之类的命名规则与C#语言一样:由字母,下划线和数字组成,但第一个字符不能是数字。并且不能和Lua的保留字相同。
6. Lua是大小写敏感的
7. 注意Lua中所有的值都可以作为条件。在控制结构的条件中除了false和nil为假,其他值都为真。所以Lua认为0和空串都是真。
]]--lua中的四种简单变量类型:--1. nil,等价于C#中的null,且是变量的默认值print("*******************");
a =nil;print(a);--2. number,等价于C#中的数值类型,在lua中不管是int,long,float,double都是一个类型numberprint("*******************");
a =10;
a =1.1;print(a);--3. string,等价于C#中的string类型,但需要注意lua中是没有char类型的,不论是单引号还是双引号都代表string类型,Lua中字符串是不可以修改的。和C#一样print("*******************");
a ="tian";
a ='tian2';print(a);--4. boolean,等价于C#中的bool类型print("*******************");
a =true;print(a);--5. type函数,可以返回变量的类型,返回值为stringprint("*******************");print(type(a));--lua中的四种复杂数据类型:--1. function:函数--2. table:表--3. userdata:数据结构--4. thread:协同程序
Lua字符串
--1. 获得字符串长度,特别注意中文字符长度为3print("*********************");
s ="123";
s ="是";print(#s);--2. lua支持转义字符print("*********************");print("213\n123\tqwe\\");--3. 字符串多行打印print("*********************");
s =[[
我
是
tian
]];print(s);--[[4. 字符串拼接,简单类型中不能直接拼接nil类型,boolean类型想要拼接这两个类型需要先使用tostring函数将其转换为string在拼接
拼接的结果为string类型,这点和C#很像]]print("*********************");print("123".."tian"..tostring(true)..tostring(nil));--5. 字符串格式化,其书写方式和C语言很像print(string.format("我今年%d岁了",18));--6. lua提供的string方法print("*********************");
str ="ASDfdsgFGASD";--小写转大写print(string.upper(str));--大写转小写print(string.lower(str));--字符串查找,输出的数字是想要查找的字符串在str中的第一个的开头索引和结束索引--注意lua的索引是从1开始的print(string.find(str,"ASD"));--截取字符串--参数分别为要截取的字符串,开始索引,结束索引print(string.sub(str,1,5));--字符串重复--参数分别是要重复的字符串,重复次数print(string.rep(str,2));--字符串修改--参数分别是要修改的字符串,要修改的字符,使用什么字符替换--打印的内容分别是:修改后的字符串,修改的次数print(string.gsub(str,"ASD","***"));--字符串转ASCII码
a = string.byte("Lua",1);print(a);--ASCII码转字符串print(string.char(a));
Lua运算符
--lua运算符print("*********************");print("算术运算符");--算术运算符包括: 加法+ 减法- 乘法* 除法/ 取余% 幂^print("1加法2".."\t"..1+2);print("1减法2".."\t"..1-2);print("2乘法3".."\t"..2*3);print("4除法2".."\t"..4/2);print("2幂运算4".."\t"..2^4);--其中lua幂运算所使用的符号在C#中是异或的符号--lua没有自增自减运算 ++ --
a =1;
a = a +1;print("lua没有自增自减运算".. a);--lua没有快捷运算(混合运算符)+= -=等
b =2;
a = a + b;print("lua没有快捷运算(混合运算符)".. a);--如果字符串可以转换为number,则也可以参与运算print("123"+2);print("123"*2);--需要注意的一点是,在lua中+仅仅有算数功能,没有字符串拼接的功能,想在lua中拼接字符串要使用.. 这一点和C#不同,不要弄混了。--算数运算符不可运算nil,会报错。print("*********************");print("条件运算符");--条件运算符包括: 大于> 小于< 大于等于>= 小于等于<= 等于== 不等于~=print("1大于2"..tostring(1>2));print("1小于2"..tostring(1<2));print("1大于等于2"..tostring(1>=2));print("1小于等于2"..tostring(1<=2));print("1等于2"..tostring(1==2));print("1不等于2"..tostring(1~=2));--注意,lua中的条件运算符写法和用法基本和C#一致,不同的是不等于在C#中是!=,而在lua中是~=print("*********************");print("逻辑运算符");--逻辑运算符包括: and or not--分别对应C#中的&& || !--lua中的逻辑运算符依然支持短路逻辑运算,对于与运算,第一项为假返回第一项,否则返回第二项;对于或运算,第一项为真返回第一项,否则返回第二项。--注意Lua中所有的值都可以作为条件。在控制结构的条件中除了false和nil为假,其他值都为真。所以Lua认为0和空串都是真。--falseprint(falseand1);--2print(1and2);--nilprint(niland1);--nilprint(0andnil);--1print(""and1);print("*********************");--lua不支持三目运算符和位运算符
Lua条件分支语句
print("*********************");print("条件分支语句");--lua条件分支语句和C#中的有很大的不同,lua中需要用if和then将条件包裹--单分支结构
a =5;if a ==5thenprint(5);end--双分支结构if a ==5thenprint(true);elseprint(false);end--多分枝语句--lua中的elseif一定要连着写,否则会报错if a ==1thenprint("a是1");elseif a ==2thenprint("a是2");elseif a ==3thenprint("a是3");elseprint("other");end--lua中没有switch语句,想要使用就需要自己实现
Lua循环语句
print("*********************");print("while语句");--while循环
num =0;while num <5doprint(num);
num = num +1;endprint("*********************");print("do while语句");--do while语句--注意until写的是结束条件,而不是C#中的循环条件repeatprint(num);
num = num -1;until num <1--满足条件跳出循环print("*********************");print("for语句");--lua中的for循环会默认自增for i =1,5doprint(i);endprint("*********************");--如果我不想自增1--三个数字分别为:初始值,结束值,增值for i =1,5,2doprint(i);end
print("*********************");print("table");--表是一切复杂数据类型的基础,包括:数组,二维数组,字典,类等等print("*********************");print("一维数组");
a ={1,2,3,4,"123",true,nil};
b ={1,2,nil,3,nil,"123",true};print("0号索引:"..tostring(a[0]));--注意lua中的索引默认从1开始,除非使用自定义索引print("1号索引:"..tostring(a[1]));print("*********************");print("一维数组遍历");print("a数组成员个数:"..tostring(#a));for i=1,#a doprint(a[i]);endprint("b数组成员个数:"..tostring(#b));for i=1,#b doprint(b[i]);end--现象表明lua中,如果table的末尾值为nil则不计算为table长度,可能为bug,日后可能会修改--旧版lua中中间nil类型会中断#关键字的长度统计print("*********************");print("二维数组");--和C语言的数组形式很像
a ={{1,2,3},{4,5,6}};print("1,1号索引:"..tostring(a[1][1]));print("2,2号索引:"..tostring(a[2][2]));print("*********************");print("二维数组的遍历");for i=1,#a do
b = a[i]for j=1,#b doprint(b[j]);endendprint("*********************");print("自定义索引");
aa ={[0]=1,2,3,[-1]=4,5};print("0号索引:"..tostring(aa[0]));print("-1号索引:"..tostring(aa[-1]));--#关键字只会统计>=1的索引print(#aa);--lua中的一些bug现象,之后可能会修复--当使用自定义索引,且间隔为一个数时,#统计出来的为最大索引数
aa ={[1]=1,[2]=2,[4]=4,[6]=6};print(#aa);--当使用自定义索引,且间隔大于一个数时,我称之为索引中断,#统计出来的为数量为中断处的索引数
aa ={[1]=1,[2]=2,[5]=4,[6]=6};print(#aa);
Lua迭代器
print("*********************");print("迭代器遍历");--迭代器遍历,主要用来遍历表的--由于#关键字得到的数组长度并不准确,我们一般不用#来遍历表print("*********************");print("ipairs迭代器遍历1");--ipairs--ipairs遍历和老版#关键字比较像,遇见nil就会停止。
b ={1,2,nil,3,nil,"123",true};for i,v inipairs(b)doprint(i,v);endprint("*********************");print("ipairs迭代器遍历2");--ipairs遍历和#关键字相比依旧是从1开始往后遍历的,小于等于0的索引得不到
a ={[0]=1,2,3,[-1]=4,5};for i,v inipairs(a)doprint(i,v);endprint("*********************");print("ipairs迭代器遍历3");--ipairs遍历只能找到连续的索引,如果索引中断,则ipairs没有办法遍历后面的内容
aa ={[1]=1,[2]=2,[4]=4,[6]=6};for i,v inipairs(aa)doprint(i,v);end--下面介绍pairs迭代器遍历,pairs相比较ipairs很多问题得到了改善print("*********************");print("pairs迭代器遍历1");--pairs迭代器遍历会直接掠过为nil的值,这样就不会像ipairs那样因为nil而中断
b ={1,2,nil,3,nil,"123",true};for i,v inpairs(b)doprint(i,v);endprint("*********************");print("pairs迭代器遍历2");--pairs可以找到所有非nil的值
a ={[0]=1,2,3,[-1]=4,5};for i,v inpairs(a)doprint(i,v);end--[[
总结:
ipairs迭代器遍历和旧版#关键字的效果一样,只适合遍历索引连续且中间没有nil类型,没有自定义索引的table。
pairs迭代器遍历会掠过nil,这样pairs遍历就不会因为nil而终止遍历,而是可以找到table所有的键值。比较通用
]]
print("*********************");print("lua的一些特殊用法");print("多变量赋值");--传统赋值方式:
a =1;
b =2;
c =3;--多变量赋值:
a,b,c =4,5,6;print("三个变量的值分别为:".. a .. b .. c);--在lua中多变量赋值和多返回值都遵循自动补空和自动省略的处理策略。--自动补空
a,b,c =1,2;print(a);print(b);print(c);--自动省略
a,b,c =1,2,3,4,5;print(a);print(b);print(c);print("*********************");print("and和or的特殊用法");--在lua中数值同样具有布尔意义。--lua中只有nil和false为假,其他情况都为真。--lua同样有短路逻辑。--借助这些特性,我们就可以通过and和or来实现lua的三目运算符。--先来看结果演示:
x =1;
y =2;local result =(x > y)and x or y
print(result);--这个结果和C#中的三目运算符的结果是一样的,?:,条件为真返回x,条件为假返回y。--[[
下面我们来说一下原理:
根据短路逻辑
(x > y) --false
所以and式返回一个(x > y),也就是false
false继续和y做or运算
根据短路逻辑返回y
如果是(x > y) --true
根据短路逻辑返回一个x
x继续和y做or运算
根据短路逻辑返回x
]]
Lua协程
print("*********************");print("lua协程");print("协程的创建");--方法一创建协程:coroutine.create();functionfunc()print("方式一创建协程");endfunctionfunc1()print("方式二创建协程");end
coroutine1 = coroutine.create(func);--协程的本质是一个thread类型的对象,方式一创建的协程也是一个thread类型的。--使用时需要使用特定API来使用。print(type(coroutine1));--方式二创建协程:coroutine.wrap();
coroutine2 = coroutine.wrap(func1);--方式二创建的协程是一个function类型,使用的时候也和函数的使用过程一样。print(type(coroutine2));print("*********************");print("lua协程的运行");--第一种方式运行协程:
coroutine.resume(coroutine1);--第二种方式:coroutine2();print("*********************");print("lua协程的挂起");
func2 =function()local i =1whiletruedoprint(i);
i = i +1;print(coroutine.running());--当coroutine3运行时显示running,当其他协程运行此函数显示suspendedprint(coroutine.status(coroutine3));--协程的挂起函数,可以返回返回值
coroutine.yield(i);endend
coroutine3 = coroutine.create(func2);--每调用一次相当于C#的迭代器调用一次movenext方法,协程就会运行一次。--由于lua是从上到下一次运行的,所以只用重启一次协程才可以运行一次。--如果是使用resume创建的协程yield会返回两个返回值,第一个显示是否重启成功,第二个显示返回值。
isOk, tempI = coroutine.resume(coroutine3);print(isOk,tempI);
coroutine.resume(coroutine3);print(isOk,tempI);
coroutine.resume(coroutine3);print(isOk,tempI);--如果是使用wrap创建协程函数,yield只会返回一个返回值。
coroutine4 = coroutine.wrap(func2);print("返回值为:"..coroutine4());print("返回值为:"..coroutine4());print("返回值为:"..coroutine4());print("*********************");print("lua协程的状态");--通过APIcoroutine.status()查询协程当前的状态。--dead 协程结束--suspended 暂停--running 进行中--其中运行中的协程才可以检测到running状态。--coroutine.running()返回正在运行的线程编号,需要在协程内使用