Lua语句

  • 赋值
  • 局部变量与块
  • 控制结构
  • break和return

Lua支持的常规语句基本与C或Pascal中所支持的语句相似,它们包括赋值、控制结构、过程调用。另外Lua还支持非传统的语句,例如多重赋值(multiple assignment)和局部变量声明。

赋值语句

赋值(assignment)的基本含义是修改一个变量或一个table中字段的值。赋值时改变一个变量的值和标域的基本方式。

str = "hello" .. " world"
print(str) -- hello world

Lua允许“多重赋值”,也就是一次性将多个值赋给多个变量,即对多个变量同时赋值,变量列表和值列表的各个元素使用逗号分隔,赋值语句右边的值会依次赋予给左边的变量。

x, y = 10, 2 * math.pi
print(x, y) -- 10   6.2831853071796

多重赋值中,Lua先对=右边元素求值,然后才执行赋值。这样便可以用一句多重赋值来交换两个变量。

x, y = 1, 2
x, y = y, x
print(x,y) -- 2 1

Lua会将=右边值的个数调整到与左边变量的个数相一致,规则是:

  • 变量个数>值的个数:按变量个数补足nil
  • 变量个数<值的个数:多余的值会被忽略(“静悄悄的”丢弃掉)
x, y, z = 0, 1
print(x, y, z) -- 0 1 nil

x, y = x + 1, y + 1, y + 2
print(x,y) -- 1 2

x, y, z = 0
print(x,y,z) -- 0 nil nil

多重赋值并不会比相等价的多条单一变量赋值语句更快,但有时的确会需要多重赋值。

多重赋值经常用来交换变量(swap)或将函数调用返回给变量。

x, y = fn()

局部变量与代码块(block)

局部变量

相对于全局变量,Lua提供了局部变量,通过local语句来创建局部变量。

i = 10 -- 全局变量
local j = 100 -- 局部变量

代码块

与全局变量不同的是,局部变量的作用域仅限于声明它们的那个代码块。代码块(block)是一个控制结构的执行体、或是一个函数的执行体、亦或是一个程序块(chunk)。

x = 3
local y = 1 -- 程序块中的局部变量

while y <= x do
    local x = y * 2 -- while循环体中的局部变量
    print(x)  -- 2 4 6
    y = y + 1
end

交互模式下输入下列代码可能不会如预期那样工作,因为交互模式中每行输入内容自身就形成了一个程序块(chunk)。

i = 3;
if i > 20 then
    local x -- then中的局部变量
    x = 10
    print(x)
else
    print(x) -- nil
end

为了这个问题,可显式的界定一个块(block),只需要将内容放入一对关键字do-end中即可,相当于C/C++中的{}。每当输入do时,Lua就不会单独地执行后面每行的内容,而是直至遇到相应的end时,才会执行整个块的内容。

do
    local x = 2 * a
    local y = (b ^ 2 - 4 * a * c) ^ (1 / 2)

    m = (-b + y) / x;
    n = (-b - y) / x;
end

尽可能地使用局部变量,这是一种良好的编程风格,局部变量可避免一些无用的名称引入全局环境(global environment),避免搞乱了全局环境。访问局部变量比访问全局变量更快。局部变量会随着其作用域的结束而消失,这样便使垃圾收集器可以释放其值。

  • 避免命名冲突
  • 访问局部变量的速度比全局变量更快

给代码块block划定一个明确的界限do..end内的部分,当想更好的控制局部变量的作用范围时很有用。

do
  local x = x*2
  local y = sqrt(a^2 - 4*a*c)
end
print(x, yu)

Lua将局部变量的声明当做语句来处理。因此可以在任何书写语句的地方书写局部变量的声明。所声明的局部变量的作用域从声明语句开始,直至所在块的结尾。

local x, y = 1, 10
if x < y then
    print(x) -- 1
    local x
    print(x) -- nil
end

print(x,y)--1 10

声明语句中还可包含初始化赋值,其规则和普通的赋值语句完全一样:额外的值会被丢弃,额外的变量会被赋予nil。如果一条声明语句没有初始化赋值,那么 它声明的所有变量都会初始化为nil

Lua中有在种习惯性写法为local foo = foo,这句代码创建一个局部变量foo,并将用全局变量foo的值初始化它。如果后续其他函数改变了全局foo的值,那么可以在这里先将它的值保存起来。这种方式还可以加速在当前作用域中对foo的访问。

在需要时才声明变量,可以使这个变量在初始化时刻就拥有一个有意义的初值。此外,缩短变量的作用域有助于提高代码的可读性。

控制结构

