使用Lua C API迭代表的表
我正在尝试迭代Lua中的表格并输出:
- 每个表的关键。
- 每个表中每个条目的键/值对。
这是代码:
void print_table(lua_State *L) { lua_pushnil(L); while(lua_next(L, -2) != 0) { const char *key = lua_tostring(L, -2); if(lua_isstring(L, -1)) printf("%s = %s", key, lua_tostring(L, -1)); else if(lua_isnumber(L, -1)) printf("%s = %d", key, lua_tonumber(L, -1)); else if(lua_istable(L, -1)) { printf("%s", key); PrintTable(L); } lua_pop(L, 1); } } }
这是我正在尝试输出的一个表的示例:
s = { p = { n = "D", g = "1", }, d = { l = "N", p = "N", u = "O", po = 100, }, e = { { n = "B", l = "P", p = "P", u = "P", po = "P", pa = { v = "4", a = "U", f = { { name = "U", type = "U" }, { name = "A", type = "I" }, { name = "A", type = "I" }, { name = "P", type = "U" }, { name = "P", type = "U" }, { name = "P", type = "I" }, { name = "T", type = "U" }, { name = "D", type = "U" }, { name = "D", type = "I" }, { name = "S", type = "I" }, { name = "C", type = "U" }, { name = "G", type = "U" }, { name = "C", type = "F" }, { name = "C", type = "U" }, }, }, c = { v = "1", a = "", f = { { name = "B", type = "U" }, { name = "E", type = "F" }, }, }, }, }, }
该函数在行中崩溃:
while(lua_next(L, -2) != 0)
由于索引无效。 导致崩溃的脚本行是:
{ name = "B", type = "U" },
我不得不承认我对Lua中的堆栈并不是很熟悉,我试图寻找类似的答案而无法找到任何答案。 谁知道我做错了什么?
谢谢!
添加工作版本以防任何人感兴趣:
void print_table(lua_State *L) { if ((lua_type(L, -2) == LUA_TSTRING)) printf("%s", lua_tostring(L, -2)); lua_pushnil(L); while(lua_next(L, -2) != 0) { if(lua_isstring(L, -1)) printf("%s = %s", lua_tostring(L, -2), lua_tostring(L, -1)); else if(lua_isnumber(L, -1)) printf("%s = %d", lua_tostring(L, -2), lua_tonumber(L, -1)); else if(lua_istable(L, -1)) { print_table(L); } lua_pop(L, 1); } }
f = { { name = "B", type = "U" }, { name = "E", type = "F" }, }
相当于:
f = { [1] = { name = "B", type = "U" }, [2] = { name = "E", type = "F" }, }
当你在密钥Lua上调用lua_tostring
时,将数字索引更改为字符串。
const char *key = lua_tostring(L, -2);
lua_tostring
使用lua_tolstring
并从手册中 :
如果值是数字,则lua_tolstring还将堆栈中的实际值更改为字符串。 (当在表遍历期间将lua_tolstring应用于键时,此更改会混淆lua_next。)
最好使用lua_type
来检查密钥是否真的是一个字符串,因为lua_isstring
只会告诉你堆栈值是否可以转换成字符串。 您也可以推送密钥的副本并在副本上调用lua_tostring
。