use std::io;
fn main() {
let is_male : bool;
let mut answer = String::new();
println!("Are you a male? (Input Y or N)");
io::stdin()
.read_line(&mut answer)
.expect("Failed to read line");
if answer == "Y" || answer == "y" {
is_male = true;
}
else if answer == "N" || answer == "n" {
is_male = false;
}
else {
println!("Invalid input!");
}
if is_male {
println!("You are a male.");
}
else {
println!("You are not a male.");
}
}
The error I got is:
error[E0381]: use of possibly-uninitialized variable: is_male
--> src\main.rs:22:9
|
22 | if !is_male {
| ^^^^^^^ use of possibly-uninitialized is_male
Does Rust not allow assigning boolean values this way? Or is there something wrong with the code?
Well, in this case you're not assigning anything to is_male, so it stays uninitialized when checked. This would be undefined behavior, if compiler allowed it to be used this way, since the value can be literally anything - any garbage which was stored in this memory before.
Things like if-else and match are expressions, so there's no reason why you can't use one directly to initialize the is_male variable.
let is_male = match answer.as_str() {
"Y" | "y" => true,
"N" | "n" => false,
other => {
println!("Invalid input! Expected 'Y' or 'N' but got '{}'", other);
return;
}
};
You almost never see uninitialized variables like your let is_male: bool; in idiomatic Rust. Although the compiler will stop you when you try to use a variable that may not have been initialized, the of declaring a variable that gets initialized later on is largely unnecessary.
People might be offended at being asked if they are male or otherwise not want to say. In this modern world gender is not a boolean. You should be prepared for that:
enum Gender {Male, Female, Unspecified}
let gender = match answer {
"Y" | "y" => Gender::Male,
"N" | "n" => Gender::Female,
_ => Gender::Unspecified,
};
if gender = Gender::male {
...
}
...
If you mean gender to be boolean but allow the user the option to not specify then perhaps your program could express that by using the Option type:
let is_male = match answer {
"Y" | "y" => Some(true),
"N" | "n" => Some(false),
_ => None,
};
if is_male == Some(true) {
println!{"You are male."};
}
Or perhaps you deem that not specifying ones gender is an error, in which case expressing that in your program with the Error type might be suitable:
let is_male = match answer {
"Y" | "y" => Ok(true),
"N" | "n" => Ok(false),
_ => Err("Gender unspecified"),
};
if is_male == Ok(true) {
println!{"You are male."};
}
enum Gender {Male, Female}
let answer = "Y";
let gender = match answer {
"Y" | "y" => Some(Gender::Male),
"N" | "n" => Some(Gender::Female),
_ => None,
};
if let gender = Some(Gender::Male) {
println!{"You are male."};
}
I like this better because:
Using the enum clearly states what it is talking about. Whereas 'true', 'false' do not.
enum Gender {Male, Female, Others, Unspecified};
let mut answer = String::new();
println!("What is your gender? (Input 'M' for male, 'F' for female, 'O' for others and 'U' for unspecified.)");
io::stdin()
.read_line(&mut answer)
.expect("Failed to read line");
println!("{}", answer);
let gender = match answer.as_str() {
"M" | "m" => Some(Gender::Male),
"F" | "f" => Some(Gender::Female),
"O" | "o" => Some(Gender::Others),
"U" | "u" => Some(Gender::Unspecified),
others => {
println!("Invalid input! Expected 'M', 'F', 'O' or 'U' but got '{}'", others);
return;
}
};
if let gender = Some(Gender::Male) {
println!{"You are male."};
}
When I allow user input, the match statement always prints Invalid input! Expected 'M', 'F', 'O' or 'U' but got {whatever}. But when I use the code you gave me, which does not allow user input, it worked fine. Why is this the case?