4.3 控制语句
Lua 中只提供了简洁且方便的控制结构,其中, if 语句用来表示条件控制,而 while、 repeat 和 for来表示循环控制。所有的控制结构都有一个显式的终结符: if、 for 和 while 结构以 end 结束, repeat结构以 until 结束。 控制结构的条件表达式结果可以是任何值。但 Lua 只认为 false 和 nil 为假,其他所有值为真。(特别注意,Lua将0和空字符串也视为真) if 语句,有三种形式: if conditions then
--then-part
end
if conditions then
--then-part
else
--else-part
end
if conditions then
--then-part
elseif conditions then
--elseif-part
.. ---> 更多其他块
else
--else-part
end
4.3.1 if then else
if语句先测试其条件,然后根据测试结果执行then部分或else部分。else部分是可选的。
if a < 0 then a = 0 end
if a < b then return a else return b end
if line > MAXLINES then
showpage()
line = 0
end
若要编写嵌套的if,可以使用elseif。它类似于在else后面紧跟着一个if,它还可以避免在这样的嵌套中出现多个end:
local op = "+"
local a, b = 5, 3
local r
if op == "+" then
r = a + b
elseif op == "-" then
r = a - b
elseif op == "*" then
r = a * b
elseif op == "/" then
r = a / b
else
error("invalid operation")
end
print(r) -- 输出 8
由于Lua不支持switch语句,所以这种一连串的if-else if 代码是很常见的。
4.3.2 while
与其他语言中的while循环一样,Lua先测试while的条件。如果条件为假,那么循环结束;不然,Lua执行循环体,并重复这一过程。
local i = 1
while i <= 5 do
print("Iteration:", i)
i = i + 1
end -- 输出 Iteration: 1 到 Iteration: 5
顾名思义,repeat-until 语句会重复执行其循环体知道条件为真时结束。由于条件测试在循环体之后执行,所以循环体至少会执行一次。
--输出第一个非空的行
local line
repeat
print("输入非空行:")
line = read()
until line ~= ""
print("你输入了:", line)
Lua 中循环体内声明的局部变量在条件部分不可见:
local x = 16
local sqr = x / 2
repeat
sqr = (sqr + x / sqr) / 2
local error = abs(sqr^2 - x)
until error < x / 10000 -- 局部变量 'error' 此时将不可见(所以Lua4.0代码直接报错 error: attempt to compare function with number)
print("平方根", x, "大约是", sqr)
4.3.4 数值型for(mumeric for)
for语句有两种形式:数值型(numerical)for 和泛型(generic)for。
for var=exp1,exp2,exp3 do
something
end
在这种循环中,var的值从exp1变化到exp2之前的每次循环会执行something,并在每次循环结束后将步长(step)exp3增加到var上。第三个表达式exp3是可选的,若不存在,Lua语言会默然步长值为1.以下是这种循环的一个典型示例:
for i=1,f(x) do print(i) end
for i=10,1,-1 do print(i) end
为了更好地使用for循环,还需要了解一些小细节。首先,for的3个表达式是在循环开始前一次性求值的。例如,上例中的f(x)只会执行一次。其次,控制变量会被自动地声明为for语句的局部变量,并且仅在循环体内可见。因此,控制变量在循环结束后就不存在了:
for i=1,10 do print(i) end
max = i --可能是错误的!这里访问的是一个全局变量的i
如果需要在循环结束后访问控制变量的值(通常是在中断循环时),必须将该值保存到另一个变量中:
-- 在一个列表中查找一个值
local a = {3, 5, 7, 9}
local value = 7
local found = nil
for i = 1, getn(a) do
if a[i] == value then
found = i -- 保存i的值
break
end
end
print(found)
最后,不要改变控制变量的值,随意改变控制变量的值可能产生不可预知的结果。如果要在循环正常结束前停止for循环,那么可以参考上面的例子,使用break语句。
4.3.5 泛型for(generic for)(以Lua4.0.1为例)
前面已经见过一个例子:
-- 打印数组“a”的所有值
local a = {"apple", "banana", "cherry"}
for i, v in a do
print(v)
end
范型 for 和数值 for 有两点相同:
1、控制变量是局部变量
2、不要修改控制变量的值
看一个例子,假定有一个表:
days = {"Sunday", "Monday", "Tuesday", "Wednesday","Thursday", "Friday", "Saturday"}
现在想把对应的名字转换成星期几,一个有效地解决问题的方式是构造一个反向表:
revDays = {["Sunday"] = 1, ["Monday"] = 2, ["Tuesday"] = 3,["Wednesday"] = 4, ["Thursday"] = 5, ["Friday"] = 6, ["Saturday"] = 7}
下面就可以很容易获取问题的答案了:
x = "Tuesday"
print(revDays[x]) --> 3
假设有一个表示星期几的表:
days = {"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"}
如果不想进行手工的操作,那么可以利用下列代码自动构造反向表:
revDays = {}
for i, v in days do
revDays[v] = i
end
local x = "Tuesday"
print(x .. " 是日期 " .. revDays[x]) -- 输出 Tuesday 是日期 3
如果你对泛型 for 还有不清楚,那么在后面的章节我们还会继续学习到。
泛型 for的一些案例文章:
https://waylee.net/thread-2502-1-1.html
https://waylee.net/thread-2503-1-1.html
https://waylee.net/thread-2504-1-1.html
https://waylee.net/thread-2505-1-1.html |