如何将 i32 转换为表示 ASCII 字符的字符串

4

这个周末我要用Rust重新做一个项目,需要将i32转换为ASCII字符并使用它作为字符代码。目前我只有一个庞大的match语句,我把它藏在文件的末尾。不幸的是,std::ascii不支持这种转换。目前我正在寻找一种更少荒谬/更符合Rust风格的方法来完成这个任务。

fn to_ascii(i: &i32) -> String {
    let a = match *i {
        0 => "NUL",
        1 => "SOH",
        2 => "STX",
        // ...
        125 => "}",
        126 => "~",
        127 => "DEL",
        _ => "",
    }
    a
}
5个回答

10

首先,你不需要返回一个String,一个&'static str就足够了。其次,你可以简单地设置一个包含所有代码表示的&'static str数组,并使用.get(_)获取相关字符串片段,只要所有字符代码是连续的(如果我对ASCII有所了解,它们应该是连续的)。即使它们并不连续,你也可以在空格中放置空字符串。

代码应该如下所示:

const CHARS: [&'static str; 128] = ["NUL", "SOH", "STX", .., "DEL"];

fn get_char_code(c: i32) -> &'static str {
    CHARS.get(c as usize).unwrap_or("")
}

谢谢,我想既然ASCII值不会真正改变,那么使用&'static str应该是可以的。 - user1610406

4

就我个人而言,我不介意采用match版本。唯一需要调整的是你不需要临时变量。我建议你遵循llogiq的回答,并返回一个&'static str,如果需要的话,你的调用者可以将其转换为String

fn get_char_code(i: &i32) -> &'static str {
    match *i {
        0 => "NUL",
        1 => "SOH",
        2 => "STX",
        // ...
        125 => "}",
        126 => "~",
        127 => "DEL",
        _ => "",
    }
}

此外,我强烈建议不要在这段代码中使用"ASCII"这个词。大多数程序员将"ASCII字符"视为一个数据的表示形式,它映射到特定的字符、标点符号或控制码。


2
您可以使用format!宏将char转换为String:
fn to_ascii(i: &i32) -> String {
    match *i {
        x@0...127 => format!("{:?}", x as u8 as char),
        _ => "".into(),
    }
}

fn main() {
    for x in 0x09..0x12 {
        print!("{} ", to_ascii(&x));
    }
    println!("");
    //'\t' '\n' '\u{b}' '\u{c}' '\r' '\u{e}' '\u{f}' '\u{10}' '\u{11}' 

    for x in 0x30..0x40 {
        print!("{} ", to_ascii(&x));
    }
    println!("");
    //'0' '1' '2' '3' '4' '5' '6' '7' '8' '9' ':' ';' '<' '=' '>' '?' 
}

这会返回转义代码'\u{0}'而不是缩写"NUL"。如果您不喜欢它的外观,可以使用大量匹配或字符串数组。

实际上,您只需要重新定义33个控制字符。对于其他可打印字符,您仍然可以使用 format!

fn to_ascii(i: &i32) -> String {
    match *i {
        x@0...32 => ["NUL", "SOH", "STX", ..., "SPC"][x as usize].into(),
        x@33...126 => format!("{}", x as u8 as char),
        127 => "DEL".into(),
        _ => "".into(),
    }
}

如果想要更加 Rust 风格的写法,可以使用类似Cow的智能指针作为返回类型:

use std::borrow::Cow;

fn to_ascii(i: &i32) -> Cow<'static, str> {
    match *i {
        x@0...32 => ["NUL", "SOH", "STX", ..., "SPC"][x as usize].into(),
        x@32...126 => format!("{}", x as u8 as char).into(),
        127 => "DEL".into(),
        _ => "".into(),
    }
}

关于Cow的使用,在此处阅读更多内容。


这个函数怎么样才能让0(或其他多个字符映射中的任何一个)返回“NUL”? - Shepmaster

0

你可以使用from_u32,而不是i32,来代替:

use std::char::from_u32;

fn main() -> Result<(), u32> {
   let n = 0x21;
   let c = from_u32(n).ok_or(n)?;
   println!("{}", c);
   Ok(())
}

0
你可以这样转换类型:
println!("{}", 'A' as i8); // prints 65
println!("{}", 65 as char); // prints 'A'

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接