Lua 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 程式碼。這同時也能透過將兩個標準程式庫函式封裝成 upvalue 來最佳化,而不是每次都查詢(儘管每次查詢的優點是可以更動態)。不過你可能還是只想使用 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);
function printf(...) local function wrapper(...) io.write(string.format(...)) end local status, result = pcall(wrapper, ...) if not status then error(result, 2) end end