lua愉快的操作栈中的数组

时间:2022-09-08 18:25:35
#include <windows.h>
#include <iostream>

using namespace std;

extern "C"
{
#include <lua.h>
#include <lauxlib.h>
#include <lualib.h>
}
#include <iostream>

#pragma comment(lib,"E:\\luaSRC\\lua5.1\\lib\\static\\lua5.1.lib")

static int f(lua_State *L)	//这个函数 读取number 加1后 压入栈昨晚返回值
{
	int sum = 0;

	if (lua_isnumber(L, -1))
	{
		sum = lua_tonumber(L, -1)+1;
		lua_pushnumber(L, sum);
	}
	else if(lua_isnil(L, -1))			//如果是nil 保持不变
		lua_pushnil(L);
	else if(lua_isstring(L, -1))		//如果是string 保持不变
		lua_pushstring(L,lua_tostring(L, -1));
	//else if								//还有其他类型检查这里就不赘述了
	//	...

	return 1;
}

bool popTable(lua_State* L, int idx)
{
	try{
		lua_pushnil(L);
		while(lua_next(L, idx) != 0){	//这里会自动过滤到nil信息 比如table里面是 1 2 nil 4 遍历只出现3次循环 1 2 4
			int keyType = lua_type(L, -2);
			if(keyType == LUA_TNUMBER){
				double value = lua_tonumber(L, -2);
				cout << "Key:" << value << endl;
			}else if(keyType == LUA_TSTRING){
				const char*  value = lua_tostring(L, -2);
				cout << "Key:" << value << endl;
			}else{
				cout << "Invalid key type: " << keyType << endl;
				return false;
			}
			int valueType = lua_type(L, -1);
			switch(valueType){
				case LUA_TNIL:
					{
						cout << "Value: nil" << endl;
						break;
					}
				case LUA_TBOOLEAN:
					{
						int value = lua_toboolean(L, -1);
						cout << value << endl;
						break;
					}
				case LUA_TNUMBER:
					{    cout << "Value:" << lua_tonumber(L, -1) << endl;
					break;
					}
				case LUA_TSTRING:
					{
						cout << "Value:" << lua_tostring(L, -1) << endl;
						break;
					}
				case LUA_TTABLE:
					{

						cout << "====sub table===" << endl;
						int index = lua_gettop(L);
						if (!popTable(L, index)) {
							cout << "popTable error in  popTable,error occured" << endl;
							return false;
						}
						break;
					}
				default:
					{
						cout << "Invalid value type: " << valueType << endl;
						return false;
					}
			}
			lua_pop(L, 1);
		}
	}catch(const char* s){
		const char* errMsg = s;
		lua_pop(L,1);
		cout << errMsg << endl;
		return false;
	}catch(std::exception& e){
		const char* errMsg = e.what();
		lua_pop(L,1);
		cout << errMsg << endl;
		return false;
	}catch(...){
		const char* errMsg = lua_tostring(L,-1);
		lua_pop(L,1);
		cout << errMsg << endl;
		return false;
	}
	return true;
}

int l_map (lua_State *L)
{
	int i, n;

	// 创建一个新的表
	lua_newtable( L );			//在整个L中 压入空表 在栈底

	lua_pushnumber( L, 1 );		//压入第一个值 key 为1
	lua_pushnumber( L, 45 );	//压入第一个值 value 为45
	lua_rawset( L, -3 );		//讲这一对键值对压入刚刚创建的空表里 并在state上清楚信息

	lua_pushnumber( L, 2 );
	lua_pushnumber( L, 99 );
	lua_rawset( L, -3 );

	lua_pushnumber( L, 4 );		//注意: 压入第3个值得时候 下标为4 数组就变成了1 2 nil 4
	lua_pushnumber( L, 150 );
	lua_rawset( L, -3 );

	lua_pushcfunction(L, f);	//将函数压栈
	//lua_setglobal(L, "average");

	/* 1st argument must be a table (t) */
	luaL_checktype(L, 1, LUA_TTABLE);		//检查栈底是不是刚刚存数据的那个table

	/* 2nd argument must be a function (f) */
	luaL_checktype(L, 2, LUA_TFUNCTION);	//检查索引为2的地方是不是 f函数

	//这里得到的是数组数量 
	//数组必须是1为key起始的table
	//如果table中间不上连续的 中间的字段是nil 如:添加了1 2 nil 4 得到数组长度是4
	n = luaL_getn(L, 1);  /* get size of table */

	for (i=1; i<=n; i++)//将数组中的数 调用f()加1后 覆盖数组里面之前的值
	{
		lua_pushvalue(L, 2);     /* push f */
		lua_rawgeti(L, 1, i);    /* push t[i] */
		lua_call(L, 1, 1);       /* call f(t[i]) */
		lua_rawseti(L, 1, i);    /* t[i] = result */	//这里3个参数L是栈 1是指栈的索引为1 i是指 操作的栈中1索引位置的table(实际是数字)下标(key)为i的 value
	}

	int type = lua_type(L,1);	//1是 table存放的位置 下面需要遍历这个table 然后打印

	if(type == LUA_TTABLE)
	{
		//int index = lua_gettop(L);
		if(popTable(L,1))		//打印栈中索引为1的table(数组中的)信息
		{
			return 0;
		}
		else
		{
			cout << "Error" << endl;
			return -1;
		}
	}

	return 0;  /* no results */
}

void main()
{
	lua_State* L = lua_open();

	luaL_openlibs(L);

	l_map(L);


	lua_close(L);
}