Rust十进制转十六进制程序输出带Some前缀的问题求助
问题描述
我用Rust写了一个十进制转十六进制的转换器,功能逻辑是对的,但输出结果前面总是带Some前缀,比如输出成Some("1")Some("A")Some("4")。我怀疑是String::from导致的问题,或者需要对结果做解析?目前正在学Rust,还没摸透细节,求帮忙解决。附上main.rs代码:
use std::{ io::{ self, Write, }, }; use std::collections::HashMap; use std::process; fn main() { let mut hex_number_system = HashMap::new(); hex_number_system.insert(1,String::from("1")); hex_number_system.insert(2,String::from("2")); hex_number_system.insert(3,String::from("3")); hex_number_system.insert(4,String::from("4")); hex_number_system.insert(5,String::from("5")); hex_number_system.insert(6,String::from("6")); hex_number_system.insert(7,String::from("7")); hex_number_system.insert(8,String::from("8")); hex_number_system.insert(9,String::from("9")); hex_number_system.insert(10,String::from("A")); hex_number_system.insert(11,String::from("B")); hex_number_system.insert(12,String::from("C")); hex_number_system.insert(13,String::from("D")); hex_number_system.insert(14,String::from("E")); hex_number_system.insert(15,String::from("F")); let mut line = 0; let mut current_multiplier = 0; let mut current_num = String::new(); let mut digit_num = 256; print!("Enter a number from 0 - 4095:"); io::stdout().flush().unwrap(); let mut input = String::new(); io::stdin().read_line(&mut input).unwrap(); println!("{:?}", input); let mut user = input.trim().parse::<i32>().unwrap(); if user > 4095 { println!("Too high"); process::exit(1); } if user < 0 { println!("Too low"); process::exit(1); } for i in 1..=3 { current_multiplier = 15; loop { if current_multiplier == 0 { print!("{}", 0); digit_num /= 16; break; } if user >= (current_multiplier * digit_num) { print!("{:?}", hex_number_system.get(¤t_multiplier)); user -= &digit_num * ¤t_multiplier; digit_num /= 16; break; } else { current_multiplier -= 1; } } } print!(" "); }
问题原因
问题和String::from完全无关,根源在这行代码:
print!("{:?}", hex_number_system.get(¤t_multiplier));
HashMap的get方法返回的是Option<&String>类型——因为Rust无法保证你传入的键一定存在于HashMap中,所以用Option包裹结果:存在就返回Some(值),不存在返回None。而你用{:?}(Debug格式化)输出时,就会把Option的完整结构打印出来,也就是你看到的Some("X")。
解决方法
1. 取出Option中的值
因为你的逻辑里current_multiplier是从15往下遍历到1,而HashMap里已经存了1-15的所有键,所以这里可以安全地用unwrap()取出Some里的值,同时把格式化符从{:?}改成{}(普通格式化):
把上述代码行改成:
print!("{}", hex_number_system.get(¤t_multiplier).unwrap());
如果想更稳妥(比如防止意外键不存在的情况),可以用unwrap_or指定默认值:
print!("{}", hex_number_system.get(¤t_multiplier).unwrap_or(&String::from("0")));
2. 修复输入打印的小问题
你的代码里println!("{:?}", input);会把输入的字符串连同引号和换行符一起打印(比如输入123会输出"123\n"),改成普通格式化更友好:
println!("{}", input.trim());
修改后的完整代码
use std::{ io::{ self, Write, }, }; use std::collections::HashMap; use std::process; fn main() { let mut hex_number_system = HashMap::new(); hex_number_system.insert(1,String::from("1")); hex_number_system.insert(2,String::from("2")); hex_number_system.insert(3,String::from("3")); hex_number_system.insert(4,String::from("4")); hex_number_system.insert(5,String::from("5")); hex_number_system.insert(6,String::from("6")); hex_number_system.insert(7,String::from("7")); hex_number_system.insert(8,String::from("8")); hex_number_system.insert(9,String::from("9")); hex_number_system.insert(10,String::from("A")); hex_number_system.insert(11,String::from("B")); hex_number_system.insert(12,String::from("C")); hex_number_system.insert(13,String::from("D")); hex_number_system.insert(14,String::from("E")); hex_number_system.insert(15,String::from("F")); let mut current_multiplier = 0; let mut digit_num = 256; print!("Enter a number from 0 - 4095:"); io::stdout().flush().unwrap(); let mut input = String::new(); io::stdin().read_line(&mut input).unwrap(); println!("{}", input.trim()); let mut user = input.trim().parse::<i32>().unwrap(); if user > 4095 { println!("Too high"); process::exit(1); } if user < 0 { println!("Too low"); process::exit(1); } for _ in 1..=3 { current_multiplier = 15; loop { if current_multiplier == 0 { print!("0"); digit_num /= 16; break; } if user >= (current_multiplier * digit_num) { print!("{}", hex_number_system.get(¤t_multiplier).unwrap()); user -= digit_num * current_multiplier; digit_num /= 16; break; } else { current_multiplier -= 1; } } } println!(); }
额外优化建议
因为你的映射关系是连续的数字1-15对应十六进制字符,用HashMap有点小题大做,直接用match表达式更高效简洁:
fn num_to_hex(n: i32) -> &'static str { match n { 1 => "1", 2 => "2", 3 => "3", 4 => "4", 5 => "5", 6 => "6", 7 => "7", 8 => "8", 9 => "9", 10 => "A", 11 => "B", 12 => "C", 13 => "D", 14 => "E", 15 => "F", _ => "0", } }
然后把之前HashMap的部分替换成调用这个函数,比如:
print!("{}", num_to_hex(current_multiplier));
这样代码会更简洁,也避免了HashMap的初始化开销。
内容的提问来源于stack exchange,提问作者FordoA455

