lua_next()函数遍历lua表

最近研究了一下通过lua_next()函数获取Lua表内容的实现过程,记录一下:

先贴一段从网上看到的lua_next()工作过程,大致如下:

lua_next() 函数的工作过程是:
1) 先从栈顶弹出一个 key;
2) 从栈指定位置的 table 里获取下一对 key-value,然后将 key 入栈,再将 value 入栈;
3) 如果第 2 步成功则返回非 0 值,否则返回 0,并且不向栈中压入任何值。

 第一遍看这个过程有点云里雾里,于是写了一个例程来验证。该例程有两个功能,分别读取一个一维Lua表和一个二维Lua表。

读取一维表的函数定义如下:

/* 遍历一维表 */
void table_traverse(lua_State *L, std::string table_name)
{
	lua_getglobal(L, table_name.c_str());  //根据表名称获取表
	
	int idx = lua_gettop(L);   // 获取表在栈上的索引
		
	lua_pushnil(L);    /* table 里第一对 key-value 的前面没有数据,所以先用 lua_pushnil() 压入一个 nil 充当初始 key */
	
	while(lua_next(L, idx))
	{
		//std::cout << "---Loop start: Stack size = " << lua_gettop(L) << std::endl;
		
		/* 输出key */
		if(lua_isnumber(L, -2))
		{
			std::cout << "key = " << lua_tonumber(L, -2) << ", ";
		}
		else if(lua_isstring(L, -2))
		{
			std::cout << "key = " << lua_tostring(L, -2) << ", ";
		}
		else
		{
			std::cout << "Error key type!" << std::endl;
		}
		
		/* 输出value */
		if(lua_isnumber(L, -1))
		{
			std::cout << "value = " << lua_tonumber(L, -1) << std::endl;
		}
		else if(lua_isstring(L, -1))
		{
			std::cout << "value = " << lua_tostring(L, -1) << std::endl;
		}
		else
		{
			std::cout << "Error key type!" << std::endl;
		}
		
		/* 弹出一个元素,即当前的value */
		lua_pop(L, 1);
		//std::cout << "---Loop end: Stack size = " << lua_gettop(L) << std::endl;
	}
	
	lua_pop(L, 1);
}

读取二维表的函数如下:

/* 遍历二维表 */
void table_traverse_2D(lua_State *L, std::string table_name)
{
	lua_getglobal(L, table_name.c_str());  //根据表名称获取表
	
	int idx2D = lua_gettop(L);   // 获取总表在栈上的索引
		
	lua_pushnil(L);
	
	while(lua_next(L, idx2D))
	{
		int idx = lua_gettop(L);   // 获取子表在栈上的索引
		//std::cout << "------Outside loop start: Stack size = " << lua_gettop(L) << std::endl;
		
		//std::cout << "Is number: " << lua_isnumber(L, -2) << std::endl;
		//std::cout << "Is table " << lua_istable(L, -1) << std::endl;
		int key_type = lua_type(L, -2);
		int value_type = lua_type(L, -1);
		std::cout << "Key type: " << lua_typename(L, key_type) << std::endl;
		std::cout << "Value type: " << lua_typename(L, value_type) << std::endl;
		
		lua_pushnil(L);
		
		while(lua_next(L, idx))
		{
			//std::cout << "---Inside loop start: Stack size = " << lua_gettop(L) << std::endl;
			
			/* 输出key */
			if(lua_isnumber(L, -2))
			{
				std::cout << "key = " << lua_tonumber(L, -2) << ", ";
			}
			else if(lua_isstring(L, -2))
			{
				std::cout << "key = " << lua_tostring(L, -2) << ", ";
			}
			else
			{
				std::cout << "Error key type!" << std::endl;
			}
			
			/* 输出value */
			if(lua_isnumber(L, -1))
			{
				std::cout << "value = " << lua_tonumber(L, -1) << std::endl;
			}
			else if(lua_isstring(L, -1))
			{
				std::cout << "value = " << lua_tostring(L, -1) << std::endl;
			}
			else if(lua_istable(L, -1))
			{
				std::cout << "value is table." << std::endl;
			}
			else 
			{
				std::cout << "Error key type!" << std::endl;
			}
			
			/* 弹出一个元素,即当前的value */
			lua_pop(L, 1);
			//std::cout << "---Inside loop end: Stack size = " << lua_gettop(L) << std::endl;
		}
		
		/* 弹出一个元素,即一个子表的内容 */
		lua_pop(L, 1);
		//std::cout << "------Outside loop end: Stack size = " << lua_gettop(L) << std::endl;
	}
	
	lua_pop(L, 1);
}

程序主体:

#include <iostream>
#include <string>
#include <vector>
#include "lua.hpp"

/* 初始化函数 */
lua_State* script_initialize(const char* script_name)
{
	lua_State *pLua = luaL_newstate(); //创建一个Lua虚拟机
	if(!pLua)
	{
		std::cout << "Failed to open Lua!" << std::endl;
		return NULL;
	}
	 
	luaL_openlibs(pLua);  //将标准类库加载到Lua虚拟机
 
	luaL_dofile(pLua, script_name);   //加载并运行lua文件

	return pLua;
}


int main()
{
	lua_State *pL = script_initialize("test_table.lua");
	if(!pL)
	{
		std::cout << "Script initialized failed!" << std::endl;
		return -1;
	}
	std::cout << "Script initialized successed!" << std::endl;
	
	table_traverse(pL, "my_table");
	
	std::cout << std::endl << std::endl;
	
	table_traverse_2D(pL, "my_table_2D");
	
	return 0;
}

Lua文件内容如下,含有一个一维表my_table和一个二维表my_table_2D。其中一维表中含有三对key-value,二维表也是有3个1维表构成的。

my_table = {color = "red", shape = "circle", size = 5}

my_table_2D = {{color = "red", shape = "circle", size = 5},
	{color = "green", shape = "rectangle", size = 10},
	{color = "blue", shape = "triangle", size = 20}
}

运行结果如下:

从打印出来的结果可以看到,对于二维表来说,每一个一维子表也是一对key-value,只不过key是数字索引(默认从1开始),value为table。

如果更进一步细致地打印出每一个循环中的数据类型和数量,则可验证本文最开始的lua_next()工作过程。有兴趣的读者可以打开以上例程中的打印语句,自己验证一下。

  • 1
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值