循环语句 #

一、while 循环 #

1.1 基本 while 循环 #

lua
-- 基本语法
while condition do
    -- 循环体
end

-- 示例:计数
local i = 1
while i <= 5 do
    print(i)
    i = i + 1
end
-- 输出:1 2 3 4 5

1.2 while 循环应用 #

lua
-- 求和
local sum = 0
local i = 1
while i <= 100 do
    sum = sum + i
    i = i + 1
end
print("1到100的和:" .. sum)  -- 5050

-- 读取输入直到特定值
local input
while input ~= "quit" do
    io.write("请输入(输入 quit 退出):")
    input = io.read()
    if input ~= "quit" then
        print("你输入了:" .. input)
    end
end

-- 处理队列
local queue = {1, 2, 3, 4, 5}
while #queue > 0 do
    local item = table.remove(queue, 1)
    print("处理:" .. item)
end

1.3 无限循环 #

lua
-- 无限循环
while true do
    -- 需要使用 break 退出
    local input = io.read()
    if input == "exit" then
        break
    end
    print("处理:" .. input)
end

二、repeat-until 循环 #

2.1 基本 repeat-until 循环 #

lua
-- 基本语法
repeat
    -- 循环体
until condition

-- 示例:至少执行一次
local i = 1
repeat
    print(i)
    i = i + 1
until i > 5
-- 输出:1 2 3 4 5

2.2 repeat-until 与 while 的区别 #

lua
-- while:先判断后执行
local x = 10
while x < 5 do
    print(x)  -- 不会执行
end

-- repeat-until:先执行后判断
local y = 10
repeat
    print(y)  -- 执行一次,输出 10
until y >= 5

2.3 repeat-until 应用 #

lua
-- 猜数字游戏
local target = math.random(1, 100)
local guess

repeat
    io.write("猜一个数字(1-100):")
    guess = tonumber(io.read())
    
    if guess == nil then
        print("请输入有效数字")
    elseif guess < target then
        print("太小了!")
    elseif guess > target then
        print("太大了!")
    end
until guess == target

print("恭喜,猜对了!")

三、数值 for 循环 #

3.1 基本数值 for 循环 #

lua
-- 基本语法
for var = start, stop, step do
    -- 循环体
end

-- 示例:从 1 到 5
for i = 1, 5 do
    print(i)
end
-- 输出:1 2 3 4 5

-- 指定步长
for i = 1, 10, 2 do
    print(i)
end
-- 输出:1 3 5 7 9

-- 负步长
for i = 10, 1, -1 do
    print(i)
end
-- 输出:10 9 8 7 6 5 4 3 2 1

3.2 for 循环变量作用域 #

lua
-- 循环变量是局部变量
for i = 1, 5 do
    print(i)
end
-- print(i)  -- 错误:i 不可见

-- 循环前定义变量
local i
for i = 1, 5 do
    print(i)
end
print(i)  -- nil(循环内的 i 是新变量)

3.3 数值 for 应用 #

lua
-- 计算阶乘
local function factorial(n)
    local result = 1
    for i = 1, n do
        result = result * i
    end
    return result
end
print(factorial(5))  -- 120

-- 打印乘法表
for i = 1, 9 do
    for j = 1, i do
        io.write(string.format("%d×%d=%d\t", j, i, i * j))
    end
    io.write("\n")
end

-- 遍历数组
local arr = {10, 20, 30, 40, 50}
for i = 1, #arr do
    print(string.format("arr[%d] = %d", i, arr[i]))
end

四、泛型 for 循环 #

4.1 ipairs 迭代器 #

lua
-- ipairs:遍历数组部分
local arr = {"a", "b", "c", "d", "e"}

for i, v in ipairs(arr) do
    print(i, v)
end
-- 输出:
-- 1    a
-- 2    b
-- 3    c
-- 4    d
-- 5    e

-- 注意:ipairs 遇到 nil 会停止
local sparse = {1, 2, nil, 4}
for i, v in ipairs(sparse) do
    print(i, v)
