带有阴影和字符串的'let'的范围 - >&str转换

问题描述 投票:0回答:3

使用以下代码,我尝试返回用户输入的温度和温度,但是徒劳无功。然后,我试图返回f32,但仍然很难......

Q1。我在底部得到错误的原因是因为'let temp = String::new();'的范围仍然存在,即使我在后面通过循环中的'let temp = temp.trim().parse::<f32>();''影响'它?

Q2。如何重写代码以便返回&str?

fn gettemp() -> f32 {
    let temp = String::new();

    loop {
        println!("What is your temperature?");

        io::stdin().read_line(&mut temp).expect("Failed to read the line");

        let temp = temp.trim().parse::<f32>();

        if !temp.is_ok() {
            println!("Not a number!");
        } else {
            break;
        }
    }

    temp
}

错误:

error[E0308]: mismatched types
  --> src/main.rs:70:5
   |
49 | fn gettemp() -> f32 {
   |                 --- expected `f32` because of return type
...
70 |     temp
   |     ^^^^ expected f32, found struct `std::string::String`
   |
   = note: expected type `f32`
              found type `std::string::String`
rust
3个回答
1
投票

A1 - 不,这不是阴影的作用。让我们看看你的代码与评论。

fn gettemp() -> f32 {
    let temp = String::new(); // Outer

    loop {
        // There's no inner temp at this point, even in the second
        // loop pass, etc.

        println!("What is your temperature?");

        // Here temp refers to the outer one (outside of the loop)
        io::stdin().read_line(&mut temp).expect("Failed to read the line");

        // Shadowed temp = let's call it inner temp
        let temp = temp.trim().parse::<f32>();
        //    ^      ^
        //    |      |- Outer temp
        //    |- New inner temp

        // temp refers to inner temp
        if !temp.is_ok() {
            println!("Not a number!");
        } else {
            // Inner temp goes out of scope
            break;
        }

        // Inner temp goes out of scope
    }

    // Here temp refers to outer one (String)
    temp
}

A2 - 你不能返回&str。 @ E_net4发布了答案的链接原因。但是,您可以返回String。你可以做类似的事情,如果你想要有一个经过验证的String

fn gettemp() -> String {
    loop {
        println!("What is your temperature?");

        let mut temp = String::new();
        io::stdin()
            .read_line(&mut temp)
            .expect("Failed to read the line");

        let trimmed = temp.trim();

        match trimmed.parse::<f32>() {
            Ok(_) => return trimmed.to_string(),
            Err(_) => println!("Not a number!"),
        };
    }
}

我在你的代码中看到了另外几个问题。

let temp = String::new();

应该是let mut temp,因为你想稍后借用可变参考(在&mut temp电话中read_line)。

另一个问题是qazxsw poi&qazxsw poi。 qazxsw poi附加到loop。运行此代码......

read_line

...例如输入read_line。你会看到以下输出......

String

......这不是你想要的。我用这种方式重写了let mut temp = "foo".to_string(); io::stdin().read_line(&mut temp).unwrap(); println!("->{}<-", temp);

10

恕我直言显示->foo10 <- 更清洁和可读(相比于建议突破循环的值)。


A3 - 为什么我们不需要在gettemp()明确陈述fn gettemp() -> f32 { loop { println!("What is your temperature?"); let mut temp = String::new(); io::stdin() .read_line(&mut temp) .expect("Failed to read the line"); match temp.trim().parse() { Ok(temp) => return temp, Err(_) => println!("Not a number!"), }; } }

它是由编译器推断的。

return temp

1
投票

关于问题1,你可以用一个值<f32>离开循环:

temp.trim().parse()

这样,整个循环的值就是你与fn gettemp() -> f32 { // 1. f32 is return type loop { println!("What is your temperature?"); let mut temp = String::new(); io::stdin() .read_line(&mut temp) .expect("Failed to read the line"); match temp.trim().parse() { // 4. parse signature is pub fn parse<F>(&self) -> Result<F, ...> // compiler knows it must be Result<f32, ...> // Result<f32, ...> = Result<F, ...> => F = f32 // F was inferred and there's no need to explicitly state it Ok(temp) => return temp, // | | // | 2. return type is f32, temp must be f32 // | // | 3. temp must be f32, the parse result must be Result<f32, ...> Err(_) => println!("Not a number!"), }; } } 一起传递的东西。

关于问题2,我不确定你是否真的想这样做,因为break是借来的类型。我想你想在这种拥有数据的情况下返回一个fn gettemp() -> f32 { let mut temp = String::new(); loop { println!("What is your temperature?"); io::stdin().read_line(&mut temp).expect("Failed to read the line"); let temp = temp.trim().parse::<f32>(); if !temp.is_ok() { println!("Not a number!"); } else { break temp.unwrap() // yield value when breaking out of loop } } }


0
投票

在您的程序中,break创建了一个新的范围。第二个&str的范围从它定义的地方开始,并在String结束时结束。请参阅以下示例:

loop { ... }

这打印2,1。

如果要返回字符串,请使用(代码根据以下注释修复):

temp

loop是借来的参考。您不能将借用的引用返回到本地变量,该变量将在函数返回时释放。

© www.soinside.com 2019 - 2024. All rights reserved.