表格以树的形式呈现,需要以迭代模式遍历该树。Lua已经有了堆栈实现,这使得工作更加容易。
- 进入时,栈顶是表,你需要推入一个
nil
元素,因为lua_next()
在检查表之前会从栈中消耗一个元素。所以栈看起来像是table -> nil
。
- 接下来,我们调用
lua_next()
,它将从栈中消耗一个元素,并将两个新的键值对添加到表中。栈看起来像是table -> key -> value
。如果没有下一个元素,调用的返回值为0。
- 如果返回值为1,并且栈上的值是嵌套表,则需要在栈上推入
nil
。现在栈看起来像是table -> key -> table -> nil
。现在你几乎回到了开始的位置,所以通过循环,你将开始遍历嵌套表。
- 如果返回值为1,并且值不是表,则处理该值。
- 如果返回值为0,我们可以检查这是否是元表。检查后,你将弹出该值并检查栈是否为
table -> key
或any -> key
。如果栈上第二个元素不是表,则已经完成遍历,可以退出循环。
以下是实现该算法的C
代码。我保留了printf
以帮助调试,但应将printf()
删除。
static int cfun(lua_State *L)
{
luaL_checktype(L, 1, LUA_TTABLE);
lua_pushnil(L);
int loop=1;
do {
if ( lua_next(L,-2) != 0 ) {
if (lua_istable(L,-1)) {
printf("Table [%s] \n", lua_tostring(L, -2));
lua_pushnil(L);
} else {
printf("(%s - %s)\n",
lua_tostring(L, -2),
lua_typename(L, lua_type(L, -1)));
lua_pop(L,1);
}
} else {
printf("table finished, still on stack (%s -> %s -> %s)\n",
lua_typename(L, lua_type(L, -3)),
lua_typename(L, lua_type(L, -2)),
lua_typename(L, lua_type(L, -1)));
if (lua_getmetatable(L,-1)) {
printf("Metatable detected\n");
lua_pop(L,1);
}
lua_pop(L,1);
if (!lua_istable(L, -2)) {
loop = 0;
}
}
} while (loop);
lua_pop(L,1);
lua_pushnumber(L,0);
return 1;
}
lua_getmetatable
? - Joseph Sible-Reinstate Monica