end
-- 只输出:1 1  和  2 2

4.2 pairs 迭代器 #

lua
-- pairs:遍历所有键值对
local dict = {
    name = "Lua",
    version = 5.4,
    author = "PUC-Rio"
}

for k, v in pairs(dict) do
    print(k, v)
end
-- 输出顺序不确定

-- pairs 可以遍历 nil 值之后的元素
local t = {1, 2, nil, 4}
for k, v in pairs(t) do
    print(k, v)
end
-- 输出:1 1, 2 2, 4 4

4.3 字符串迭代 #

lua
-- string.gmatch 迭代字符串
local s = "hello world from lua"
for word in string.gmatch(s, "%a+") do
    print(word)
end
-- 输出:hello, world, from, lua

-- 遍历字符
for i = 1, #s do
    local c = string.sub(s, i, i)
    print(i, c)
end

4.4 文件迭代 #

lua
-- 逐行读取文件
local file = io.open("data.txt", "r")
if file then
    for line in file:lines() do
        print(line)
    end
    file:close()
end

五、循环控制 #

5.1 break 语句 #

lua
-- break:跳出循环
for i = 1, 10 do
    if i == 5 then
        break
    end
    print(i)
end
-- 输出:1 2 3 4

-- 查找元素
local arr = {3, 5, 2, 8, 1, 9}
local target = 8
local found_index = nil

for i, v in ipairs(arr) do
    if v == target then
        found_index = i
        break
    end
end

if found_index then
    print("找到 " .. target .. " 在位置 " .. found_index)
end

5.2 goto 语句(Lua 5.2+) #

lua
-- goto:跳转到标签
local i = 0
::loop::
i = i + 1
print(i)
if i < 5 then
    goto loop
end
-- 输出:1 2 3 4 5

-- 使用 goto 模拟 continue
for i = 1, 10 do
    if i % 2 == 0 then
        goto continue
    end
    print(i)  -- 只打印奇数
    ::continue::
end

-- 使用 goto 跳出嵌套循环
for i = 1, 10 do
    for j = 1, 10 do
        if i + j > 15 then
            goto done
        end
        print(i, j)
    end
end
::done::
print("完成")

5.3 没有 continue? #

Lua 没有内置的 continue,但有几种替代方案:

lua
-- 方法1:使用 goto(Lua 5.2+)
for i = 1, 10 do
    if i % 2 == 0 then
        goto continue
    end
    print(i)
    ::continue::
end

-- 方法2:使用 if-else
for i = 1, 10 do
    if i % 2 ~= 0 then
        print(i)
    end
end

-- 方法3:使用 while 模拟
local i = 0
while i < 10 do
    i = i + 1
    if i % 2 == 0 then
        -- continue
    else
        print(i)
    end
end

六、嵌套循环 #

6.1 基本嵌套 #

lua
-- 打印矩形
for i = 1, 3 do
    for j = 1, 5 do
        io.write("* ")
    end
    io.write("\n")
end
-- 输出:
-- * * * * *
-- * * * * *
-- * * * * *

-- 打印三角形
for i = 1, 5 do
    for j = 1, i do
        io.write("* ")
    end
    io.write("\n")
end
-- 输出:
-- *
-- * *
-- * * *
-- * * * *
-- * * * * *

6.2 嵌套循环应用 #

lua
-- 二维数组遍历
local matrix = {
    {1, 2, 3},
    {4, 5, 6},
    {7, 8, 9}
}

for i = 1, #matrix do
    for j = 1, #matrix[i] do
        io.write(matrix[i][j] .. " ")
    end
    io.write("\n")
end

-- 查找二维数组
local function find_in_matrix(matrix, target)
    for i = 1, #matrix do
        for j = 1, #matrix[i] do
            if matrix[i][j] == target then
                return i, j
            end
        end
    end
    return nil, nil
end

