前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Lua学习笔记:Lua里table表的使用例及介绍

Lua学习笔记:Lua里table表的使用例及介绍

原创
作者头像
晨星成焰
发布2024-09-08 11:01:37
1680
发布2024-09-08 11:01:37
举报
文章被收录于专栏:Lua学习笔记C++入门基础知识

Lua Table 简介

  • Table 结构:在Lua中,table是一种可以存储键值对的数据结构,它既可以用作数组(通过数字索引来访问元素),也可以用作字典(通过任意类型作为键),作为二者的结合体使用也是可以的
  • 索引:除了 nil 和 NaN 外,任何Lua值都可以作为table的索引。
  • 动态调整大小:table没有固定的大小限制,你可以根据需要添加或删除元素。
  • 内存管理:由于Lua的垃圾收集机制,当没有任何引用指向table时,它将被自动回收。 相应的代码Lua层面构造表的使用

CPP的基本调用Lua脚本代码

代码语言:cpp
复制
#include <stdio.h>
#include <lua.hpp>

int mian()
{
	lua_State* L = luaL_newstate();

	luaL_openlibs(L);

	luaL_dofile(L, "LuaTableTest.lua");

	lua_close(L);
	return 0;
}

表是Lua特有的功能强大的东西。

在Lua脚本中,可以使用 {} 来创建一个空表,并通过直接赋值的方式来初始化数组或字典。例如,通过 myTablekey = value 的形式,可以向表中添加元素。

1.Lua构造表使用例

代码语言:lua
复制
-- LuaTableTest.lua
-- 创建一个空表
local myTable = {}

-- 作为数组使用
myTable[1] = "Hello"
myTable[2] = "World"

-- 作为字典使用
myTable.name = "Alice"
myTable.age = 25

-- 遍历table
for k, v in pairs(myTable) do
    print(k, v)
end

-- 输出: 输出顺序是随机的,因为TableTable的遍历顺序是随机的
-- 1 Hello
-- 2 World
-- name Alice
-- age 25

2.Lua表库函数使用例

Lua提供了一组丰富的内置函数来帮助操作table,比如table.concat用于连接表中的元素为一个字符串,table.insert用于在指定位置插入新的元素,table.move用于移动表中的元素,table.remove用于移除元素等。

另外,无论何时,若一个操作需要取表的长度,这张表必须是一个真序列,或是拥有 __len 元方法。所有的库函数都忽略传入参数的那张表中的非数字键。

1.链接.插入.移动.移除演示

  • table.concat (list , sep , i , j)
    • list:表
    • sep:分隔符,默认值是空串
    • i:起始索引,默认为1
    • j:结束索引,默认为#list

提供一个列表,其所有元素都是字符串或数字,

返回指定表中从start位置到end位置且每个元素以特定分隔符分割的字符串

注意:当使用 table.concat 函数时,它默认会按照数值索引的顺序连接表中的元素,忽略非数值索引的键值对。

  • table.insert (list, pos, value)
    • list: 表
    • pos: 位置(Lua的索引是从1开始的)
    • value: 值

在 list 的位置 pos 处插入元素 value , 并后移元素 listpos, listpos+1, ···, list#list 。 pos 的默认值为#list+1既数组末尾 , 因此调用 table.insert(t,x) 会将 x 插在列表 t 的末尾。

  • table.move (a1, f, e, t ,a2)
    • a1: 源表
    • f: 开始索引
    • e: 结束索引
    • t: 目标索引
    • a2: 目标表,默认为a1

将开始索引到结束索引区间内的元素从表 a1 移动到表 a2目标索引开始的位置。

目标区间可以和源区间重叠。 索引 f 必须是正数。

  • table.remove (list , pos)
    • list: 表
    • pos: 位置,默认为#list

移除 list 中 pos 位置上的元素,并返回这个被移除的值。 当 pos 是在 1 到 #list 之间的整数时, 它向前移动元素 listpos+1, listpos+2, ···, list#list 并删除元素 list#list; 索引 pos 可以是 #list + 1 ,或在 #list 为 0 时可以是 0 ; 在这些情况下,函数删除元素 listpos。

