使用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);
        }
    }
点赞
用户415823
用户415823
f = {
    { name = "B", type = "U" },
    { name = "E", type = "F" },
}

等价于:

f = {
    [1] = { name = "B", type = "U" },
    [2] = { name = "E", type = "F" },
}

当你调用lua_tostring函数时,Lua会将数字索引改变为字符串。

const char *key = lua_tostring(L, -2);

lua_tostring函数使用lua_tolstring函数,从手册中可以看到:

如果值是一个数字,那么lua_tolstring也会把栈中的实际值改变为一个字符串。(当在表格遍历时,我们把lua_tolstring应用于键时,这种改变会混淆lua_next。)

最好使用lua_type函数检查键是否真的是一个字符串,因为lua_isstring函数只会告诉你栈值是否可以转换成字符串。你也可以推送一个键的副本,在副本上调用lua_tostring

2015-03-26 20:49:34