通过Lua表迭代

Tom*_*ese 15 c lua lua-table

我试图迭代lua表但我不断收到此错误:

invalid key to 'next'
Run Code Online (Sandbox Code Playgroud)

我知道索引从-8开始,我知道那里有一个表,因为它获得了第一个(也是唯一的)值.但是,它会尝试再次循环,即使我知道表中只有一个字符串.

if (lua_istable(L, index))
{
    lua_pushnil(L);

    // This is needed for it to even get the first value
    index--;

    while (lua_next(L, index) != 0)
    {
        const char *item = luaL_checkstring(L, -1);
        lua_pop(L, 1);

        printf("%s\n", item);
    }
}
else
{
    luaL_typerror(L, index, "string table");
}
Run Code Online (Sandbox Code Playgroud)

任何帮助,将不胜感激.

当我使用正索引时(只要我不从中删除1),这工作正常

编辑:我注意到,如果我单独留下项目的值,我就不会收到此错误.只有当我开始读取item的值时才会出现此错误.当我从表中获得值时,我调用另一个Lua函数,这可能会破坏lua_next吗?

fin*_*nnw 31

您需要注意两件事:

  • 确保在下次调用之前将原始密钥保留在堆栈中lua_next.luaL_checkstring将非字符串键转换为字符串(因为结果字符串不在表中,它将成为无效键.)通过传递luaL_checkstring密钥而不是原始密钥,可以轻松完成此操作.
  • 确保在每次循环中保留堆栈结构(即弹出尽可能多的值)

您的函数仅适用于负值index.你是正确的,index--;将确保index在按下键后仍然指向表,但只有当它index是负数(即相对于堆栈的顶部.)如果index是绝对或伪索引,那么这将导致它指向错误的项目.最简单的解决方法是将对表的另一个引用推送到堆栈顶部.

这是一个最小的C程序来演示:

#include <lauxlib.h>
#include <lua.h>

static void iterate_and_print(lua_State *L, int index);

int main(int ac, char **av)
{
   lua_State *L = luaL_newstate();
   luaL_openlibs(L);

   // Create a table and put it on the top of the stack
   luaL_loadstring(L, "return {one=1,[2]='two',three=3}");
   lua_call(L, 0, 1);

   iterate_and_print(L, -1);
   return 0;
}

static void iterate_and_print(lua_State *L, int index)
{
    // Push another reference to the table on top of the stack (so we know
    // where it is, and this function can work for negative, positive and
    // pseudo indices
    lua_pushvalue(L, index);
    // stack now contains: -1 => table
    lua_pushnil(L);
    // stack now contains: -1 => nil; -2 => table
    while (lua_next(L, -2))
    {
        // stack now contains: -1 => value; -2 => key; -3 => table
        // copy the key so that lua_tostring does not modify the original
        lua_pushvalue(L, -2);
        // stack now contains: -1 => key; -2 => value; -3 => key; -4 => table
        const char *key = lua_tostring(L, -1);
        const char *value = lua_tostring(L, -2);
        printf("%s => %s\n", key, value);
        // pop value + copy of key, leaving original key
        lua_pop(L, 2);
        // stack now contains: -1 => key; -2 => table
    }
    // stack now contains: -1 => table (when lua_next returns 0 it pops the key
    // but does not push anything.)
    // Pop table
    lua_pop(L, 1);
    // Stack is now the same as it was on entry to this function
}
Run Code Online (Sandbox Code Playgroud)


lhf*_*lhf 5

不要使用luaL_checkstring否定参数.请lua_tostring改用.

此外,确保在循环中调用函数后堆栈保持不变:lua_next期望堆栈顶部的前一个表键,以便它可以恢复遍历.