Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

while loop not prompting for user input (c++)

My loop works good until i enter the last value being the input for gender, when "true" is inputted, the loop ignores cin's for the remaining loops and just prints the text in cout until loop is over, any ideas how to make the loop ask for input on every loop or where did i make a mistake? ps: it's a schoolwork, so i can't change the struct which is given. Thanks for any suggestions. code snippet:

int main()
{
    struct Patient
    {
        double height;
        double weight;
        int age;
        bool isMale;
    };
    Patient ListOfPatients[4];
    int iii = 0;

    while (iii < 4)
    {
        cout << "enter the height (eg. 1.80 metres) of patient number  " << iii + 1 << " :" << endl;
        cin >> ListOfPatients[iii].height;
        cout << "enter the weight (eg. 80kg) of patient number " << iii + 1 << " :" << endl;
        cin >> ListOfPatients[iii].weight;
        cout << "enter the age of patient number " << iii + 1 << " :" << endl;
        cin >> ListOfPatients[iii].age;
        cout << "is the patient a male? (true = male or false = female) " << endl;
        cin >> ListOfPatients[iii].isMale;

        iii++;
    }

    return 0;
}
like image 784
Average JS enjoyer Avatar asked Jan 02 '23 04:01

Average JS enjoyer


2 Answers

The problem is when you read isMale. A bool is really a number, 0 for false, 1 for true. You can't read a string into it.

What happens is that you end up with a bunch of characters in the stream that can't be read by any of the >> operations, so they all just fail in a row. Try passing in 1 or 0 on the command line, and it all works fine.

If you want the user to be able to pass in a string and then treat this as a bool, you can use a utility provided exactly for this, or do it manually just to help you understand.

To use the standard utility, it is called std::boolalpha and comes in the <iomanip> header:

std::cin >> std::boolalpha >> ListOfPatients[i].isMale;

To do it manually, read this into a std::string object and do some comparison yourself, like this:

std::string tmpIsMale;
std::cin >> tmpIsMale;
ListOfPatients[i].isMale = (tmpIsMale == "true");

It is also a good idea to check the state of the stream after you try to read from it, for precisely this reason. You can put the stream directly into an if for this:

std::cin >> someVariable;
if (!cin) { // cin is not in a good state
    std::cerr << "Failed to read someVariable, please try again with a proper value!\n";
    return 1;
}

A few asides and bad practices you may want to avoid:

  1. using namespace std; is widely considered to be bad practice.
  2. std::endl is a bit more contentious, but the way you are using it suggests you don't understand it.
  3. Gender isn't a boolean option. I know it's not a strictly technical matter, and if the struct is provided by your teacher you are a bit stuck, but come on, it's 2019! Learning to write good programs doesn't just mean the technicalities of the language, but learning how to write programs that are good for the users too, so it's a good idea to get into good habits early.
like image 88
BoBTFish Avatar answered Jan 06 '23 10:01

BoBTFish


You can use the stream manipulator boolalpha to not do any of the comparing yourself:

cin >> std::boolalpha >> cListOfPatients[iii].isMale >> std::noboolalpha;
like image 28
Hatted Rooster Avatar answered Jan 06 '23 10:01

Hatted Rooster