控制结构的条件表达式可以是任何值,Lua认为falsenil为假。

  • Lua提供一组传统的、小巧的控制结构,包括用于条件执行的if,用于迭代的whilerepeatfor
  • 控制结构均有 一个显式的终止符:if、for、whileend作为结尾,repeatuntil作为结尾。
  • 控制结构中的条件表达式可以是任意值,Lua将所有不是falsenil的值视为真。

判断语句

Lua中判断语句包括三个关键字ifelseelseif,并以end作为结束整个语句的标识。

判断语句的格式分为三种:

第1种格式

if 表达式 then
    语句块
end

第2种格式

if 表达式 then
    为真语句块
else
    为假语句块
end

第3种格式

if 表达式1 then
    语句块1
elseif 表达式2 then
    语句块2
elseif 表达式3 then
    语句块3
...
else
    语句块n
end

运算符与组块

local today=1

if today==1 then
    print('Monday')
elseif today==2 then
    print('Tuesday')
elseif today==3 then
    print('Wednesday')
elseif today==4 then
    print('Thursday')
elseif today==5 then
    print('Friday')
elseif today==6 then
    print('Saturday')
elseif today==7 or today==0 then
    print('Sunday')
else
    print('Unknown')
end
-- Monday

判断考试单科成绩在90和100之间为优秀,70到90之间为良好,60到70之间为及格,0到60之间为不及格。

local n=0

if n>=90 and n<=100 then
    print('excellent/great/best')
elseif n>=70 and n<90 then
    print('good')
elseif n>=60 and n<70 then
    print('average/general')
elseif n>=0 and n<60 then
    print('bad/weak/poor')
else
    print('error')
end

判断一个数是否为大于100的偶数

local n=0

if n<100 and n%2==0 then
    print('success')
else
    print('error')
end

判断两个数是否均为小于或等于200的奇数

local n,m=0,1

if n<=200 and m<=200 and n%2==1 and m%2==1 then
    print('success')
else
    print('error')
end

if then else

if a<0 then a=0 end

if a<0 then return a else return b end

if line>MAXLINES then
  showpage()
  line=0
end

若要编写嵌套的if可使用elseif,它类似于在else后紧跟一个if,它还可以避免在这样的嵌套中出现多个end

if op=='+' then
    result = a+b
elseif op=='-' then
    result = a-b
elseif op=='*' then
    result = a*b
elseif op=='/' then
    result = a/b
else
    error('invalid operation')
end

Lua不支持switch语句,一连串的if-else if代码是很常见的。

循环结构

while

arr = {'x','y','z'} -- Lua中数组的索引从1开始
local idx = 1
while arr[idx] do
    print(idx, arr[idx])
    idx = idx + 1 -- Lua中没有自增自减操作
end

-[[
1   x
2   y
3   z
-]]

repeat

repeat
    line = io.read()
until line ~= ""

print(line)

repeat...until相当于while...do

local sum = 1

repeat
    sum = sum + 1
    print(sum)
until sum == 10

for

-- for循环默认步进值为1
for idx=1,10,2 do
    print(idx) -- 1 3 5 7 9
end
arr = {'x','y','z'}
for i=1,#arr do -- #arr表示arr的长度
    print(i, arr[i])
end

循环语句

循环语句是程序中一种重要的控制结构,特点是在给定条件成立时,反复执行某程序段,知道条件不成立为止。给定的条件为循环条件,反复执行的程序段称为循环体。Lua中主要的循环语句分为:

循环语句1:while...do

while 循环条件 do
    循环体
end

while循环线判断循环条件表达式后执行,若表达式为假,则不运行循环直接跳出。

示例:

local i=5

while i>0 do
    print(i)
    i = i-1
end

输出1到100之间能被7整除的数字

local n=1

while n<100 do
    if n%7==0 then
        print(n)
    end
    n = n + 1
end

Lua先测试while循环的条件,为假则循环结束,否则执行循环体,并重复此过程。

local i=1
local arr = {1,2,3,4,5}

while arr[i] do
    print(arr[i])
    i = i+1
end

循环语句2:repeat...until

repeat
    循环体
until 循环条件

repeat是先运行一遍循环体,然后在判断循环条件表达式。

定义函数利用循环让函数能够计算n的阶乘

fn = function(n)
    local m = 1
    if n < 1 then
        n = 1
    end
    repeat
        m = n * m
        n = n - 1
    until n == 0
    print(n, m)
end

fn(3)

一条repeat-until语句重复执行其循环体直至条件为真时结束,测试是在循环体之后做的,因此循环体至少会执行一次。

repeat
    line = io.read()
until line~=""

print(line)

