Home > front end >  why can't I use multiple conditions with logical operators in this case? C
why can't I use multiple conditions with logical operators in this case? C

Time:06-11

#include <iostream>

int main(int, char **)
{
   using namespace std;

   int days;

   cout<<"How many days did you work this month? ";
   cin>>days;
   while(!(cin>>days) || (days<1) || (days>31)){
      if(!(cin>>days)){
         cout<<"Number of days should be... well, a number. Please re-enter: ";
         cin.clear();
         cin.ignore(100,'\n');
      }
      else if(days<1 || days>31){
         cout<<"Number of days should be between 1 and 31. Please re-enter:";
         cin>>days;
      }
   }
   return 0;
}

This is supposed to validate user input:

  • The first condition is there to avoid an infinite loop when you ask for an int and the user enters a char/string. This part works just fine, it keeps asking for input until I enter a number, and then proceeds to execute the next part of the program (not shown here).

  • the number of days should be between 1 and 30. If I enter a number - any number, inside or outside the range - the program will not do anything AT ALL. Won't even show the error message.

I can make it work if I use two separate loops, one to validate !(cin>>days) and another for (days<1) || (days>31). I don't know what it is that I'm doing wrong here.

CodePudding user response:

your problem is that you are reading cin input 3 times before you do anything

   int days;

   cout<<"How many days did you work this month? ";
   cin>>days;   <<<<<==== 1
   while(!(cin>>days) <<<<<<<=====2|| (days<1) || (days>31)){
      if(!(cin>>days)){  <<<<<<=== 3
         cout<<"Number of days should be... well, a number. Please re-enter: ";
         cin.clear();
         cin.ignore(100,'\n');

      }
      else if(days<1 || days>31){
         cout<<"Number of days should be between 1 and 31. Please re-enter:";
         cin>>days;
      }
   }

if you want to test if there was an input error just do !cin

ie

   int days;

   cout<<"How many days did you work this month? ";
   cin>>days;
   while(!(cin) || (days<1) || (days>31)){
      if(!(cin)){
         cout<<"Number of days should be... well, a number. Please re-enter: ";
         cin.clear();
         cin.ignore(100,'\n');
         cin >> days; 
      }
      else if(days<1 || days>31){
         cout<<"Number of days should be between 1 and 31. Please re-enter:";
         cin>>days;
      }
   }

CodePudding user response:

You are using three sequential calls of cin>>days

cin>>days;
while(!(cin>>days) || (days<1) || (days>31)){
   if(!(cin>>days)){
//...

or

while(!(cin>>days) || (days<1) || (days>31)){
   if(!(cin>>days)){
       //...
   }
   else if(days<1 || days>31){
      //...
      cin>>days;
   }
}

That just does not make any sense.

The code can look the following way, for example:

int days;
bool failure;

cout<<"How many days did you work this month? ";

while( ( failure = !(cin>>days) ) || (days<1) || (days>31)){
   if( failure ){
      cout<<"Number of days should be... well, a number. Please re-enter: ";
      cin.clear();
      cin.ignore(100,'\n');
   }
   else if(days<1 || days>31){
      cout<<"Number of days should be between 1 and 31. Please re-enter:";
   }
}

CodePudding user response:

You are calling cin >> days too many times.

You are prompting the user for input and then reading in days before entering the loop, but you are completely ignoring the user's initial input.

Then, once you are inside the loop, you read in days again before doing anything else. But you didn't prompt the user for another input yet. Eventually, hopefully they will figure out that your program is waiting for another input, and will type something in.

But if that input fails to read a number, or the number is out of range, then you are prompting the user and reading in days yet again before jumping to the next loop iteration, which then starts the bad pattern all over again, waiting for an extra input without prompting the user to enter any input.

You should be reading in days only 1 time per loop iteration.

Other people have suggested how to pigeon-hole the input validation into your existing loop structure. I would instead suggest a slightly different loop structure that should make the code a little easier to understand and follow:

#include <iostream>
#include <limits>

int main()
{
   using namespace std;

   int days;

   cout << "How many days did you work this month? ";
   do {
      if (!(cin >> days)) {
         cout << "Number of days should be... well, a number. Please re-enter: ";
         cin.clear();
         cin.ignore(numeric_limits<streamsize>::max(), '\n');
      }
      else if ((days < 1) || (days > 31)) {
         cout << "Number of days should be between 1 and 31. Please re-enter:";
      }
      else {
         break;
      }
   }
   while (true);

   cout << "Thank you for working " << days << "day(s)!";
   return 0;
}
  • Related