Lua中string.format函数的布尔插值字符是什么?

4

我正在寻找适用于 string.format 的布尔插值字符(如标题所述)。
我希望找到这样一种东西:

print(string.format("nil == false: %b",(nil==false))

%b只是一个占位符,使用它会导致错误。我需要的是“b”。我不能仅仅这样做:

print("nil == false: " .. (nil==false))

因为布尔值不能与字符串拼接。我可以这样做:

val=(nil==false)
if val==false then truth="false" else truth="true" end
print("nil==false: ".. truth)

但这需要做很多工作。


print("nil == false: " .. tostring(nil==false)) 是什么意思? - greatwolf
2个回答

5
首先,你应该尝试阅读手册的相关部分。这将让你发现,没有布尔格式说明符。
greatwolf建议的是一种解决方案,即显式地将值转换为字符串。如果你的真值可能为nil,但你想将它输出为false,那么这个技巧是有用的:
truth = nil
print("nil==false: ".. tostring( not not truth ))

以这种方式,nilfalse都会显示为false编辑(回答评论):
在Lua 5.2中,%s指定符会自动使用tostring将参数内部转换为字符串。因此:
print( string.format( "%s  %s  %s", true, nil, {} ) )

打印:

true  nil  table: 00462400

否则,您可以创建自己的格式化函数,将 string.format 包装起来:
 local function myformat( fmt, ... )
    local buf = {}
     for i = 1, select( '#', ... ) do
         local a = select( i, ... )
         if type( a ) ~= 'string' and type( a ) ~= 'number' then
             a = tostring( a )
         end
         buf[i] = a
     end
     return string.format( fmt, unpack( buf ) )
 end


 print( myformat( "%s  %s  %s", true, nil, {} ) )

考虑到它比其他选择更短,这很公平。不过我很好奇,是否可以使用 CC++ 添加/扩展 string.format 以使用新的布尔字符? - Plakhoy
@Sefault 当然可以,但需要一些操作。请查看我的回复,了解一种实现方法。 - greatwolf
如果您的 C 语言技能很好,您可以修改源代码。我的编辑中显示了一种更简单的方法。如果您真的想要一个新的格式说明符,请查看 greatwolf 的答案,但我认为这有点过度设计。 - Lorenzo Donati support Ukraine
你的方法似乎可行。select 做什么?Lua 参考文献并不是很有帮助。此外,为什么 @greatwolf 的答案过于复杂了?在我看来,它相当令人印象深刻和聪明。 - Plakhoy
@Segfault我完全同意你对greatwolf聪明的看法。当我说“过度杀伤力”时,我的意思是这样的努力可能不值得解决问题。作为概念证明或有用技术示例,它非常棒,但在这种情况下,就像用大炮打苍蝇一样(当然这不是greatwolf的错)。我质疑是否真的值得所有的麻烦和混乱,只为了能够有一个布尔型的格式说明符。请记住,Lua 5.2%s可以处理所有转换。 - Lorenzo Donati support Ukraine
显示剩余2条评论

5
如果你想知道如何修改string.format以支持布尔值,这里提供一种可行的方法:
do
local format = string.format
function string.format(str, ...)
  local args = {...}
  local boolargs = {}
  str = str:gsub("%%b", "%%%%b")
  for i = #args, 1, -1 do
    if type(args[i]) == "boolean" then
      table.insert(boolargs, 1, args[i])
      table.remove(args, i)
    end
  end
  str = format(str, unpack(args))

  local j = 0
  return (str:gsub("%%b", function(spec) j = j + 1; return tostring(boolargs[j]) end))
end
end

print(string.format("%s is %b", "nil == false", nil==false))

可能有点难以理解。这个想法是在字符串中用gsub替换所有的“%b”,并将其替换为双重转义%%b,以便格式不会尝试解释它。我们让string.format做它的事情,然后我们手动处理结果中的%b


@Segfault 实际映射到格式规范的项目在传递的 ... 部分中。在将其提供给真正的 string.format 之前,我们必须从中删除所有布尔值。但是,我们还需要保留那些已删除的布尔值,以便稍后知道要替换什么。变长参数 ... 在 Lua 中不是一级构造,因此我将其包装成一个表格,以便更轻松地操作。 - greatwolf
我必须说,你的回答令人印象深刻。为什么 g=... 存储了函数传递的第一个参数,而 f={...} 存储了参数表?此外,为什么你要使用 local args={...},而已经有一个隐式的 arg 表被传递了呢? - Plakhoy
我明白了,谢谢。我的意思是举个例子,就像这样:`function func(...) g=... f={...} print(f) -- table: 0076B070 print(g) -- "first arg" end func("first arg","second arg")`为什么fg不一样?值的调整? - Plakhoy
@Segfault 这是因为 f = {...} 在包装参数的过程中创建了一个新的表。另一方面,g = ...,右侧有1个或多个参数,但左侧只能适合一个参数。如果你有 g, h, i = ...,那么你从右侧获取前3个参数,并将它们分别放入 g, h, i 中。 - greatwolf

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接