2017-06-22 31 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)總是在那裏,這只是「哪一點是什麼「沒有真正記錄...... –

相關問題