Lua 教程 - 第十一章:Lua 实战项目
第十一章:Lua 实战项目
纸上得来终觉浅,绝知此事要躬行。学习了这么多理论知识,是时候通过一些实战项目来巩固我们的 Lua 技能了。
本章将通过三个难度递增的小项目,带领大家综合运用前面学到的知识:
-
命令行计算器:练习字符串解析和基本的数学运算。
-
文本统计工具:练习文件 I/O、字符串匹配和表的操作。
-
简单的配置文件解析器:练习表的结构化数据处理。
11.1 项目一:命令行计算器
功能描述
用户在命令行输入简单的四则运算表达式(如 10 + 20 * 3),程序计算并输出结果。为了简化,我们暂时只支持两个操作数和一个运算符。
代码实现
-- calculator.lua
function calculate(n1, op, n2)
if op == "+" then
return n1 + n2
elseif op == "-" then
return n1 - n2
elseif op == "*" then
return n1 * n2
elseif op == "/" then
if n2 == 0 then
return nil, "Division by zero"
end
return n1 / n2
else
return nil, "Unknown operator"
end
end
print("Simple Calculator (Enter 'exit' to quit)")
print("Format: number operator number (e.g., 10 + 5)")
while true do
io.write("> ")
local input = io.read()
if input == "exit" then
break
end
-- 解析输入: 捕获 数字 运算符 数字
local n1_str, op, n2_str = string.match(input, "(%d+)%s*([%+%-%*/])%s*(%d+)")
if n1_str and op and n2_str then
local n1 = tonumber(n1_str)
local n2 = tonumber(n2_str)
local result, err = calculate(n1, op, n2)
if result then
print("Result: " .. result)
else
print("Error: " .. err)
end
else
print("Invalid input format!")
end
end
扩展挑战
-
支持浮点数(修改模式匹配
%d+为[%d%.]+)。 -
支持多个运算符的优先级解析(这就需要用到逆波兰表达式或递归下降解析了,难度较高)。
11.2 项目二:文本统计工具
功能描述
读取一个文本文件,统计其中出现频率最高的 10 个单词。
代码实现
-- word_count.lua
local filename = "sample.txt" -- 假设文件名为 sample.txt
local f = io.open(filename, "r")
if not f then
print("Cannot open file: " .. filename)
os.exit()
end
local text = f:read("a") -- 读取所有内容
f:close()
local counts = {}
-- 遍历所有单词
for word in string.gmatch(text, "%a+") do
word = string.lower(word) -- 转小写
if string.len(word) > 2 then -- 忽略过短的单词
counts[word] = (counts[word] or 0) + 1
end
end
-- 将统计结果转换为数组以便排序
local sorted_words = {}
for w, c in pairs(counts) do
table.insert(sorted_words, {word = w, count = c})
end
-- 排序:按频率降序
table.sort(sorted_words, function(a, b)
return a.count > b.count
end)
-- 输出前 10 个
print("Top 10 words:")
for i = 1, math.min(10, #sorted_words) do
local item = sorted_words[i]
print(string.format("%-15s: %d", item.word, item.count))
end
扩展挑战
-
支持命令行参数指定文件名(使用
arg表)。 -
过滤掉常见的停用词(如 “the”, “and”, “is” 等)。
11.3 项目三:简单的配置文件解析器
功能描述
解析类似于 INI 格式的配置文件,并将其转换为 Lua 表。
配置文件示例 (config.ini):
[server]
host = 127.0.0.1
port = 8080
[database]
user = admin
password = secret
代码实现
-- ini_parser.lua
function parse_ini(filename)
local f = io.open(filename, "r")
if not f then return nil, "Cannot open file" end
local config = {}
local current_section = nil
for line in f:lines() do
-- 去除空白字符
line = string.match(line, "^%s*(.-)%s*$")
-- 忽略空行和注释
if line ~= "" and string.sub(line, 1, 1) ~= ";" then
-- 匹配 [section]
local section = string.match(line, "^%[(.+)%]$")
if section then
current_section = section
config[current_section] = config[current_section] or {}
else
-- 匹配 key = value
local key, value = string.match(line, "^(%w+)%s*=%s*(.+)$")
if key and value then
if current_section then
config[current_section][key] = value
else
print("Warning: Key found outside section: " .. key)
end
end
end
end
end
f:close()
return config
end
-- 测试
local conf = parse_ini("config.ini")
if conf then
print("Database User: " .. conf.database.user)
print("Server Port: " .. conf.server.port)
end
扩展挑战
-
支持布尔值和数字类型的自动转换(目前全部解析为字符串)。
-
支持写入功能,将 Lua 表保存回 INI 文件。
总结
通过这三个项目,我们练习了:
-
字符串处理:
string.match,string.gmatch是文本处理的神器。 -
表的操作:用作字典计数、用作数组排序、用作结构化数据存储。
-
文件 I/O:读取文件内容、按行迭代。
-
逻辑控制:循环、条件判断、函数封装。
希望这些项目能让你对 Lua 的实际应用有更深的体感。
下一章预告:作为教程的最后一章,我们将总结 Lua 的最佳实践,探讨性能优化技巧,并以此结束我们的 Lua 基础之旅。