-- 冒泡排序
local function bubble_sort(arr)
    local n = #arr
    for i = 1, n - 1 do
        for j = 1, n - i do
            if arr[j] > arr[j + 1] then
                arr[j], arr[j + 1] = arr[j + 1], arr[j]
            end
        end
    end
    return arr
end

七、自定义迭代器 #

7.1 简单迭代器 #

lua
-- 创建一个简单的迭代器
local function iter(t)
    local i = 0
    local n = #t
    return function()
        i = i + 1
        if i <= n then
            return t[i]
        end
    end
end

-- 使用
local arr = {1, 2, 3, 4, 5}
for v in iter(arr) do
    print(v)
end

7.2 状态迭代器 #

lua
-- 带状态的迭代器
local function range_iter(t, current)
    current = current + 1
    if current <= t.stop then
        return current
    end
end

local function range(start, stop)
    return range_iter, {start = start, stop = stop}, start - 1
end

-- 使用
for i in range(1, 5) do
    print(i)
end

7.3 实用迭代器 #

lua
-- 反向迭代器
local function rev_iter(t, i)
    i = i - 1
    if i >= 1 then
        return i, t[i]
    end
end

local function reversed(t)
    return rev_iter, t, #t + 1
end

local arr = {1, 2, 3, 4, 5}
for i, v in reversed(arr) do
    print(i, v)
end

-- 键排序迭代器
local function sorted_pairs(t)
    local keys = {}
    for k in pairs(t) do
        table.insert(keys, k)
    end
    table.sort(keys)
    
    local i = 0
    return function()
        i = i + 1
        local k = keys[i]
        if k then
            return k, t[k]
        end
    end
end

local dict = {c = 3, a = 1, b = 2}
for k, v in sorted_pairs(dict) do
    print(k, v)
end

八、性能优化 #

8.1 减少循环内计算 #

lua
-- 不推荐:循环内重复计算
for i = 1, #arr do
    if i <= #arr / 2 then
        process(arr[i])
    end
end

-- 推荐:预先计算
local half = #arr / 2
for i = 1, #arr do
    if i <= half then
        process(arr[i])
    end
end

8.2 选择合适的迭代器 #

lua
-- 数组遍历:使用数值 for(最快)
for i = 1, #arr do
    process(arr[i])
end

-- 需要值时:使用 ipairs
for i, v in ipairs(arr) do
    process(v)
end

-- 字典遍历:使用 pairs
for k, v in pairs(dict) do
    process(k, v)
end

九、实用示例 #

9.1 斐波那契数列 #

lua
local function fibonacci(n)
    local a, b = 0, 1
    for i = 1, n do
        print(a)
        a, b = b, a + b
    end
end
fibonacci(10)

9.2 质数判断 #

lua
local function is_prime(n)
    if n < 2 then return false end
    if n == 2 then return true end
    if n % 2 == 0 then return false end
    
    for i = 3, math.sqrt(n), 2 do
        if n % i == 0 then
            return false
        end
    end
    return true
end

-- 打印 100 以内的质数
for i = 1, 100 do
    if is_prime(i) then
        io.write(i .. " ")
    end
end

9.3 数据处理 #

lua
-- 统计单词频率
local function word_frequency(text)
    local freq = {}
    for word in string.gmatch(text:lower(), "%a+") do
        freq[word] = (freq[word] or 0) + 1
    end
    return freq
end

local text = "hello world hello lua world world"
local freq = word_frequency(text)
for word, count in pairs(freq) do
    print(word, count)
end

十、总结 #

本章介绍了 Lua 的循环语句:

  1. while 循环:先判断后执行
  2. repeat-until 循环:先执行后判断,至少执行一次
  3. 数值 for 循环:按步长遍历数值范围
  4. 泛型 for 循环:使用迭代器遍历
  5. 循环控制:break 跳出循环,goto 跳转
  6. 嵌套循环:处理多维数据
  7. 自定义迭代器:创建自己的迭代器

掌握循环语句是处理重复任务的基础。下一章,我们将学习函数。

最后更新:2026-03-27