如何创建一个动态打印十六进制整数的宏,前导零

时间:2017-10-27 20:11:59

标签: macros rust println

我希望创建一个宏,它将以十六进制显示一个数字类型,其前导零等于其大小。例如,hex!(2u8)将打印$02(前导零),hex!(2u16)将打印$0002(16位前导零)

这就是我现在所拥有的,但它仅适用于8位数字。它将显示大于8位的数字,但不会显示等于大小的前导零。我需要一种方法来替换2${:02X}的整数大小,但print!()宏需要字符串文字。

macro_rules! hex {
    ($val:expr) => {{
        println!("${:02X}", $val);
    }}
}

2 个答案:

答案 0 :(得分:5)

我建议使用包装结构而不是直接在某处打印,而不是根据您的需要格式化内容:

use std::fmt;

#[derive(Debug)]
pub struct UpperHexLeadingZeroes<T>(pub T);
impl<T: fmt::UpperHex> fmt::Display for UpperHexLeadingZeroes<T> {
    fn fmt(&self, w: &mut fmt::Formatter) -> fmt::Result {
        use std::mem::size_of;
        let width = size_of::<T>() * 2; // 2 nibbles per byte
        write!(w, "${:0width$X}", self.0, width = width)
    }
}

像这样使用:

fn main() {
    println!("{}", UpperHexLeadingZeroes(2u8));
    println!("{}", UpperHexLeadingZeroes(2u16));
    println!("{}", UpperHexLeadingZeroes(2u32));
    println!("{}", UpperHexLeadingZeroes(2u64));
}

答案 1 :(得分:4)

你真的不需要一个宏。使用Formatter's dollar syntax,可以根据表达式指定打印值的宽度,如此处所示。

fn hex<T: UpperHex>(e: T) {
    println!("{:01$X}", e, mem::align_of::<T>() * 2);
}

Playground