在Lua中一个声明在循环体中的局部变量的作用域包括了条件测试。

local sqr = x/2

repeat
    sqr=(sqr+x/sqr)/2
    local error=math.abs(sqr^2-x)
until error<x/10000

for循环语句分为两种:一种是数值for,另一种是泛型for

循环语句3:for...do

for 变量=初始值,终止值,步长 do
    循环体
end

步长可以省略,默认值为1。

for i = 10, 1, -1 do
    print(i)
end

初始值、终止值、步长三部分都只会被执行一次,即使使用变量或表达式替代终止值和步长,在循环体中改变了终止值和步长,循环也能正常结束。

stop, step = 10, 1
for start = 1, stop, step do
    stop = stop + 1
    step = step + 1
    print(start, stop, step)
end

执行循环时若想让循环中途停止不再执行,应该怎么办呢?使用break关键字,它的作用就是跳出正在执行的循环,注意break只能在循环体中使用。

stop, step = 10, 1

for start = 1, stop, step do
    if start == 5 then
        break
    end
    print(start, stop, step)
end

循环语句4:for...in...do

数字型for(numeric for)

for语句有两种形式:数字型for(numeric for)、泛型for(generic for)

数字型for的语法:

for var=begin,end,step do
  <execute body>
end

--[[
var 从begin表达式变化到end表达式,每次变化都以step作为步长递增var,并执行一次执行体。
若不指定step步长,则默认为1.
--]]

示例:九九乘法表

1x1=01 1x2=02 1x3=03 1x4=04 1x5=05 1x6=06 1x7=07 1x8=08 1x9=09 
2x2=04 2x3=06 2x4=08 2x5=10 2x6=12 2x7=14 2x8=16 2x9=18 
3x3=09 3x4=12 3x5=15 3x6=18 3x7=21 3x8=24 3x9=27 
4x4=16 4x5=20 4x6=24 4x7=28 4x8=32 4x9=36 
5x5=25 5x6=30 5x7=35 5x8=40 5x9=45 
6x6=36 6x7=42 6x8=48 6x9=54 
7x7=49 7x8=56 7x9=63 
8x8=64 8x9=72 
9x9=81 
for i=1,9,1 do
    local str = ""
    for j=1,9,1 do
        if(j>=i) then
            local result = i*j
            if result<=9 then
                result = "0"..result
            end
            str = str..i.."x"..j.."="..result.." "
        end
    end
    print(str)
end

示例

for i=1,f(x) do
    print(i)
end

for i=10,1,-1 do
    print(i)
end

如果不想给循环设置上限的话,可使用常量math.huge

for i=1,math.huge do
    if (0.3*i^3 - 20*i^2 - 500 >= 0) then
        print(i)
        break
    end
end

在编程语言中,循环与判断的应用是非常广泛的,Lua中循环判断语句是允许嵌套使用,用来处理一些比较复杂的问题。

使用1,2,3,4四个数字组成互不相同且无重复的三位数,三位数可填写在百位、十位、个位,可先组成排列后在去除不满足条件的排列。

for a = 1, 4, 1 do
    for b = 1, 4, 1 do
        for c = 1, 4, 1 do
            if a ~= b and a ~= c and b ~= c then
                print(a..b..c)
            end
        end
    end
end

计算斐波那契数列的前20个数字,斐波那契数列又称为黄金分割数列,是这样的一个数列1,1,2,3,5,8,13,21...

fb = function(i)
    if i > 0 and i <= 2 then
        return 1
    else
        local j = fb(i - 1) + fb(i - 2)
        return j
    end
end

n = 1
while n < 10 do
    print(fb(n))
    n = n + 1
end

递归,从前有座山山里有座庙,庙里有个老和尚正在讲故事:从前有座山,山里有座庙...直到有一天有个老和尚不再讲故事了,于是他去找到之前那个讲故事的那个老和尚,直到找到最初讲故事的那个老和尚。

泛型for

常见迭代器

  • 迭代数组的 ipairs
  • 迭代table表的 pairs
  • 迭代文件每行的lines
-- 循环遍历数组
for k,v in ipairs(arr) do
  print(k, v)
end

-- 循环遍历表
for item in pairs(tbl) do
  print(item)
end

break和return语句

  • break语句用来退出当前循环(forrepeatwhile),在循环外部不可以使用。
  • return 语句用来从函数返回结果,当一个函数自然结束,结尾会有一个默认的return,这种函数类似pascal的过程。

Lua语法要求breakreturn只能出现在代码块block的结尾一句,也就是说,作为程序快chunk的最后一句,或在end之前,或在else前,或在until前。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值