遍历 Lua 表格
我正在尝试遍历一个lua表,但我一直收到以下错误:
` 无效键'下一个'
`
我知道索引起始为-8,我知道那里有一个表,因为它得到了第一个(也是唯一的)值。但是,即使我知道表中只有一个字符串,它仍然尝试循环回来。
`` ` 如果(lua_istable(L,index)) { lua_pushnil(L);
//这是必需的,以便它甚至可以获得第一个值 索引-;
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的值放置不变的情况下,我才不会收到此错误。只有在我开始读取item的值时才会发生这种错误。当我从表中获取值时,我调用另一个Lua函数,这可能会干扰lua \ _next吗?
原文链接 https://stackoverflow.com/questions/6137684
从手册中:
const char *lua_tolstring(lua_State *L, int index, size_t *len);
将给定可接受索引处的Lua值转换为C字符串。如果len不为NULL,则还将其设置为字符串长度。Lua值必须是字符串或数字;否则,该函数将返回NULL。如果该值是数字,则
lua_tolstring
还会将堆栈中的实际值更改为字符串。(当在表遍历期间应用于键时,此更改使lua_next
混淆。)
luaL_checkstring
调用lua_tolstring
。
有两个需要注意的事项:
- 在下一次调用
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);
// 创建一个表并把它放在堆栈顶部
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)
{
// 推一个对表的另一个引用到堆栈顶部(以确保我们知道它在哪里,这个函数可以适用于负、正和伪索引)
lua_pushvalue(L, index);
// 堆栈现在包含:-1 => 表
lua_pushnil(L);
// 堆栈现在包含:-1 => nil;-2 => 表
while (lua_next(L, -2))
{
// 堆栈现在包含:-1 => 值;-2 => 键;-3 => 表
// 复制键,这样 lua_tostring 就不会修改原始键
lua_pushvalue(L, -2);
// 堆栈现在包含:-1 => 键;-2 => 值;-3 => 键;-4 => 表
const char *key = lua_tostring(L, -1);
const char *value = lua_tostring(L, -2);
printf("%s => %s\n", key, value);
// 弹出值 + 键的副本,留下原始键
lua_pop(L, 2);
// 堆栈现在包含:-1 => 键;-2 => 表
}
// 堆栈现在包含:-1 => 表(当 lua_next 返回 0 时,它会弹出键但不会推入任何东西)
// 弹出表
lua_pop(L, 1);
// 堆栈现在与进入该函数时相同
}
从 lua_next
的文档中摘录了以下示例:
int lua_next (lua_State *L, int index);
从堆栈中弹出一个键,并从给定索引处的表(给定键值之后的“下一个”键值对)推送一个键值对。 如果表中没有更多元素,则
lua_next
返回 0(并且不推送任何内容)。典型的遍历如下所示:
/* 将表在 't' 索引处压入堆栈 */ lua_pushnil(L); /* 第一个键 */ while (lua_next(L, t) != 0) { /* 使用 'key'(在索引 -2 处)和 'value'(在索引 -1 处) */ printf("%s - %s\n", lua_typename(L, lua_type(L, -2)), lua_typename(L, lua_type(L, -1))); /* 删除 'value';保留 'key' 以备下次迭代 */ lua_pop(L, 1); }
在遍历表时,不要直接在键上调用
lua_tolstring
,除非你知道键实际上是一个字符串。请记住,lua_tolstring
可能会更改给定索引处的值;这会使下一个调用lua_next
混淆。有关修改表时的注意事项,请参见函数
next
。
- 如何在roblox studio中1:1导入真实世界的地形?
- 求解,lua_resume的第二次调用继续执行协程问题。
- 【上海普陀区】内向猫网络招募【Skynet游戏框架Lua后端程序员】
- SF爱好求教:如何用lua实现游戏内调用数据库函数实现账号密码注册?
- Lua实现网站后台开发
- LUA错误显式返回,社区常见的规约是怎么样的
- lua5.3下载库失败
- 请问如何实现文本框内容和某个网页搜索框内容连接,并把网页输出来的结果反馈到另外一个文本框上
- lua lanes多线程使用
- 一个kv数据库
- openresty 有没有比较轻量的 docker 镜像
- 想问一下,有大佬用过luacurl吗
- 在Lua执行过程中使用Load函数出现问题
- 为什么 neovim 里没有显示一些特殊字符?
- Lua比较两个表的值(不考虑键的顺序)
- 有个lua简单的项目,外包,有意者加微信 liuheng600456详谈,最好在成都
- 如何在 Visual Studio 2022 中运行 Lua 代码?
- addEventListener 返回 nil Lua
- Lua中获取用户配置主目录的跨平台方法
- 如何编写 Lua 模式将字符串(嵌套数组)转换为真正的数组?
不要在负参数中使用
luaL_checkstring
。改用lua_tostring
。另外,确保在循环中调用函数后堆栈保持不变:
lua_next
期望上一个表的键保持在堆栈顶部,以便可以恢复遍历。