在 Lua 中,`for` 和 `while` 是两种核心的循环结构的详细用法

在 Lua 中,forwhile 是两种核心的循环结构,用于实现重复执行逻辑。以下是它们的详细用法、进阶技巧及注意事项:


在 Lua 中,`for` 和 `while` 是两种核心的循环结构的详细用法—目录

  • 一、`for` 循环
    • 1. 数值 `for` 循环
      • 基础语法:
      • 关键特性:
      • 常见问题:
    • 2. 泛型 `for` 循环
      • 基础语法:
      • 关键特性:
  • 二、`while` 循环
    • 基础语法:
    • 关键特性:
  • 三、进阶用法
    • 1. 嵌套循环与标签控制
    • 2. 循环控制命令
    • 3. 性能优化技巧
  • 四、特殊场景与模式
    • 1. 遍历复杂数据结构
    • 2. 模拟 C 风格 `for` 循环
    • 3. 事件循环与协程
  • 五、注意事项与最佳实践
    • 1. 避免死循环
    • 2. 变量作用域
    • 3. 性能对比
  • 六、实战示例
    • 示例1:猜数字游戏
    • 示例2:批量文件处理
    • 示例3:生产者-消费者模型


一、for 循环

1. 数值 for 循环

基础语法:

-- 格式:for var = start, end [, step] do ... end
for i = 1, 5 doprint(i)  -- 输出 1 到 5
endfor i = 10, 1, -2 doprint(i)  -- 输出 10,8,6,4,2
end

关键特性:

• 范围表达式:startendstep 均为表达式,运行时计算。
• 隐式步长:默认步长为 1
• 浮点数支持:

for i = 0, 1, 0.2 doprint(i)  -- 输出 0, 0.2, 0.4, 0.6, 0.8, 1.0
end

常见问题:

• 浮点精度问题:

for i = 0, 0.1, 0.1 do print(i) end  -- 可能因精度丢失导致死循环

解决:改用整数步长后缩放:

for i = 0, 1, 0.1 do ... end  -- 改为整数逻辑

2. 泛型 for 循环

基础语法:

-- 格式:for k, v in pairs(t) do ... end
local t = {a=1, b=2, c=3}
for key, value in pairs(t) doprint(key, value)  -- 遍历表的所有键值对
endfor index, value in ipairs({"a", "b", "c"}) doprint(index, value)  -- 遍历数组部分(1-based)
end

关键特性:

• 迭代器协议:pairs(遍历所有键值)和 ipairs(遍历数组部分)是内置迭代器。
• 自定义迭代器:

-- 生成斐波那契数列的迭代器
function fib()local a, b = 0, 1return function()a, b = b, a + breturn aend
endfor num in fib() doif num > 100 then break endprint(num)
end

二、while 循环

基础语法:

-- 格式:while condition do ... end
local i = 1
while i <= 5 doprint(i)i = i + 1  -- 必须修改条件相关变量,否则死循环
end

关键特性:

• 条件前置:每次循环开始前检查条件。
• 无限循环:

while true do-- 需要主动 break 或 return 退出
end

三、进阶用法

1. 嵌套循环与标签控制

::outer_loop::
for i = 1, 3 dofor j = 1, 3 doif i == 2 and j == 2 thengoto outer_loop  -- 跳出外层循环endprint("i:", i, "j:", j)end
end

2. 循环控制命令

break:立即退出当前最内层循环。
continue:跳过当前迭代(Lua 5.3+ 支持):

for i = 1, 5 doif i == 3 then continue endif i == 5 then break endprint("Current value:", i)
end
-- 输出:1,2,4

3. 性能优化技巧

• 减少循环内计算:

-- 不推荐:每次循环都计算 len
for i = 1, #table dolocal len = #table  -- 重复计算print(i, len)
end-- 推荐:预计算
local len = #table
for i = 1, len doprint(i, len)
end

