Lua Printf |
|
printf
字符串格式化函数。
使用 io.write()
、print()
和 string.format()
在 Lua 中编写格式化文本很容易。io.write
与 print
类似,只是 io.write
不会在每个输出后添加换行符。C 函数 printf()
可以模拟为
> io.write(string.format("Hello from %s on %s\n",_VERSION,os.date())) Hello from Lua 5.1 on Mon Jan 1 22:11:56 2007
或者,可以将其封装在一个函数中,如下所示:
printf = function(s,...) return io.write(s:format(...)) end -- function
然后可以像这样使用:
printf("Hello from %s on %s\n",_VERSION,date())
在上面的示例中,printf()
的格式字符串和可变参数列表被传递给 string.format()
。write()
打印生成的格式化字符串。[*1]
有趣的是,Lua 5.1 中字符串方法的语法强制对第一个参数进行单独处理。这是有道理的,因为它与其他参数的作用完全不同。
请注意,Lua 的 string.format
函数不支持完整的 C 格式规范 [1],因此此函数不能直接替换。如果您需要 C 格式规范的全部功能,您可能需要在 C 代码中执行 printf
调用,然后从 Lua 中调用它。或者,您可以使用 C 字符串函数在 Lua 中完全模拟您需要的行为(更多工作量)。
上面的示例可以用 C 代码编写如下。这还通过捕获两个标准库函数作为上值来进行优化,而不是每次都查找它们(尽管每次都查找它们具有更动态的优势)。不过,您可能只想使用 Lua 版本。
static int l_printf (lua_State *L) { lua_pushvalue(L, lua_upvalueindex(2)); lua_insert(L, 1); lua_call(L, lua_gettop(L) - 1, 1); lua_pushvalue(L, lua_upvalueindex(1)); lua_pushvalue(L, -2); lua_call(L, 1, 0); return 0; } int luaopen_printf (lua_State *L) { lua_getglobal(L, "io"); lua_getglobal(L, "string"); lua_pushliteral(L, "write"); lua_gettable(L, -3); lua_pushliteral(L, "format"); lua_gettable(L, -3); lua_pushcclosure(L, l_printf, 2); /* With 5.1, I'd probably just return 1 at this point */ lua_setglobal(L, "printf"); return 0; }
一个 C 函数 l_printf
在 Lua 中注册为 printf
。当从 Lua 调用 l_printf
时,format()
会使用给定的参数调用,然后 write()
会使用 format
的结果调用,最后返回结果的数量。
脚注
[*1] Lua 4 版本为
function printf(...) write(call(format,arg)) end
static int l_printf (lua_State *l) { lua_getglobal(L,"format"); lua_insert(L,1); lua_call(L,lua_gettop(L)-1,LUA_MULTRET); lua_getglobal(L,"write"); lua_insert(L,1); lua_call(L,lua_gettop(L)-1,LUA_MULTRET); return lua_gettop(L); } lua_register(L,"printf",l_printf);
pcall()
包装器来捕获错误并指向有问题的 printf()
。否则很难确切地知道错误来自哪里。
function printf(...) local function wrapper(...) io.write(string.format(...)) end local status, result = pcall(wrapper, ...) if not status then error(result, 2) end end