如何将字节格式化为2位十六进制字符串,以Rust为例

如何将字节格式化为2位十六进制字符串,以Rust为例,rust,string-formatting,Rust,String Formatting,通常需要将一个字节打印为两个十六进制数字,例如10应给出0x0a。在Rust中,可以使用类似于println!(“{:#02x}”,10),但它给出了0xa 我尝试过的事情列表(使用和的信息和几个StackOverflow问题): println!(“{:#02x}”,10); 普林顿!(“{:#0x}”,10); 普林顿!(“{:#x}”,10); 普林顿!(“{:#x}”,10); 普林顿!(“{:#0x?}”,10); 普林顿!(“{:{02x}”,第10段); 它们都输出0xa,而不是

通常需要将一个字节打印为两个十六进制数字,例如
10
应给出
0x0a
。在Rust中,可以使用类似于
println!(“{:#02x}”,10)
,但它给出了
0xa

我尝试过的事情列表(使用和的信息和几个StackOverflow问题):

println!(“{:#02x}”,10);
普林顿!(“{:#0x}”,10);
普林顿!(“{:#x}”,10);
普林顿!(“{:#x}”,10);
普林顿!(“{:#0x?}”,10);
普林顿!(“{:{02x}”,第10段);
它们都输出
0xa
,而不是
0x0A
所需的行为


此问题已编辑(删除相关情绪),随后标记为其他问题的副本。但其他答案并没有说明为什么上面的列表不起作用。
#
格式选项会导致意外的输出(
0xa
),尤其是
02
,令人惊讶的是,它根本没有任何效果!没有其他问题关注这一点,也没有特别关注

如果您使用:

println!("10 is 0x{:02x} in hex", 10);       // ==> "0x0a"
而不是:

println!("10 is {:#02x} in hex", 10);        //     "0xa"
它起作用了

然而,正如评论员指出的,这不是错误,而是对
02
的含义的混淆。它不是指最小有效位数,而是指最小字符总数,现在必须包括
0x
。因此,这也是可行的:

println!("10 is {:#04x} in hex", 10);        //     "0x0a"
但这一解决方案和将其作为“正确”解决方案的文化都存在问题

首先请注意,通过
#
包含
0x
促进了总宽度的概念,而
04
现在规定了总宽度。一个人需要在心里减去2才能得到有效数字,这是有效部分。无论如何,
{:#04x}
将10000格式化为
0x2710
,它占用6个字符,而不是4个字符。所以总宽度的概念失败了,作为一个概念,也许太微不足道了

此外,
{:#03x}
{:#02x}
{:#01x}
都会产生与`{:#x}相同的行为,并且编译器(1.35)不会标记它们,尽管它们没有意义并且指示错误

其次,
#
格式化程序仅对特定的数字表示有用,例如插入
0x
,但不插入
$
(另一种常见的十六进制表示格式)

第三,至关重要的是,总宽度的概念只有在使用
#
格式化程序时才变得明确(然后在普通字节情况下无声地失败)。“代码”>格式化程序意味着Rube可以考虑总宽度,并且当它应用时应该使用它(即在固定宽度布局的上下文中)。p> 其余部分说明了为什么
#
是一种特殊情况下的解决方案,以及为什么在一般情况下不建议使用它

应根据上下文选择格式化程序字符串,特别是在所选格式表达意图时,如何考虑在该上下文中显示数字。因此:

  • {:#04x}
    关注总宽度,这在执行刚性固定宽度表格布局时非常有用。在这种情况下,
    #
    格式化程序显然符合人体工程学<代码>{:#04x}在生成自定义格式字符串(给定固定宽度的上下文)时显然也很有用,例如当输出需要按需从十六进制更改为二进制时(例如,
    {:#04x}
    {:#04b}
    ),尽管很难想象具体的情况

  • 0x{02x}
    表示有效位数,当主要关注如何在给定有限空间的情况下表示一行上的信息时,这很有用。在这种情况下,常见的编辑是删除
    0x
    。使用
    0x{:02x}
    时,只需删除
    0x
    ,而使用
    {:04}
    格式化程序时,需要同时删除
    并用
    04
    替换
    02
    。在这两种情况下,最终结果是相同的:
    {:02x}
    ,但
    #
    需要一个概念转换

根据具体情况,
#
格式化程序是否符合人体工程学和表达意图。使用与要实现的目标相匹配的格式。但在一般情况下,最好将
#
视为一个相对模糊的特性。它的额外智能性只有在定义明确的情况下才可取

不幸的是,其他答案建议将
{:#04x}
作为默认值,“正确”或“防锈剂”。但是,某些功能(
#
)可用并不意味着: -防锈剂,或建议使用它, -总宽度的基本概念需要表达,或 -总宽度的概念应该推广到所有的Rust格式表达式(这是大多数答案所证明的根本问题)

总之,
#
是可用的,但是
0x{:02x}
通常更简单、更切中要害并且得到普遍认可。它是并且没有隐藏的缺陷

如模块中所述:

#
-此标志表示应使用“替代”打印形式。其他形式包括:

  • #x
    -在参数前面加一个0x
  • #X
    -在参数前面加一个0x
这与请求宽度相互作用,因为宽度占整个替换,因此
0x0a
4个字符,而不是2个字符

如果请求的宽度小于所需的宽度,则将忽略请求的宽度,而使用最小宽度(此处为3个字符)

快速实验:

印刷品:

0xa
0xa
0xa
0x0a
0x00a
0x000a

一切都很好。

只是
println!(“{:#04x}”,10)--您如何知道这是一个长期存在的bug?您在github回购协议中有问题吗?
#
标志应该有不同的含义
fn main() {
    println!("{:#01x}", 10);
    println!("{:#02x}", 10);
    println!("{:#03x}", 10);
    println!("{:#04x}", 10);
    println!("{:#05x}", 10);
    println!("{:#06x}", 10);
}