• 使用泛型 for 替代手动索引:

-- 低效写法
local i = 1
while my_table[i] doprint(my_table[i])i = i + 1
end-- 高效写法
for _, value in ipairs(my_table) doprint(value)
end

四、特殊场景与模式

1. 遍历复杂数据结构

-- 遍历嵌套表(深度优先)
local function deep_traverse(t)for k, v in pairs(t) doif type(v) == "table" thendeep_traverse(v)elseprint(k, v)endend
end

2. 模拟 C 风格 for 循环

-- 自定义范围迭代器
function range(start, stop, step)step = step or 1local current = startreturn function()if (step > 0 and current <= stop) or (step < 0 and current >= stop) thenlocal value = currentcurrent = current + stepreturn valueendend
endfor i in range(1, 5, 1) do print(i) end  -- 1,2,3,4,5

3. 事件循环与协程

-- 使用协程实现非阻塞循环
local function task()for i = 1, 5 doprint("Coroutine:", i)coroutine.yield()  -- 主动让出执行权end
endlocal co = coroutine.create(task)
coroutine.resume(co)  -- 启动协程
coroutine.resume(co)  -- 恢复执行

五、注意事项与最佳实践

1. 避免死循环

• 确保循环条件最终会变为 false

-- 错误示例:缺少变量递增
local i = 1
while i <= 5 doprint(i)-- i 未更新 → 死循环
end

2. 变量作用域

for 循环变量是块级作用域(Lua 5.3+):

for i = 1, 3 dolocal i = "inner"  -- 局部变量,不影响外层循环print(i)  -- 输出 "inner"
end

3. 性能对比

场景推荐结构原因
遍历数组ipairs效率高,自动处理 nil
遍历字典pairs遍历所有键值对
已知迭代次数数值 for更直观
条件不确定的重复执行while/repeat灵活控制退出条件

六、实战示例

示例1:猜数字游戏

math.randomseed(os.time())
local secret = math.random(1, 100)
print("猜一个 1~100 的数字:")while true dolocal guess = tonumber(io.read())if not guess then break end  -- 输入非数字退出if guess < secret thenprint("太小了!")elseif guess > secret thenprint("太大了!")elseprint("恭喜猜中!")breakend
end

示例2:批量文件处理

local files = {"a.txt", "b.txt", "c.txt"}
for _, filename in ipairs(files) dolocal file = io.open(filename, "r")if file thenprint("处理文件:", filename)file:close()elseprint("文件不存在:", filename)end
end

示例3:生产者-消费者模型

local queue = {}
local function producer()for i = 1, 5 dotable.insert(queue, "item"..i)print("生产:", i)end
endlocal function consumer()while true doif #queue > 0 thenlocal item = table.remove(queue, 1)print("消费:", item)elsebreakendend
endproducer()
consumer()

通过灵活组合 forwhile 循环,并结合 Lua 的迭代器和协程特性,可以实现高效且易读的逻辑控制。对于复杂场景,建议优先使用泛型 for 和表驱动模式,减少手动循环控制带来的复杂性。


本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/diannao/77406.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

A2DP(Advanced Audio Distribution Profile)是蓝牙协议栈中用于音频传输的一个标准化协议

A2DP&#xff08;Advanced Audio Distribution Profile&#xff09;是蓝牙协议栈中用于音频传输的一个标准化协议&#xff0c;主要用于高质量音频流的无线传输。以下是A2DP协议的详细信息&#xff1a; 定义 A2DP协议允许音源设备&#xff08;Source&#xff0c;简称SRC&#…

STM32_USB

概述 本文是使用HAL库的USB驱动 因为官方cubeMX生成的hal库做组合设备时过于繁琐 所以这里使用某大神的插件,可以集成在cubeMX里自动生成组合设备 有小bug会覆盖生成文件里自己写的内容,所以生成一次后注意保存 插件安装 下载地址 https://github.com/alambe94/I-CUBE-USBD-Com…

