use*_*185 2 string-formatting rust
通常一个人要打印一个字节为2个十六进制数字,例如10应该给0x0a。在Rust中,可能会使用println!("{:#02x}", 10),但是它给出了0xa。
我尝试过的事情列表(使用std::fmt和中的信息fmt::LowerHex以及一些StackOverflow问题):
println!("{:#02x}", 10);
println!("{:#0x}", 10);
println!("{:#x}", 10);
println!("{:#x?}", 10);
println!("{:#0x?}", 10);
println!("{:#02x?}", 10);
Run Code Online (Sandbox Code Playgroud)
全部输出0xa,而不是期望的行为0x0A。
该问题已被编辑(消除了相关的情绪),随后被标记为其他问题的重复。但是其他答案不能解决为什么上面的列表不起作用。在#意想不到的输出(格式选项的结果0xa),尤其是02,出人意料的是,已经完全没有作用!没有其他问题对此#特别关注。
use*_*185 18
如果您使用:
println!("10 is 0x{:02x} in hex", 10); // ==> "0x0a"
Run Code Online (Sandbox Code Playgroud)
代替:
println!("10 is {:#02x} in hex", 10); // "0xa"
Run Code Online (Sandbox Code Playgroud)
有用。
然而,正如评论者指出的那样,这不是错误,而是对 的含义的混淆02。它并不意味着有效数字的最小数量,而是字符的最小总数,现在必须包括0x。所以这也有效:
println!("10 is {:#04x} in hex", 10); // "0x0a"
Run Code Online (Sandbox Code Playgroud)
但这个解决方案以及将其推广为“正确”解决方案的文化存在问题。
首先请注意,包含0xthrough#促进了总宽度的概念,04现在指定了总宽度。需要在心里减去 2 才能得到有效数字,即重要部分。不管怎样,{:#04x}都会将 10000 格式化为0x2710,它占用 6 个字符,而不是 4 个。所以总宽度的概念失败了,作为一个概念,也许太琐碎了。
此外{:#03x},令人困惑的{:#02x}是,{:#01x}所有结果都与`{:#x}具有相同的行为,并且不会被编译器(1.35)标记,尽管它们没有意义并指示错误。
其次,#格式化程序仅对 Rust 特定的数字表示有用,例如插入0x但不是$(另一种常见的十六进制表示格式)。
第三,至关重要的是,只有在使用格式化程序时,总宽度的概念才变得明确#(然后在常见字节情况下默默地失败)。格式化程序#意味着 Rust 可以选择考虑总宽度,并且应该在应用时使用它(即在固定宽度布局的上下文中)。
其余部分说明了为什么它#是特殊情况解决方案,以及为什么在一般情况下不推荐它。
应根据上下文选择格式化程序字符串,特别是人们如何考虑在该上下文中显示数字,因为所选格式表达了意图。所以:
{:#04x}专注于总宽度,在进行严格的固定宽度表格布局时很有用。在这种情况下,格式化程序#显然符合人体工程学。{:#04x}在生成自定义格式化字符串(给定固定宽度上下文)时显然也很有用,例如,当输出需要根据需要从十六进制更改为二进制时(例如更改{:#04x}为{:#04b}),尽管很难想象具体情况。
0x{02x}表示有效数字的数量,当主要关注的是如何在给定有限空间的情况下在一行上表示信息时很有用。在这种情况下,常见的编辑是删除0x. 使用0x{:02x}可以0x简单地删除,而使用{:#04}格式化程序则需要删除并#替换。两种情况的最终结果是相同的:,但需要概念转变。0402{:02x}#
根据具体情况,#格式化程序是否符合人体工程学并能表达意图,也可能不符合人体工程学。使用与您想要实现的目标相符的格式。但在一般情况下,最好将其视为#相对模糊的功能。仅在明确定义的情况下才需要其额外的智能。
不幸的是,其他答案建议{:#04x}默认为“正确”或“Rust 解决方案”。然而,某个特性 ( #) 可用这一事实并不意味着: - Rust 认可它,或者建议使用它, - 需要表达总宽度的基本概念,或者 - 总宽度的概念应该概括所有 Rust 格式表达式(这是大多数答案所证明的根本问题)
总而言之,Rust 已经#可用,但0x{:02x}通常仍然更简单、更切题并且得到普遍认可。它是KISS并且没有隐藏的缺陷。
如std::fmt模块中所述:
#-此标志指示应使用“备用”打印形式。替代形式为:
#x-在参数前加0x#X-在参数前加0x
这与请求宽度相互作用,因为宽度占整个替换的范围,因此0x0a是4个字符,而不是2 个字符。
如果请求的宽度小于必需的宽度,则忽略请求的宽度,而使用最小宽度(此处为3个字符)。
在操场上进行快速实验:
fn main() {
println!("{:#01x}", 10);
println!("{:#02x}", 10);
println!("{:#03x}", 10);
println!("{:#04x}", 10);
println!("{:#05x}", 10);
println!("{:#06x}", 10);
}
Run Code Online (Sandbox Code Playgroud)
印刷品:
fn main() {
println!("{:#01x}", 10);
println!("{:#02x}", 10);
println!("{:#03x}", 10);
println!("{:#04x}", 10);
println!("{:#05x}", 10);
println!("{:#06x}", 10);
}
Run Code Online (Sandbox Code Playgroud)
一切都很好。