如何在Rust中将字节格式化为2位十六进制字符串

时间:2019-06-06 21:12:09

标签: rust string-formatting

一个普通人想将一个字节打印为2个十六进制数字,例如10应该给0x0a。在Rust中,人们会使用类似println!("{:#02x}", 10)的东西,但它会给出0xa

我尝试过的事情列表(使用来自std::fmtfmt::LowerHex的信息以及一些StackOverflow问题):

println!("{:#02x}", 10);
println!("{:#0x}", 10);
println!("{:#x}", 10);
println!("{:#x?}", 10);
println!("{:#0x?}", 10);
println!("{:#02x?}", 10);

它们全部输出0xa,而不是0x0A的预期行为。


此问题已被编辑(消除了相关的情绪),随后被标记为其他问题的重复。但是其他答案不能解决为什么上面的列表不起作用。 #格式选项会导致意外的输出(0xa),特别是02令人惊讶地根本没有效果!没有其他问题着眼了这个,尤其是#上也是如此。

2 个答案:

答案 0 :(得分:6)

std::fmt模块中所述:

  

#-此标志指示应使用“备用”打印形式。替代形式为:

     
      
  • #x-在参数前加0x
  •   
  • #X-在参数前加0x
  •   

这与请求宽度交互,因为宽度占整个的替代,因此0x0a 4 个字符,而不是2个字符。

如果您请求的宽度小于必要宽度,则忽略请求的宽度,而使用最小宽度(此处为3个字符)。

快速实验on the playground

fn main() {
    println!("{:#01x}", 10);
    println!("{:#02x}", 10);
    println!("{:#03x}", 10);
    println!("{:#04x}", 10);
    println!("{:#05x}", 10);
    println!("{:#06x}", 10);
}

打印:

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

一切都很好。

答案 1 :(得分:-1)

如果您使用:

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#的引入包括总宽度的概念。一个人需要在精神上减去2才能得到有效位数,这是有效位数。不管04会将10000格式设置为{:#04x},它占用6个字符,而不是4个字符。因此,总宽度的概念失败了,作为一个概念,也许太简单了。

此外,0x2710{:#03x}{:#02x}都容易引起与`{:#x}相同的行为,尽管它们使编译器(1.35)不对其进行标记没有意义,并指出一个错误。

第二,{:#01x}格式器仅对特定于Rust的数字表示有用,例如插入#而不插入0x(另一种常见的十六进制表示格式)。

非常重要的是,总宽度的概念只有在使用$格式化程序时才变得明确(然后在普通字节情况下静默失败)。 #格式程序表示Rust具有该选项来考虑总宽度,并且在应用总宽度时(在固定宽度布局的情况下)应该使用它。

其余部分说明了为什么#是一种特殊情况的解决方案,以及为什么在一般情况下不建议使用它。

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

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

  • {:#04x}表示有效数字的数量,在主要关注点是如何在有限的空间内表示一行信息时,此数字很有用。在这种情况下,常见的修改是删除{:#04b}。使用0x{02x}可以简单地删除0x,而使用0x{:02x}格式化程序则需要同时删除0x并将{:#04}替换为{{1} }。两种情况下的最终结果是相同的:#,但是04需要概念上的转变。

根据情况,02格式化程序是符合人体工程学的,并且可以表达意图。使用与您要实现的目标相符的格式。但是在一般情况下,最好将{:02x}视为相对模糊的功能。仅在定义明确的情况下才需要其附加的智能功能。

不幸的是,其他答案建议将#作为默认值,“正确”或“可靠解决方案”。但是,某些功能(#)可用这一事实并不意味着: -Rust认可它,否则建议使用它, -总宽度的基本概念需要表达,或 -总宽度的概念应推广到所有Rust格式表达式(这是大多数答案所显示的根本问题)

总而言之,提供了#的锈迹,但是{:#04x}仍然通常更简单,更关键并且得到普遍认可。它是KISS,没有隐藏的缺陷