2017-06-22 20 views
5

我最初的意图是以保留数字符号的方式将带符号的原始数字转换为其十六进制表示。事实证明,LowerHex,UpperHex和有符号的原始整数的亲属的当前实现将简单地将它们视为无符号。无论我添加哪些额外的格式化标志,这些实现似乎都只是将数字重新解释为其未格式化的对应格式。 (Playground如何将有符号整数格式化为符号感知十六进制表示形式?

println!("{:X}", 15i32);   // F 
println!("{:X}", -15i32);   // FFFFFFF1 (expected "-F") 
println!("{:X}", -0x80000000i32); // 80000000 (expected "-80000000") 
println!("{:+X}", -0x80000000i32); // +80000000 
println!("{:+o}", -0x8000i16);  // +100000 
println!("{:+b}", -0x8000i16);  // +1000000000000000 

std::fmt的文档并不清楚这是否是应该发生的,或者甚至是有效的,并且UpperHex(或任何其他格式性状)没有提到有符号整数实现解释数字为无符号。 Rust的GitHub存储库似乎没有相关的问题。

最终,人们可以为该任务实现特定的功能(如下所示),不幸的是,它与格式化程序API不兼容。

fn to_signed_hex(n: i32) -> String { 
    if n < 0 { 
     format!("-{:X}", -n) 
    } else { 
     format!("{:X}", n) 
    } 
} 

assert_eq!(to_signed_hex(-15i32), "-F".to_string()); 

此行为是否为有意识的有符号整数类型?有没有办法做到这一点格式化程序,同时仍然坚持标准Formatter

回答

4

有没有办法做到这一点格式化过程,同时仍然坚持标准Formatter

是的,但是您需要创建一个新类型以提供UpperHex的独特实现。下面是尊重+#0标志(也可能更多,我还没有测试)的实现:

use std::fmt::{self, Formatter, UpperHex}; 

struct ReallySigned(i32); 

impl UpperHex for ReallySigned { 
    fn fmt(&self, f: &mut Formatter) -> fmt::Result { 
     let prefix = if f.alternate() { "0x" } else { "" }; 
     let bare_hex = format!("{:X}", self.0.abs()); 
     f.pad_integral(self.0 >= 0, prefix, &bare_hex) 
    } 
} 

fn main() { 
    for &v in &[15, -15] { 
     for &v in &[&v as &UpperHex, &ReallySigned(v) as &UpperHex] { 
      println!("Value: {:X}", v); 
      println!("Value: {:08X}", v); 
      println!("Value: {:+08X}", v); 
      println!("Value: {:#08X}", v); 
      println!("Value: {:+#08X}", v); 
      println!(); 
     } 
    } 
} 
+0

我发誓访问格式化选项没有以前是有,但它看起来像他们自1.5.0以来,我一直在那里,所以我不知道我在想什么。 – Shepmaster

+0

['flags()'](https://doc.rust-lang.org/nightly/std/fmt/struct.Formatter.html#method.flags)总是在那里,这只是“哪一点是什么“没有真正记录...... –

相关问题