Rust程序为什么无法从if语句中返回值?

4

我正在制作一个简单的控制台程序,用于在摄氏度和华氏度之间进行转换。该程序需要多次获取用户输入,一次是转换类型,另一次是要转换的值。当我运行该程序时,它可以编译和运行而不出现任何错误,但实际上它并没有返回任何值。

以下是程序代码:

use std::io;

// C to F: F = C*(9/5) + 32
// F to C: C = (F-32)*(5/9)

/**********Converts between Fahrenheit and Celsius*********/

fn main() -> () {
    println!("Do you want to convert to Celsius or Fahrenheit? Input C or F");
    let mut convert_type = String::new();

    io::stdin()
        .read_line(&mut convert_type)
        .expect("Failed to conversion type.");

    let t = String::from(convert_type);

    println!("You want to convert to: {}", t);
    println!("What temperature would you like to convert?");
    let mut temp = String::new();

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

    let temp: i32 = match temp.trim().parse() {
        Ok(temp) => temp,
        Err(_e) => -1,
    };

    if &t == "C" {
        println!("{}", ctof(temp));
    } else if &t == "F" {
        println!("{}", ftoc(temp));
    }
}

// Celsius to Fahrenheit
fn ctof(c: i32) -> i32 {
    (c * (9 / 5)) + 32
}

//Fahrenheit to Celsius
fn ftoc(f: i32) -> i32 {
    (f - 32) * (5 / 9)
}

这是控制台的一部分代码,你可以看到它没有输出转换结果:
cargo run --verbose
   Compiling ftoc v0.1.0 (/Users/roberthayek/rustprojects/ftoc)
     Running `rustc --crate-name ftoc src/main.rs --color always --crate-type bin --emit=dep-info,link -C debuginfo=2 -C metadata=8f02d379c2e5c97d -C extra-filename=-8f02d379c2e5c97d --out-dir /Users/roberthayek/rustprojects/ftoc/target/debug/deps -C incremental=/Users/roberthayek/rustprojects/ftoc/target/debug/incremental -L dependency=/Users/roberthayek/rustprojects/ftoc/target/debug/deps`
    Finished dev [unoptimized + debuginfo] target(s) in 1.16s
     Running `target/debug/ftoc`
Do you want to convert to Celsius or Fahrenheit? Input C or F
C
You want to convert to: C

What temperature would you like to convert?
0

2
你尝试过打印输出你的值来查看它实际上是什么吗?像这样:printl!("{?}", t); - behnam
2
请在以后提供一个 MCVE。您不需要发布完整的程序,而是只需发布有趣的代码片段以及所有必需的函数和类型。有关 Rust 特定 MCVE 的更多信息,请参见 [tag:rust]-tag,例如使用 playground。 - hellow
1个回答

12

您应该养成处理所有情况的习惯,即使是您没有预料到的情况。如果您这样做了,您就会发现问题所在。因此,不要像这样:

if &t == "C" {
    println!("{}", ctof(temp));
} else if &t == "F" {
    println!("{}", ftoc(temp));
}

你可以这样编写代码(你也可以使用最后没有 if 的 else 分支,但是match 更加吸引人):
match t.as_str() {
    "C" => println!("{}", ctof(temp)),
    "F" => println!("{}", ftoc(temp)),
    _ => println!("please enter C or F"),
}

当你运行程序时,你会发现t似乎既不等于"C"也不等于"F"。这将带领你通过调试打印来检查t的值。

match t.as_str() {
    "C" => println!("{}", ctof(temp)),
    "F" => println!("{}", ftoc(temp)),
    _ => println!("t = {:?}", t),
}

此时,您将看到t的值不是"C",而是"C\n""C\r\n"。然后您会意识到read_line没有为您从字符串中剥离换行符。


2
我记得 unreachable!() 现在可以接受参数,所以你可能只需要使用 unreachable!("t = {:?}", t") - Matthieu M.
是的,它确实可以。请查看unreachable!()的声明。 - hellow
2
有趣。虽然我有点不经思考地编写了这段代码,但我意识到在用户输入t的情况下,unreachable()是完全不合适的。 - Benjamin Lindley
1
的确,到达一个无法到达的代码是一个错误(在这种情况下是安全的,但仍然是一个错误)。 - Stargateur

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