Two infinite loops that shouldn't be

Hello!

I am working on a couple of class problems. The first is to create a program to convert from binary to decimal. For some reason, my while loop creates an infinite loop, and I am not sure why. Any hints would be much appreciated!

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
#include <iostream>
#include <cmath>
using namespace std;

int main ()
{
  int b, num1, num2;
  float a, n;
  n = 0, a = 0;
  cout << "Please enter an unsigned integer in binary." << endl;
  cin >> num1;
  b = num1;
  do
  {
    num2 = num1 % 10;
    while (num2 == 1 || num2 == 0 || num1 != 0) //This creates an infinite loop?
    {
      a = a + pow(a , n);
      num1 = num1 / 10;
      n = n + 1;
    }
    if (num2 != 0 || num2 != 1)
    {
      cout << "Invalid binary number. Terminating." << endl;
      num1 = 0;
    }
  }
  while (num1 != 0);
  cout << "Your binary number " << b << " is " << a << " in decimal." << endl;
 
  return 0;
}


As I said, my while loop goes infinite. My exit out of the loop, num1, reaches 0 yet the loop continues.

Problem number 2 is a little more complicated I think. We were asked to build a menu and have the menu repeat until the user quits the program. Even if you put in a letter value. I put in a letter value, and the entire do-while loop goes infinite! I will highlight what I think are the relevent parts with comments. My problems are on lines 26 and 99 I believe. The behavior of this program is the it loops my entire do-while loop if a user inputs a number, without stopping for my "cin" expressions. Again, any hints would be much appreciated!

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
#include <iostream>
using namespace std;

int main()

{

  float num1, num2, num3; //defines my two number variables, 
                             //and my answer.
  float ans; //defines the user's answer as a var.
  int num0; //defines my menu choice
 
  do //This repeats the menu until the user chooses the quit option.
  {
  //Menu, with addition subtraction multiplication and division problems   //choices.
  cout << "     Menu" << endl;
  cout << "1. Addition Problem" << endl;
  cout << "2. Subtraction Problem" << endl;
  cout << "3. Multiplication Problem" << endl;
  cout << "4. Division Problem" << endl;
  cout << "5. Quit" << endl;
  cout << "Please enter the number of the type of math problem you would like to practice." << endl;
  cin >> num0;

  while (num0 != 1 && num0 != 2 && num0 != 3 && num0 != 4 && num0 != 5 && num0 != 6)  //This should make anything not a 1-6 become a 6.
  {
  num0 = 6;
  }
   
  num1 = 1 + rand() % 500; //Ranomly generates num1 1-500
  num2 = 1 + rand() % 500; //Randomly generates num2 1-500

  if ( num0 == 1) //Addition problem begins here
{
  cout << "Please enter your answer below" << endl;
  cout << num1 << endl;
  cout << "+" << num2 << endl;
  cout << "_____" <<  endl;
  cin >> ans;
  num3 = num1 + num2;
     if (num3 == ans) //If statement that if answer is correct, user will see congratulatory message,
                     //otherwise will see the correct answer.
        cout << "Congratulations, " << num3 << " is the correct answer!" << endl;
     else
        cout << "Sorry, the correct answer is " << num3 << "." << endl; 

}
  else if ( num0 == 2) //Subtraction problem begins here
{
  cout << "Please enter your answer below" << endl;
  cout << num1 << endl;
  cout << "-" << num2 << endl;
  cout << "_____" << endl;
  cin >> ans;
  num3 = num1 - num2;
      if (num3 == ans)  //If statement that if answer is correct, user will see congratulatory message,
                     //otherwise will see the correct answer.
          cout << "Congratulations, " << num3 << " is the correct answer!" << endl;
      else
          cout << "Sorry, the correct answer is " << num3 << "." << endl;
}
  else if ( num0 == 3) //Multiplication problem begins here
{
  num1 = 1 + rand() % 10; //Randomly generates a number 1-10, easier for multiplication
  num2 = 1 + rand() % 10; //Randomly generates a number 1-10
  cout << "Please enter your answer below" << endl;
  cout << num1 << endl;
  cout << "*" << num2 << endl;
  cout << "_____" << endl;
  cin >> ans;
  num3 = num1 * num2;
      if (num3 == ans)  //If statement that is answer is correct, user will see congratulatory message,
                     //otherwise will see the correct answer.
            cout << "Congratulations, " << num3 << " is the correct answer!" << endl;
      else
            cout << "Sorry, the correct answer is " << num3 << "." << endl;
}
  else if ( num0 == 4) //Division problem begins here
{
   num1 = 1 + rand() % 10; //Randomly generates a number 1-10, easier for division
   num2 = 1 + rand() % 10; //Randomly generates a number 1-10
   cout << "Please enter your answer below" << endl;
   cout << num1 << endl;
   cout << "/" << num2 << endl;
   cout << "_____" << endl;
   cin >> ans;
   num3 = num1 / num2;
       if (num3 == ans)  //If statement that if answer is correct, user will see congratulatory message,
                     //otherwise will see the correct answer.
                cout << "Congratulation, " << num3 << " is the correct answer!" << endl;
       else
                cout << "Sorry, the correct answer is " << num3 << "." << endl;
}
   else if ( num0 == 5) //Program quit
{
}
   else if (num0 != 5 || num0 != 1 || num0 != 2 || num0 != 3 || num0 !=4) //Tells user to enter a valid menu choice
//This should let the user enter in a new choice, but it doesn't!
{
   cout << "Please enter a valid menu number to continue." << endl;
   cin >> num0;
}
}
  while (num0 != 5); //This closes the do loop
  return 0;
}


