Muh*_*fil 0 parsing types rust
我正在制作十进制到二进制的转换程序。为什么我无法将字符串解析为数字?binary_vec[i]是一个character。我应用to_string()了将其转换为字符串的方法,因为parse()它不适用于字符,但仍然给我一个错误。
use std::io;
fn main() {
let mut binary = String::new();
println!("Enter a decimal: ");
io::stdin().read_line(&mut binary)
.ok()
.expect("Couldn't read line");
println!("{}",to_decimal(binary));
}
fn to_decimal(mut binary_str:String) -> String {
let mut binary_no: u32 = binary_str.trim().parse().expect("invalid input");
if binary_no == 0 {
format!("{}",binary_no)
}
else {
let mut bits = String::new();
let mut binary_vec: Vec<char> = binary_str.chars().collect();
let mut result = 0;
let mut i = 0;
while i <=binary_str.len()-2{
let mut result = result + (binary_vec[i].to_string().parse::<u32>().unwrap() * 2^(i as u32));
i = i +1;
}
format!("{}",result)
}
}
Run Code Online (Sandbox Code Playgroud)
结果:
Compiling sixteen v0.1.0 (C:\Users\Muhammad.3992348\Desktop\rust\hackathon\sixteen)
warning: unused variable: `bits`
--> src\main.rs:19:17
|
19 | let mut bits = String::new();
| ^^^^ help: consider prefixing with an underscore: `_bits`
|
= note: #[warn(unused_variables)] on by default
warning: unused variable: `result`
--> src\main.rs:24:21
|
24 | let mut result = result + (binary_vec[i].to_string().parse::<u32>().unwrap() * 2^(i as u32));
| ^^^^^^ help: consider prefixing with an underscore: `_result`
warning: variable does not need to be mutable
--> src\main.rs:13:15
|
13 | fn to_decimal(mut binary_str:String) -> String {
| ----^^^^^^^^^^
| |
| help: remove this `mut`
|
= note: #[warn(unused_mut)] on by default
warning: variable does not need to be mutable
--> src\main.rs:14:9
|
14 | let mut binary_no: u32 = binary_str.trim().parse().expect("invalid input");
| ----^^^^^^^^^
| |
| help: remove this `mut`
warning: variable does not need to be mutable
--> src\main.rs:19:13
|
19 | let mut bits = String::new();
| ----^^^^
| |
| help: remove this `mut`
warning: variable does not need to be mutable
--> src\main.rs:20:13
|
20 | let mut binary_vec: Vec<char> = binary_str.chars().collect();
| ----^^^^^^^^^^
| |
| help: remove this `mut`
warning: variable does not need to be mutable
--> src\main.rs:21:13
|
21 | let mut result = 0;
| ----^^^^^^
| |
| help: remove this `mut`
warning: variable does not need to be mutable
--> src\main.rs:24:17
|
24 | let mut result = result + (binary_vec[i].to_string().parse::<u32>().unwrap() * 2^(i as u32));
| ----^^^^^^
| |
| help: remove this `mut`
Finished dev [unoptimized + debuginfo] target(s) in 1.04s
Running `target\debug\sixteen.exe`
Enter a decimal:
100
thread 'main' panicked at 'called `Result::unwrap()` on an `Err` value: ParseIntError { kind: InvalidDigit }', src\libcore\result.rs:997:5
note: Run with `RUST_BACKTRACE=1` environment variable to display a backtrace.
error: process didn't exit successfully: `target\debug\sixteen.exe` (exit code: 101)
Run Code Online (Sandbox Code Playgroud)
编辑:我已经输入100,我希望输出4。
编写的代码存在很多问题。好消息是,您可以通过听编译器警告来解决大多数问题!
--> src/main.rs:19:17
|
19 | let mut bits = String::new();
| ^^^^ help: consider prefixing with an underscore: `_bits`
|
= note: #[warn(unused_variables)] on by default
Run Code Online (Sandbox Code Playgroud)
这告诉您bits在此声明之后不使用该变量。如果您打算以后使用它,可以暂时将其注释掉。
warning: unused variable: `result`
--> src/main.rs:24:21
|
24 | let mut result = result + (binary_vec[i].to_string().parse::<u32>().unwrap() * 2^(i as u32));
| ^^^^^^ help: consider prefixing with an underscore: `_result`
|
= note: #[warn(unused_variables)] on by default
Run Code Online (Sandbox Code Playgroud)
这是大个子。这告诉我们该变量result未使用。可是等等!我们在这里使用它!不!实际上,通过使用let mut此处,我们可以创建一个新变量并覆盖旧变量。您想要的是改写旧值。只需更改let mut result = ...为result = ...。
现在,如果再次运行该程序并输入100,将得到输出5。这似乎仍然不正确,但是我们仍有一些警告需要解决,因此让我们回到这一点。
warning: variable does not need to be mutable
--> src/main.rs:13:15
|
13 | fn to_decimal(mut binary_str:String) -> String {
| ----^^^^^^^^^^
| |
| help: remove this `mut`
|
= note: #[warn(unused_mut)] on by default
Run Code Online (Sandbox Code Playgroud)
如果我们不打算对输入字符串进行突变,则不应使其可变。只需删除mut。其他两个警告(第14和20行)也是如此。
好的!现在,我们可以在没有任何警告的情况下运行该程序。但是,我们可以使用一些更高级的棉绒cargo clippy。如果尚未安装clippy,则可以使用进行安装rustup install component clippy。
现在,我们还要注意一些其他警告。
warning: operator precedence can trip the unwary
--> src/main.rs:24:32
|
24 | result = result + (binary_vec[i].to_string().parse::<u32>().unwrap() * 2^(i as u32));
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider parenthesizing your expression: `(binary_vec[i].to_string().parse::<u32>().unwrap() * 2) ^ (i as u32)`
|
= note: #[warn(clippy::precedence)] on by default
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#precedence
Run Code Online (Sandbox Code Playgroud)
哦哦 Clippy告诉我们优先级规则表明该优先级*之前已评估过^。这不是我们对乘法和指数的期望。原来,^是不是该指数运算符。相反,它是按位异或。如果我们想了一些权力,我们可以使用pow的方法,所以替换2 ^ (i as u32)用2.pow(i as u32)。这将导致消息编译器错误error[E0689]: can't call method `pow` on ambiguous numeric type `{integer}`。好。我们可以使用后缀使数字类型明确。将其更改为2_u32.pow(i as u32)。
我们可以仅使用建议来解决Clippy给我们的其他三个警告。之后,Clippy会再发出一个警告,该警告也只是通过建议而得到解决。
在继续之前,让我们通过运行来使我们的代码更漂亮cargo fmt。最后,代码如下所示:
use std::io;
fn main() {
let mut binary = String::new();
println!("Enter a decimal: ");
io::stdin()
.read_line(&mut binary)
.expect("Couldn't read line");
println!("{}", to_decimal(binary));
}
fn to_decimal(binary_str: String) -> String {
let binary_no: u32 = binary_str.trim().parse().expect("invalid input");
if binary_no == 0 {
format!("{}", binary_no)
} else {
//let mut bits = String::new();
let binary_vec: Vec<char> = binary_str.chars().collect();
let mut result = 0;
let mut i = 0;
while i <= binary_str.len() - 2 {
result += binary_vec[i].to_string().parse::<u32>().unwrap() * 2_u32.pow(i as u32);
i += 1;
}
format!("{}", result)
}
}
Run Code Online (Sandbox Code Playgroud)
我们修复了两个错误,仅使用编译器警告和基本工具来清理代码!还不错吧?但是现在如果我们输入100,我们的输出是1。那不对 让我们添加一些调试语句,看看是否可以看到发生了什么。
result += dbg!(binary_vec[i].to_string().parse::<u32>().unwrap()) * dbg!(2_u32.pow(i as u32));
Run Code Online (Sandbox Code Playgroud)
如果我们现在运行它,这就是我们得到的。
Enter a decimal:
100
[src/main.rs:22] binary_vec[i].to_string().parse::<u32>().unwrap() = 1
[src/main.rs:22] 2u32.pow(i as u32) = 1
[src/main.rs:22] binary_vec[i].to_string().parse::<u32>().unwrap() = 0
[src/main.rs:22] 2u32.pow(i as u32) = 2
[src/main.rs:22] binary_vec[i].to_string().parse::<u32>().unwrap() = 0
[src/main.rs:22] 2u32.pow(i as u32) = 4
1
Run Code Online (Sandbox Code Playgroud)
我们可以看到它正确地解析了数字:binary_vec[i].to_string().parse::<u32>().unwrap()is 1,then 0,then 0。2的幂也很好。这里的问题是它倒退了!我们希望左边的数字乘以2的最高幂。让我注意,这是代码中您习惯最少的部分。至少for要为这种事情使用一个循环要好得多。如果您可以管理迭代器,那就更好了。
在任何情况下,我们都可以通过使力量从binary_str.len() - 2下降到下降0而不是从相反的方向扭转顺序。因此,我们可以将代码更改为
while i <= binary_str.len() - 2 {
result += dbg!(binary_vec[i].to_string().parse::<u32>().unwrap()) * dbg!(2_u32.pow((binary_str.len() - 2 - i) as u32));
i += 1;
}
Run Code Online (Sandbox Code Playgroud)
我们得到
Enter a decimal:
100
[src/main.rs:22] binary_vec[i].to_string().parse::<u32>().unwrap() = 1
[src/main.rs:22] 2u32.pow((binary_str.len() - 2 - i) as u32) = 4
[src/main.rs:22] binary_vec[i].to_string().parse::<u32>().unwrap() = 0
[src/main.rs:22] 2u32.pow((binary_str.len() - 2 - i) as u32) = 2
[src/main.rs:22] binary_vec[i].to_string().parse::<u32>().unwrap() = 0
[src/main.rs:22] 2u32.pow((binary_str.len() - 2 - i) as u32) = 1
4
Run Code Online (Sandbox Code Playgroud)
因此,我们可以看到力量从4正确地降低到了1。我们的答案终于是正确的!在更多输入上对其进行测试,并尝试找到一些边缘情况。还有更多的错误可以找到。对代码满意后,取出调试语句。