【文献阅读】Capabilities of Gemini Models in Medicine

​ Google DeepMind Google Research 发表于 2024-04-29 相关链接&#xff1a; 数据集&#xff1a;https://huggingface.co/datasets/katielink/med-gemini-medqa-relabeled 注&#xff1a;长EHR是长的电子健康记录&#xff08;Electronic Health Record&#xff09; 未开…

网络安全小知识课堂(最终完结版)

网络安全入门 &#xff1a;从 “小白” 到 “守护者” 的蜕变之旅 写在完结之际 历经 13 篇的深度探索&#xff0c;我们从 DDoS 攻击的 “流量洪水” 一路闯关到 HTTPS 的 “加密堡垒”&#xff0c;揭开了网络安全世界的层层面纱。感谢每一位读者的陪伴与互动&#xff0c;你们…

Php laravel 留言板 curd 实战

1. 项目创建 首先我们用composer创建项目 &#xff0c; composer会根据当前的php版本 帮我们选择支持的最高版本 composer create-project --prefer-dist laravel/laravel myblog laravel新版本比较激进 &#xff0c;需要最低 php7 支持 2. 项目配置 数据库配置 &#xff0c…

HTTP 压力测试工具autocannon(AI)

简介 autocannon 是一款基于 Node.js 的高性能 HTTP 压力测试工具&#xff0c;适用于评估 Web 服务的并发处理能力和性能瓶颈。 一、工具特点 高性能‌&#xff1a;利用 Node.js 异步非阻塞机制模拟高并发请求‌。‌实时监控‌&#xff1a;测试过程中动态展示请求统计和性能…

LVM 扩容详解

目录 一、LVM扩容 1. 查看磁盘分区情况&#xff1a; 2. 查看pv、vg、lv 情况 3. 将新硬盘分区初始化 4. 将初始化后的分区添加到VG中 5. 查看逻辑卷的设备路径 6. VG分配给lv 二、扩展文件系统 1.确认文件系统类型 三、检验 一、LVM扩容 1. 查看磁盘分区情况&#xff1a; …

每日一题(小白)数组娱乐篇21

由于题意可知我们是要将对应的数字转换为英文&#xff0c;我们要考虑两点一个是进制的转换&#xff0c;也就是类似于我们的十进制一到9就多一位&#xff0c;这里的进制就是Z进制也就是27进制一旦到26下一位则进位&#xff1b;另一方面要考虑数字的转换也就是1~26对应A~Z。解决上…

python爬虫:喜马拉雅案例(破解sign值)

声明&#xff1a; 本文章中所有内容仅供学习交流使用&#xff0c;不用于其他任何目的&#xff0c;严禁用于商业用途和非法用途&#xff0c;否则由此产生的一切后果均与作者无关&#xff01; 根据上一篇文章&#xff0c;我们破解了本网站的&#xff0c;手机号和密码验证&#x…

深入探讨:Spring 如何接入 DeepSeek​

​在当今数字化浪潮中&#xff0c;人工智能&#xff08;AI&#xff09;技术的迅猛发展深刻地改变着各个领域的技术格局。Java 作为一种广泛应用于企业级开发的编程语言&#xff0c;其生态系统也在不断演进以适应 AI 技术的融入。Spring 框架&#xff0c;作为 Java 生态中的中流…

VSCode运行,各类操作缓慢,如何清理

VSCode写代码&#xff0c;随着项目逐步进展&#xff0c;代码量在增加&#xff0c;依赖的第三方头文件也在增加&#xff0c; 先是发现代码提示的速度变慢&#xff0c; 后来格式化代码速度太慢 然后c/c代码的语法检查有时候压根就失败&#xff0c;来个错误提示 还有source contro…

Elasticsearch:加快 HNSW 图的合并速度

