为啥我的 LUA 解释器不能处理字符串键值?
Posted
技术标签:
【中文标题】为啥我的 LUA 解释器不能处理字符串键值?【英文标题】:Why isn't my LUA interpreter able to handle string key values?为什么我的 LUA 解释器不能处理字符串键值? 【发布时间】:2019-07-26 18:46:22 【问题描述】:同时使用预定义脚本和 LUA 运行时环境测试代码时,LUA 不会采用任何形式的字符串键值。但是,如果使用数值键,LUA 将按预期使用它。当我使用带有 LUA 文件的 Tshark 来解析数据包捕获时,此规则的例外情况。这允许字符串键值语法正常工作。有什么我可能做错了吗?
我尝试过创建多个不同变体的 .lua 脚本文件,包括:
testArray.NewItem = "value1" testArray["NewItem"] = "value1"
NewItemValue = "新项目" testArray[NewItemValue] = "value1"
这些都会导致 nil 值或由于尝试调用 nil 值而导致的错误,具体取决于用于检查的返回样式。
> tcpstream =
> stream1 = tostring(14356)
> tcpstream[stream1] = "nothing"
> print(#tcpstream)
0
> print(tcpstream[1])
nil
> tcpstream[1] = "nothing"
> print(#tcpstream)
1
> print(tcpstream[1])
nothing
在 tcpstream[stream1] = "nothing" 之后的 print(#tcpstream) 的输出应该显示 1 而不是零。随后的 print(tcpstream[1]) 也应该显示“nothing”。
【问题讨论】:
您的测试无效,因此您的结论无效。print(tcpstream[stream1])
打印“无”。
【参考方案1】:
来自http://lua-users.org/wiki/TablesTutorial
# 运算符不计算表中的所有项目 (!)。相反,它会找到最后一个整数(非小数)键。由于它的实现方式,如果表中的所有整数键都不连续,则其结果是不确定的。这就是为什么它不应该用于用作稀疏数组的表[2])。
“#”不是计算 Lua 表中元素数量的好方法(有时不正确)。
至于
> stream1 = tostring(14356)
> tcpstream[stream1] = "nothing"
> print(#tcpstream)
0
> print(tcpstream[1])
nil
Lua 使用键值对,而不是显式索引。如果你做'arr[1] = 22',这意味着键'1'的值是22,而不是第一个元素的值是22。
【讨论】:
您的参考对于撰写本文时的 Lua 版本是正确的。当前版本的参考手册给出了不同的描述。显然,应该使用开始使用版本的参考手册。如果#
用在它设计的表上,那是好的和正确的。【参考方案2】:
长度操作符(#
)不像你想象的那样工作,这是 Lua 初学者的常见错误。
#sometable
的默认行为是返回从数字 1
(或 5.3 的任何 nil 值之后)开始的连续键的数量。字符串键永远不会使用表的默认 #
运算符进行评估。
在 5.3 中,如果您的序列包含多个 nil 值,则 #
的行为是不确定的。
Lua 5.3 Reference Manual: 3.4.7 – The Length Operator
Lua 5.1 Reference Manual: 2.5.5 – The Length Operator
我将包含 5.1 中的行,因为我觉得它很好地涵盖了有关运算符和表格的信息。虽然注意与 5.3 的工作方式相同,但可能更容易理解为什么您会看到您所做的行为。
2.5.5 – 长度运算符 长度运算符由一元运算符# 表示。字符串的长度是它的字节数(即每个字符为一个字节时字符串长度的通常含义)。
表 t 的长度被定义为任意整数索引 n,使得 t[n] 不为 nil 且 t[n+1] 为 nil;此外,如果 t1 为零,则 n 可以为零。 对于一个从 1 到给定 n 的非 nil 值的常规数组,它的长度正好是 n,它的最后一个值的索引。 如果数组有“洞”(即 nil其他非 nil 值之间的值),那么 #t 可以是直接在 nil 值之前的任何索引(也就是说,它可以将任何这样的 nil 值视为数组的末尾)。
以下是不同表格的一些示例及其#
结果:
table1 = --number keys in array
true,
true,
true,
table2 = -- number keys in hash
[1] = true,
[2] = true,
[3] = true,
table3 = -- only strings as key
['1'] = true,
['2'] = true,
['3'] = true,
table4 = -- No key 2 defined
[1] = true,
-- [2] = true,
[3] = true,
table5 = -- table with both string and number keys
[1] = true,
['2'] = true,
print(#table1) -- 3
print(#table2) -- 3
print(#table3) -- 0
print(#table4) -- v5.3(1 or 3) v5.1(1)
print(#table5) -- 1
【讨论】:
“从数字 1 开始的连续键的数量”:这与您引用的 5.1 参考相矛盾。 @TomBlodget 我已将支持我的主张的手册中的声明加粗。如果该行没有消除矛盾,我可能需要更多信息来理解您所指的矛盾。#"one", "two", "three", nil, "five", nil, "seven"
根据您的描述,这将是 3。根据 5.1,它可以是任何整数 >= 0。根据 5.3,它可以是 3、5 或 7。简而言之,# 是误用在这样的表上。
@TomBlodget 5.3 是不确定的,我现在已经澄清了这一点。我仍在努力解决 5.1 的评论。以上是关于为啥我的 LUA 解释器不能处理字符串键值?的主要内容,如果未能解决你的问题,请参考以下文章
lua 与 c++或者c 交互的底层原理谁能解释一下?最最底层的,为啥它们调用C或者C++的函数?