Thanks for the help.

while (num2 == 1 || num2 == 0 || num1 != 0)

but nowhere in the body of the loop do you ever change num2's value, so if num2 is 0 or 1
coming into the loop, it will never terminate.

second problem.

int num0;

cin >> num0;

If what the user types is not an integer, the input is never consumed, meaning that cin >> num0 sees the
same input over and over.

You have to clear the input stream to fix the error condition. There are plenty of examples around here
that show you how. It involves calling cin.ignore().

Thank you for the replies!

For the first one, I am sorry I didn't explain better. I didn't want my num2 == 1 || num2 == 0 to be my only exit from the loop. The reason that is there is to catch for a number entered that is not binary (102 for example). However, I did manage to fix this problem: while ((num2 == 1 || num2 == 0) && num1 != 0) by adding a new set of parenthesis. And yes I do need to update my num2 in my loop, thank you for that pointer. Now my output is just wrong but I can run tests now that I can see output, so that one is basically solved, thank you!

I am running tests with the second one with cin.ignore

Thanks for your help!

And one last question, is there any way to do a "PRess any key to continue" in C++ without hitting the enter?

Update: I tried adding in cin.ignore() to my code under the menu after my cin >> num0, instead of just the cin that is there. If I understand this correctly, that should solve the problem of the infinite looping of the program because the program is looping itself because lets say "a" is entered, then it will be stored as the variable num0 and the program won't be able to stop it. But now it just gets stuck in my while loop.
1
2
3
4
5
6
while (num0 != 1 && num0 != 2 && num0 != 3 && num0 != 4 && num0 != 5 && num0 != 6)  
  {
  cout << "Please enter a valid selection" << endl;
  cin >> num0;
  cin.ignore;
  }


And here the cin.ignore is not working like I think it should?
Last edited on
First, cin.ignore() is a function, so in order to call it you use cin.ignore(). Also, you aren't fixing the problem at all. I would go check this article:

http://www.cplusplus.com/forum/articles/6046/
Any ideas on "Press any key to enter" to of deal with C++? In other words, no need to push enter?