作者&#xff1a;来自 Elastic Thomas Veasey 及 Mayya Sharipova 过去&#xff0c;我们曾讨论过搜索多个 HNSW 图时所面临的一些挑战&#xff0c;以及我们是如何缓解这些问题的。当时&#xff0c;我们也提到了一些计划中的改进措施。本文正是这项工作的成果汇总。 你可能会问…

人事|人事管理系统|基于Springboot+vue的人事管理系统设计与实现(源码+数据库+文档)

人事管理系统 目录 基于Springboot的人事管理系统设计与实现 一、前言 二、系统功能设计 三、系统实现 1、管理员登录 2、员工管理 3、公告信息管理 4、公告类型管理 5、培训管理 6、培训类型管理 四、数据库设计 1、实体ER图 五、核心代码 六、论文参考 七、最新…

2.4GHz射频前端噪声系数优化架构

2.4GHz射频前端电路架构由信号处理链路、硬件模块及性能规范构成&#xff0c;其系统组成与参数要求如下&#xff1a; 一、信号发射链路‌ 数字基带信号通过DAC转换为模拟信号‌ 调制电路将信号加载至本地振荡器生成的2.4GHz载波‌ 功率放大器将信号强度提升至20-25dBm范围‌ …

开源 LLM 应用开发平台 Dify 全栈部署指南(Docker Compose 方案)

开源 LLM 应用开发平台 Dify 全栈部署指南&#xff08;Docker Compose 方案&#xff09; 一、部署环境要求与前置检查 1.1 硬件最低配置 组件要求CPU双核及以上内存4GB 及以上磁盘空间20GB 可用空间 1.2 系统兼容性验证 ✅ 官方支持系统&#xff1a; Ubuntu 20.04/22.04 L…

Trae AI 保姆级教程:从安装到调试全流程指南

Trae AI 保姆级教程&#xff1a;从安装到调试全流程指南 Trae AI 是字节跳动推出的一款 AI 原生集成开发环境(IDE)&#xff0c;专为中文开发者设计&#xff0c;集成了 Claude 3.5 和 GPT-4o 等先进 AI 模型&#xff0c;支持通过自然语言交互实现代码生成、项目构建与调试。本教…

博物馆小程序怎么做?从0到1打造数字化文化窗口

博物馆小程序怎么做&#xff1f;从0到1打造数字化文化窗口 一、行业痛点&#xff1a;传统博物馆的数字化困局 在数字化浪潮下&#xff0c;传统博物馆普遍面临三大挑战&#xff1a; ​​客流受限​​&#xff1a;线下接待能力有限&#xff0c;难以触达更广泛人群 ​​互动单一…

基于 Netty 框架的 Java TCP 服务器端实现,用于启动一个 TCP 服务器来处理客户端的连接和数据传输

代码&#xff1a; package com.example.tpson_tcp;import io.netty.bootstrap.ServerBootstrap; import io.netty.channel.ChannelFuture; import io.netty.channel.ChannelInitializer; import io.netty.channel.ChannelOption; import io.netty.channel.EventLoopGroup; imp…

深入解析原生鸿蒙中的 RN 日志系统:从入门到精通!

全文目录&#xff1a; 开篇语&#x1f4d6; 目录&#x1f3af; 前言&#xff1a;鸿蒙日志系统究竟有多重要&#xff1f;&#x1f6e0;️ 鸿蒙 RN 日志系统的基础结构&#x1f4dc; 1. 日志的作用⚙️ 2. 日志分类 &#x1f527; 如何在鸿蒙 RN 中使用日志系统&#x1f58b;️ 1…

算法训练营Day01(二分 双指针)

704. 二分查找 - 力扣&#xff08;LeetCode&#xff09; 关于二分查找 最重要的是要处理好边界问题&#xff0c;每次写完边界可以带入特殊值进行测试确定区间的不变量是什么&#xff1f;比如区间的左闭右闭&#xff0c;和左闭右开&#xff0c;每次二分完的新区间&#xff0c;一…