I have an issue with the following C++ program. It calculates and prints out the blood alcohol concentration using the Widmark formula based on information the user enters. There is some input error checking, for example if a random character is entered after being asked for which beverage they drank, or if any number higher than 400 is entered after being asked for weight. Then an error message appears (which is intentional) and the user is asked for input again.
However, they are some issues with the input error checking, for example if x>1 characters are entered after being asked for the gender, the error message appears x times (it should appear only once). If any non-integer characters are entered after being asked for weight, the error message appears infinite times, resulting in an endless loop (same issue with litres drunk after entering non-float values).
Is there some way to limit the inputs so that error messages only appear once after any invalid input?
#include<iostream> // for std::cin and std::cout
#include<iomanip> // for std::fixed and std::setprecision
float BAC (char gender, int weight, char drink, float litres) // function to calculate blood alcohol concentration
{
// local variables
float bac, rate, vol; // blood alcohol concentration, widmark rate, volume percentage
// determine widmark rate
if (gender == 'm' || gender == 'M') // not case-sensitive
{
rate = 0.68;
}
if (gender == 'f' || gender == 'F')
{
rate = 0.55;
}
if (gender == 'c' || gender == 'C')
{
rate = 0.75;
}
// determine volume percentage
if (drink == 'b' || drink == 'B')
{
vol = 5;
}
if (drink == 'w' || drink == 'W')
{
vol = 12;
}
if (drink == 's' || drink == 'S')
{
vol = 38;
}
// calculating blood alcohol concentration
bac = ((litres * 1000) * (vol / 100) * 0.8) / (weight * rate);
// ((litres * 1000) * (vol / 100) * 0.8) --> formula for alcohol mass
// (litres * 1000) --> conversion to millilitres
return bac;
}
int main () // main function for user input/output
{
// variables to be entered
char gender, drink;
int weight;
float litres;
// getting user input
std::cout << "Are you male (m), female (f), or a small child (c)?" << std::endl;
do
{
std::cin >> gender;
if (gender != 'm' && gender != 'M' && gender != 'f' && gender != 'F' && gender != 'c' && gender != 'C') // check input
{
std::cout << "\nInvalid input: Please enter 'm', 'f' or 'c' (capital letters are allowed)." << std::endl;
}
}
while (gender != 'm' && gender != 'M' && gender != 'f' && gender != 'F' && gender != 'c' && gender != 'C');
// repeat as long as valid input is entered
std::cout << "\nWhat is your weight (in kg)?" << std::endl;
do
{
std::cin >> weight;
if (weight < 10 || weight > 400)
{
std::cout << "\nInvalid input: Please enter a number bigger than or equal to 10 and smaller than or equal to 400." << std::endl;
}
}
while (weight < 10 || weight > 400);
std::cout << "\nWhich beverage did you drink? beer: (b), wine: (w), schnapps: (s)" << std::endl;
do
{
std::cin >> drink;
if (drink != 'b' && drink != 'B' && drink != 'w' && drink != 'W' && drink != 's' && drink != 'S')
{
std::cout << "\nInvalid input: Please enter 'b', 'w' or 's' (capital letters are allowed)." << std::endl;
}
}
while (drink != 'b' && drink != 'B' && drink != 'w' && drink != 'W' && drink != 's' && drink != 'S');
std::cout << "\nHow many litres did you drink?" << std::endl;
do
{
std::cin >> litres;
if (litres < 0 || litres > 10)
{
std::cout << "\nInvalid input: Please enter a number bigger than or equal to 0 and smaller than or equal to 10." << std::endl;
}
}
while (litres < 0 || litres > 10);
// print the result
std::cout << std::endl << std::endl << "Your blood alcohol concentration is: "
<< std::fixed << std::setprecision(2) // show only 2 decimal places after the dot
<< BAC (gender, weight, drink, litres) // function call
<< " thousandths." << std::endl;
return 0;
}