我正在尝试遍历lua表,但我不断收到此错误:
invalid key to 'next'
我知道索引从-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");
}
任何帮助都将不胜感激。
当我使用正索引时(只要我不从中删除1),这样可以正常工作
编辑:我注意到如果单独留下项目的值,我就不会收到此错误。只有当我开始读取item的值时才会出现此错误。当我从表中获得值时,我调用另一个Lua函数,这会破坏lua_next吗?
答案 0 :(得分:30)
您需要注意两件事:
lua_next
之前原始密钥保留在堆栈中。 luaL_checkstring
会将非字符串键转换为字符串(因为结果字符串不在表中,它将成为无效键。)通过传递luaL_checkstring
密钥的副本而不是原文。您的功能仅适用于index
的负值。您是正确的index--;
将确保index
在按下键后仍然指向该表,但仅当index
为负时(即相对于堆栈的顶部。)如果{ {1}}是绝对或伪索引,然后它会导致它指向错误的项目。最简单的解决方法是将对表的另一个引用推送到堆栈的顶部。
这是一个最小的C程序来演示:
index
答案 1 :(得分:5)
请勿将luaL_checkstring
与否定参数一起使用。请改用lua_tostring
。
此外,确保在循环中调用函数后堆栈保持不变:lua_next
期望堆栈顶部的前一个表键,以便它可以恢复遍历。
答案 2 :(得分:2)
来自manual:
const char *lua_tolstring (lua_State *L, int index, size_t *len);
转换给定的Lua值 C字符串的可接受索引。如果是len 不是NULL,它也设置* len 字符串长度。 Lua值必须 是一个字符串或数字;除此以外, 该函数返回NULL。如果 value是一个数字,然后是lua_tolstring 也改变了实际值 堆叠到一个字符串。 (此更改 当lua_tolstring时混淆lua_next 在表格中应用于键 遍历。)强>
luaL_checkstring
来电lua_tolstring
。
答案 3 :(得分:-1)
另请参阅lua_next
文档中的示例,摘自此处:
int lua_next (lua_State *L, int index);
从堆栈中弹出一个键,并从给定索引处的表中推送一个键值对(给定键之后的“下一个”对)。如果表中没有更多元素,则
lua_next
返回0(并且不进行任何操作)。典型的遍历如下:
/* table is in the stack at index 't' */ lua_pushnil(L); /* first key */ while (lua_next(L, t) != 0) { /* uses 'key' (at index -2) and 'value' (at index -1) */ printf("%s - %s\n", lua_typename(L, lua_type(L, -2)), lua_typename(L, lua_type(L, -1))); /* removes 'value'; keeps 'key' for next iteration */ lua_pop(L, 1); }
在遍历表时,不要直接在密钥上调用
lua_tolstring
,除非您知道密钥实际上是字符串。回想一下,lua_tolstring
可能会改变给定索引的值;这会混淆下一次调用lua_next
。有关在遍历期间修改表的注意事项,请参阅函数
next
。