4

I am making a simple console program that converts between Celsius and Fahrenheit. The program takes user input multiple times, once for the type of conversion and once for the value to convert. When I run the program it compiles and runs without error, however, it does not actually return any value.

Here is the program:

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)
}

Here is a snippet of the console, as you can see it does not output the conversion:

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
Shepmaster
  • 388,571
  • 95
  • 1,107
  • 1,366
roberthayek
  • 167
  • 2
  • 10
  • 2
    Have you tried printing your value to see what it actually is? Like, `printl!("{?}", t);` ? – behnam Nov 09 '18 at 03:10
  • 2
    Please provide a [MCVE](https://stackoverflow.com/help/mcve) in the future. You don't need to post your full program, but instead only the snippet that is interesting together will all the required functions and types. See the [tag:rust]-tag for more information about rust specific mcves, e.g. using the playground – hellow Nov 09 '18 at 07:22

1 Answers1

12

You should make a habit of handling all cases, even ones you don't expect. If you had done so, you would have found the problem. So instead of this:

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

You could write this (you could also use a final else branch with no if, but match is much more appealing):

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

And when you ran your program, you would see that t seemed to be equal to neither "C" nor "F". That would hopefully lead you to check the value of t, by doing a debug print.

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

At which point you would see that the value of t is not "C", but "C\n" or "C\r\n". And you would then realize that read_line was not stripping the newline from your string for you.

Benjamin Lindley
  • 101,917
  • 9
  • 204
  • 274
  • 2
    I seem to remember that `unreachable!()` now accepts parameters, so you may be able to just use `unreachable!("t = {:?}", t"),`. – Matthieu M. Nov 09 '18 at 07:19
  • Yes it does. Look at the declaration at [`unreachable!()`](https://doc.rust-lang.org/std/macro.unreachable.html) – hellow Nov 09 '18 at 07:20
  • 2
    Interesting. Though I kind of wrote this code unthinkingly and just realized that `unreachable()` is entirely inappropriate in this situation where `t` comes from user input. – Benjamin Lindley Nov 09 '18 at 07:38
  • 1
    Indeed reach an unreachable code is a bug (safe in this case but still a bug). – Stargateur Nov 09 '18 at 08:26