这章的内容主要是集中在如何保存一张表的数据。
如何保存循环表和共享表。
循环表:在一张表中有一个元素是本张表
例如:
a = {1,2,3}
a[4] = a;
共享表:两张表中包含了一张一样的表。
例如:
a = {1,2,3,{4,5,6}}
b = {a[4],7,8,9}
以下代码是对循环表的打印,目前只能打印到屏幕上,等学会了如何写文件,就可以把打印动作换成写文件动作了。
function GS(value)
if type(value) == "number" then
return tostring(value)
elseif type(value) == "string" then
return string.format("%q",value)
end
end
function save(name,value,saved)
saved = saved or {}
io.write(tostring(name)," = ")
if type(value) == "string" or type(value) == "number" then
io.write(GS(value),"\n")
elseif type(value) == "table" then
if saved[value] then
io.write(saved[value],"\n")
else
saved[value] = name
io.write("{}\n")
for k,v in pairs(value) do
local filedname = string.format("%s[%s]",name,GS(k))
save(filedname,v,saved)
end
end
end
end
do
local num = {10,x=11,12}
num[3] = num
save('num',num);
end
我们从最后一块do…end看起
这块是程序运行的入口,首先我是先定义了一个局部的循环表,可以发现,表中索引为3的域(我更喜欢叫它元素),是这张表本身,这个样子就变成了一张循环表。
save函数是保存动作的主体。可以看到实际save函数是有三个形式参数的,但是主体调用的时候只填写了两个实际参数,这个就是之前基础中,函数的形式参数的多值赋值机制了。
save函数在收到需要保存的值的名称和值之后,先检查值是什么类型的,如果是简单的string类型和number类型,就会先调用GS函数,进行一下简单的序列化(全都变成字符类型),然后保存(这里是打印,我还不会写文件,所以用打印代替了)。
如果判断为是表类型的数据,就先检查saved表(saved会记录保存过的表)中是否有这张表保存过,如果没有那就行打印一个{}表示这个值是个表类型,然后通过遍历这张表的每一个元素再次调用save函数去保存每一元素(看起来有点像递归)。
当程序检测到num[3]的时候,会发现它也是一张表,然后对比了一下saved发现上次存过了,然后就把这个表的名字返回来给num[3],这里就完成了循环表的保存。
由于共享表的共享部分有可能是在另一张表中,所以saved这张表必须要在全局变量中,这样就可以对共享表进行类似循环表的操作:
do
local num1 = {10,x=11,12,{1,2,3}}
local num2 = {6,7,8,num1[3]}
local Saved = {}
save('num1',num1,Saved)
save('num2',num2,Saved)
end