代码语言:lua
复制
-- LuaTableFunc.lua
local src = {a=1, b=2,'a', 'b', 'c', 'd'}
-- 数值索引:1='a', 2='b', 3='c'
-- 字符串键:'a'=1, 'b'=2  a=1和b=2是非数字键索引被忽略了
-- concat
print('-------------concat------------')
print(table.concat(src, ','))    -- 输出: a,b,c,d --忽略了a=1,b=2的值
print(table.concat(src, '|',1,3)) -- 输出: a|b|c
table.insert(src, 2, 'x') -- 在2的位置插入x
print(table.concat(src, '#')) -- 输出:a#x#b#c#d

-- insert
print('-------------insert------------')
local insertTest = {1, 2, 3}
table.insert(insertTest, 1, 'a') -- 在1的位置插入a
print(table.concat(insertTest, ','))      -- 输出: a,1,2,3

-- move
print('-------------move------------')
local moveTest = {}
table.move(src, 1, 3, 1, moveTest)
print(table.concat(moveTest, '|'))    -- 输出: a|x|b

-- remove
print('----------------remove-----------')
local removeTest = {1, 2, 3}
print('remove:'..table.remove(removeTest)) -- remove:3
print(table.concat(removeTest, ',')) -- 输出 1,2
table.insert(removeTest,'3') -- 在末尾插入3
print(table.concat(removeTest, '|')) -- 输出 1|2|3

2.sort和pack跟unpack函数示例

  • table.sort (list , comp)
    • list: 表
    • comp: 比较函数,默认使用 <

可以类比于cpp里的sort库函数

注意:当内容中既有number类型又有string类型的元素时,无法进行排序。

在表内从 list1 到 list#list 原地 对其间元素按指定次序排序。 如果提供了 comp , 它必须是一个可以接收两个列表内元素为参数的函数。 当第一个元素需要排在第二个元素之前时,返回真 (因此 not comp(listi+1,listi) 在排序结束后将为真)。 如果没有提供 comp, 将使用标准 Lua 操作 < 作为替代品。

  • table.pack (···) 返回用所有参数以键 1,2, 等填充的新表, 并将 "n" 这个域设为参数的总数。 注意这张返回的表不一定是一个序列。
  • table.unpack (list , i , j)
    • list: 表
    • i: 起始索引,默认为1
    • j: 结束索引,默认为#list

返回列表中的元素。 这个函数等价于return listi, listi+1, ···, listj

i 默认为 1 ,j 默认为 #list。

代码语言:lua
复制
-- LuaTableFunc.lua

-- sort
print('-------------sort------------')
local sortTest = {'b', 'a', 'c', 'd'}
table.sort(sortTest)
for i,v in ipairs(sortTest) do
    print(i,v)
end
-- 输出 
-- 1	a
-- 2	b
-- 3	c
-- 4	d

-- pack And unpack
print('-------------pack--unpack---------')
local packTest = table.pack(4, 3, 2, 1)
print(packTest.n)      -- 输出: 4 -- n是数组的长度
print(table.unpack(packTest))   -- 输出: 4 3 2 1

print(table.unpack(packTest, 2, 3))     -- 输出: 3 2

C/C++层面构造表的使用

在C/C++中,通过Lua API可以创建和操作Lua表。例如,可以使用lua_newtable来创建一个新的空表,并使用lua_pushstring和lua_setfield来设置表中的键值对。此外,还可以通过lua_setglobal将表设置为全局变量,以便在Lua脚本中访问。之后,通过加载并执行Lua脚本来处理这些表。

1.CPP层面代码

代码语言:cpp
复制
// lua_pop(L,弹出栈顶元素数量1开始 );

#include <stdio.h>
#include <lua.hpp>

