How do I format a signed integer to a sign-aware hexadecimal representation?

前端 未结 2 778
执念已碎
执念已碎 2020-12-20 17:18

My initial intent was to convert a signed primitive number to its hexadecimal representation in a way that preserves the number\'s sign. It turns out that the current implem

相关标签:
2条回答
  • 2020-12-20 18:06

    This is like Francis Gagné's answer, but made generic to handle i8 through i128.

    use std::fmt::{self, Formatter, UpperHex};
    use num_traits::Signed;
    
    struct ReallySigned<T: PartialOrd + Signed + UpperHex>(T);
    
    impl<T: PartialOrd + Signed + UpperHex> UpperHex for ReallySigned<T> {
        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 >= T::zero(), prefix, &bare_hex)
        }
    }
    
    fn main() {
        println!("{:#X}", -0x12345678);
        println!("{:#X}", ReallySigned(-0x12345678));
    }
    
    0 讨论(0)
  • 2020-12-20 18:09

    Is there a way to do this formatting procedure while still adhering to a standard Formatter?

    Yes, but you need to make a newtype in order to provide a distinct implementation of UpperHex. Here's an implementation that respects the +, # and 0 flags (and possibly more, I haven't tested):

    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 讨论(0)
提交回复
热议问题