为什么无法解析字符串 锈

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。

SCa*_*lla 9

编写的代码存在很多问题。好消息是,您可以通过听编译器警告来解决大多数问题!

  --> 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。我们的答案终于是正确的!在更多输入上对其进行测试,并尝试找到一些边缘情况。还有更多的错误可以找到。对代码满意后,取出调试语句。