I have a menu with option.
Option 1: BMI caculator (option 1/case 1)
When entering the details in BMI calculator such as Height in Meters I am trying to get it to loop back and print an error message and ask again if the height that the user entered isn't a int (meters) for example if the user inputs a string say "M" it will not work and loops back to the initial question prompting for input IE: 2.1. I'm trying to use IF ELSE inside the switch/case. You can see in height section I can use goto case 1
to loop it but does not work for weight ( because that will go back to the beginning of case 1 and user would need to enter height again), Whatever the outcome of weight I need to keep the result of Height prior to weight so as to perform the final calculation BMI = . Sorry if this isn't clear, I'm really new and really stuck.
switch (optionsIn)
case 1:
{
Console.Clear();
Console.WriteLine("What is your height in meters");
double heightMax = 0.00;
string heightMeters = Console.ReadLine();
double.TryParse(heightMeters, out double heightM);
if (heightMax < heightM)
{
Console.Clear(); // nothing needs to run here , just clear to look better and move to collection of weight.
}
else
{
Console.Clear();
Console.WriteLine("Incorrect option try again");
Console.WriteLine("press enter to try again");
Console.ReadKey();
goto case 1; // better way to do it rather than goto case 1?
}
Console.WriteLine("Enter weight in Kgs"); // need to start here if incorrect input from user
double kgs = 00.00;
string weight = Console.ReadLine();
double.TryParse(weight, out double weightKgs);
if (kgs < weightKgs)
{
Console.Clear(); // nothing needs to run here , just clear console to look neat and move to calculating and printing BMI
}
else
{
Console.WriteLine("Incorrect option try again"); // cannot get to loop back to Enter weight
Console.WriteLine("press enter to return");
Console.ReadKey();
break;
}
double bmi = weightKgs / (heightM * heightM);
Console.WriteLine($"BmI is " bmi);
Console.WriteLine("press any key to exit");
Console.ReadKey();
break;
}
CodePudding user response:
I suggest method extraction:
public static double ReadDouble(string title, Func<double, bool> validation) {
// Keep Asking User until correct value is provided
while (true) {
// Show title if we have it
if (!string.IsNullOrWhiteSpace(title))
Console.WriteLine(title);
if (!double.TryParse(Console.ReadLine(), out double result))
// Not a double value at all; say, "bla-bla-bla"
Console.WriteLine("Syntax error. Please, try again.");
else if (validation != null && !validation(result))
// Not a valid double value, say, 123456.89 kg weight
Console.WriteLine("Not a valid value. Please, try again.");
else
return result;
}
}
then you can easily use it within switch \ case
:
double heightM = ReadDouble("What is your height in meters", m => m > 0.3 && m < 3.0);
double weightKgs = ReadDouble("Enter weight in Kgs", m => m > 0.7 && m < 700.0);
double bmi = weightKgs / (heightM * heightM);
Console.WriteLine($"BmI is {bmi:F1}");
CodePudding user response:
Instead of using goto
- which is considered bad practice and is not all that much readable, try using a while
or do/while
loop instead.
Something like:
string input;
double heightMax = 0.0;
do {
input = Console.ReadLine();
double.TryParse(input, out double heightM);
Console.Clear();
} while (heightMax >= heightM);
Also, consider using functions for loading the data. Maybe you can think of some way of generalizing so that you can have only one function that you can reuse for all the stuff you need to load.