As to my first problem, I solved it with the help of the internet and a friend like this:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
do //This repeats the menu until the user chooses the quit option.
  {
  //Menu, with addition subtraction multiplication and division problems choices.
  cout << "     Menu" << endl;
  cout << "1. Addition Problem" << endl;
  cout << "2. Subtraction Problem" << endl;
  cout << "3. Multiplication Problem" << endl;
  cout << "4. Division Problem" << endl;
  cout << "5. Quit" << endl;
  cout << "Please enter the number of the type of math problem you would like to practice." << endl;
  cin >> choice;   

  while (!isdigit(choice[0])) // if choice is a non numerical answer, repeats menu
  {
  cout << "Invalid choice selected.  " << endl << endl;;
  cout << "     Menu" << endl;
  cout << "1. Addition Problem" << endl;
  cout << "2. Subtraction Problem" << endl;
  cout << "3. Multiplication Problem" << endl;
  cout << "4. Division Problem" << endl;
  cout << "5. Quit" << endl;
  cout << "Please enter the number of the type of math problem you would like to practice." << endl; 
  cin >> choice;
  }

  num0 = atoi(choice); // converts characters to integers
  num1 = 1 + rand() % 500; //Ranomly generates num1 1-500
  num2 = 1 + rand() % 500; //Randomly generates num2 1-500

  switch (num0)
  {
  case 1:
  cout << "Please enter your answer below" << endl;
  cout << num1 << endl;
  cout << "+" << num2 << endl;
  cout << "_____" <<  endl;
  cin >> choice;
  while (!isdigit(choice[0 && 1 && 2 && 3 && 4 && 5])) // if ans is a non numerical answer, asks for new ans
  {
   cout << "That is not a valid numerical answer" << endl;
   cin >> choice;
  }
  ans = atoi(choice); //convert character to number
  num3 = num1 + num2;
     if (num3 == ans) //If statement that if answer is correct, user will see congratulatory message,
                     //otherwise will see the correct answer.
        cout << "Congratulations, " << num3 << " is the correct answer!" << endl;
     else
        cout << "Sorry, the correct answer is " << num3 << "." << endl;
  break;

etc. (lines 13 and 26 for the menu choice, 38 and 43 for ans).

I tried going with the cin.ignore(); function, even trying cin.ignore(100, '\n') before and after inputs, but once the loop started it would not stop for anything. And I tried cin.ignore(100, 1 && 2 && 3 && 4 && 5); but it would also discard those statements, then once the user hit a 4 and enter, then they would be free to type a letter and enter the infinite loop of doom again. So I started searching for a way to convert characters to integers, as my program didn't go into the infinite loop of doom with an integer expression as it did with a character expression.

Is cin.ignore important for programming? Meaning should I work harder on trying to get a good understanding of it, or is it something just used after cin to clear the buffer of '\n'?
Line 38 does not do what you think it does.

What you want there is to check the stream:

1
2
3
4
if( !cin ) {
    cout << "That is not a valid numerical answer" << endl;
    cin.ignore( 1000, '\n' );  // *see below
}


cin.ignore() is there for a purpose, so yes, if you plan at all to do interactive text-based programs you will need
to understand it.

* The above line says to ignore all input up to and including the next '\n' in the stream, but to ignore no more
than 1000 characters in any case. So in other words, if the user were to type 1001 characters without pressing
ENTER, the above line would read everything except the very last character the user typed before ENTER. This is a problem, but most programmers either a) assume no user would be stupid enough to type that many characters without pressing ENTER, or b) use std::numeric_limits<unsigned>::max(), in which case instead of 1000 characters, it is 4+ billion.

But with that above example, what if the user typed in "aghrns" ENTER ten typed in "a" and enter. Wouldn't that then send the program into an infinite loop again?

And yeah, while test running the program if the user enters 3fd5 for example, the while statement does not catch that, it only catches the character in the first place. However, with this set-up, the program doesn't go into an infinite loop no matter what input the user puts in, which was my goal. To make it more efficient I could try to doing that (I believe it would be a slight improvement). Would there be any other benefits to implementing your idea over mine?
No, it wouldn't, but the program wouldn't work either. You would need to ask the user to enter another
answer and check again, just as you've done above.

To answer your other question, the question is: if the user enters 3fd5 for example at the main menu,
how much do you trust that answer? What will be the user's reaction if you accept the input but the
user didn't really mean to type that? Probably the user didn't mean to enter that; maybe they just
fat-fingered some keys, maybe they dropped something on the keyboard, maybe they were just
joking around, mad at the computer, who knows. For a simple program like the above (no offense),
it probably doesn't matter. In general, probably it does. For example: suppose your program was
asking a nurse to enter the number of ccs of medication to dispense through an IV. If the user entered
"300o", would you trust it? Did they really mean 300 and just fat-finger the o, right below the zero?
Or did they really mean 30 and accidentally hit the 0 twice and the o? Or did they really mean 3000?
What would be the ramifcations if you accepted 300 but the user really meant 30? What would be
the ramifications if you accepted 300 but the user really meant 3000? Would you be satisfied relying
on the user to catch the fact that the display says its now dispensing a different amount of medication
than what they were expecting? Would the patient be satisfied with that?

Just some things to think about, not just for this project, but for all of your projects moving forward.



For a simple problem like this, it wouldn't really matter. Personally I wouldn't care about the wrong thing enetered. But the project listed as one of its qualities to be able to handle any input, expected or unexpected, and deal with it appropriately. And the program is supposed to loop on itself (not infinite loop) until the user decides to quit. it was a learning project, and I took it as such, learning the best way to do it for future projects (just in case one day the prof asks us to make a program for the delivery of IV fluids or something like that).

Thank you much for the help. It will give me some things to think about for future projects.
Topic archived. No new replies allowed.