int main()
{
	// 创建一个虚拟机
	lua_State* L = luaL_newstate();

	// 加载一些常用的系统库
	luaL_openlibs(L);

	/*------创造一个表,并设置键值对------ */
	lua_newtable(L); // 创建一个新的 Lua 表,并将其压入栈顶。

	lua_pushstring(L, "xmr"); // 将字符串 "xmr" 压入栈顶。
	lua_setfield(L, 1, "name"); // 将栈顶的值设置为表中键 "name" 对应的值。
	// 此时栈顶的值是 "xmr",而索引 1/-2 指向的是刚创建的表,因此相当于为表添加了一个键 "name" 和对应的值 "xmr"。

	lua_pushstring(L, "Hello World"); // 将字符串 "Hello World" 压入栈顶。
	lua_rawseti(L, -2, 1); // 将栈顶的值设置为表中索引 1 对应的值。
	// 这里使用 `-2`/用1也可以,一般建议用-2 是为了获取表的索引(即上一步创建的表),然后设置索引 1 的值为 "Hello World"。

	lua_setglobal(L, "tab"); // 将当前创建的表设置为全局变量 "tab"。
	// 此时栈顶的值是刚创建的表,该表有两个元素:`name = "xmr"` 和 `[1] = "Hello World"`。

	/*--------------------------------*/

	// 加载 Lua 文件并执行,文件名为 "luaTableTest.lua"
	if (luaL_dofile(L, "CTestLuaTable.lua"))
	{
		// 如果 Lua 文件执行失败,则 Lua 错误会被压入栈顶。
		printf("%s\n", lua_tostring(L, -1)); // 输出错误信息。
	}

	// 关闭虚拟机
	lua_close(L);
	return 0;
}

//代码流程总结
//创建 Lua 虚拟机:使用 luaL_newstate() 创建一个新的 Lua 虚拟机实例。
//加载 Lua 标准库:使用 luaL_openlibs() 加载 Lua 标准库。
//创建 Lua 表:
//使用 lua_newtable() 创建一个新的空表,并将其压入栈顶。
//使用 lua_pushstring() 和 lua_setfield() 设置表中键 "name" 的值为 "xmr"。
//使用 lua_pushstring() 和 lua_rawseti() 设置表中索引 1 的值为 "Hello World"。
//设置全局变量:使用 lua_setglobal() 将创建的表设置为全局变量 "tab"。
//执行 Lua 脚本:使用 luaL_dofile() 加载并执行 Lua 脚本 "luaTableTest.lua"。
//输出结果:脚本执行后,输出表 "tab" 中键 "name" 和索引 1 对应的值。
//关闭虚拟机:使用 lua_close() 关闭 Lua 虚拟机。

2.Lua接收到CPP传过来的表使用例

在Lua脚本中,可以简单地通过全局变量名来访问由C/C++创建并设置的表,例如print(tab.name)和print(tab1),分别输出表tab中键name和索引1对应的值。

代码语言:lua
复制
-- CTestLuaTable.lua
print(tab.name)  -- 输出表 "tab" 中键 "name" 对应的值。
print(tab[1])    -- 输出表 "tab" 中索引 1 对应的值。

总结

在Lua中,table是一种非常灵活且强大的数据结构,它可以用来存储键值对,既可以作为数组使用(通过数字索引来访问元素),也可以作为字典使用(通过任意类型作为键)。这种灵活性使得table成为了Lua中处理数据的主要工具之一。table没有固定的大小限制,可以根据需要动态地添加或删除元素,并且由于Lua的自动垃圾回收机制,当没有任何引用指向一个table时,它将被自动回收,从而有效地管理内存。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • Lua Table 简介
    • 1.Lua构造表使用例
      • 2.Lua表库函数使用例
        • 1.链接.插入.移动.移除演示
        • 2.sort和pack跟unpack函数示例
    • C/C++层面构造表的使用
      • 1.CPP层面代码
        • 2.Lua接收到CPP传过来的表使用例
        • 总结
        领券
        问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档