Binary to decimal error handling

I'm having problems implementing this. The original program works, which is as follows:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#include <iostream>

using namespace std;

int main() {

	char nextDigit;
	long int decimalValue = 0;

	cin.unsetf(ios_base::skipws);

	cin >> nextDigit;
	
	while (nextDigit != '\n') {
		decimalValue = ((decimalValue * 2) + nextDigit - 48);			
                cin >> nextDigit;
	}
	
	cout << "Decimal value is: " << decimalValue << endl;


	return 0;
}


I want to first change it, so that if the user enters a non-binary number, the program outputs "Error, wrong number." and quits. But everything I try, it ruins the code. Is there any way of doing this without changing the logic of the code too much?
Last edited on
At the beginning of your while loop, you could just check if the character is not equal to 0 or 1

Something like
1
2
3
4
5
if (nextDigit != '0' && nextDigit != '1') //If character is not 0 and character is not 1
{
	cout << "Invalid Binary Entry. Closing Program.";
	return -1;
}


So your revised code would be

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
#include <iostream>

using namespace std;

int main() {

	char nextDigit;
	long int decimalValue = 0;

	cin.unsetf(ios_base::skipws);

	cin >> nextDigit;

	while (nextDigit != '\n') {
		if (nextDigit != '0' && nextDigit != '1') //If character is not 0 && not 1
		{
			cout << "Invalid Binary Entry. Closing Program.";
			return -1;
		}
		decimalValue = ((decimalValue * 2) + nextDigit - 48);
		cin >> nextDigit;
	}

	cout << "Decimal value is: " << decimalValue << endl;


	return 0;
}
OH SO YOU PUT IT INSIDE THE WHILE LOOP! Man I was thinking about this and trying stuff like it for 2 hours, thank you so much.

Initially, I tried this:

1
2
3
4
5
6
7
8
9
10
11
if (!(nextDigit == 0 || nextDigit == 1)) {
		cout << "0" << endl; // output 0 if no valid digit(s) were entered.
	}
	else {
		while (nextDigit != '\n') {
			decimalValue = ((decimalValue * 2) + nextDigit - 48);
			cin >> nextDigit;
		}
		cout << "Decimal value is: " << decimalValue << endl; 
	}


But it only checked if it wasnt a 0 or a one, you're way is awesome. It checks the if the CHARACTERS are 0 or 1. That's genius man. Thanks again. If I wanted to make it continually ask the user to enter an input until a correct one is there, I'd need a while loop inside of a while loop right?

By the way, what does return -1 do there? I've never seen it before.
I think I almost have it, I have this so far:
1
2
3
4
5
6
7
8
9
10
11
12
while (nextDigit != '\n') {
		while (nextDigit != '0' && nextDigit != '1') 
		{
			cout << "Invalid Binary Entry. Enter again: " << endl;
			cin >> nextDigit;
		}
		decimalValue = ((decimalValue * 2) + nextDigit - 48);
		cin >> nextDigit;
	}

	cout << "Decimal value is: " << decimalValue << endl;


The only problem is, when I enter a wrong number, lets say 202..etc, it prints Invalid binary entry multiple times, not once like I want it to. I can't make sense of this, I only have one cout statement though..
Last edited on
Well for your code, return 0 and return 1/ return any number would do the same thing.

But in other applications your return # actually means something. Usually if an application is successful/closes properly, it returns 0. I just put -1 since they entered an invalid number. It's a way to close the program and get out of the while loop. If you just wanted to exit the while loop and not close the program, you could alternatively use break; to get out of that while loop.


You could use a bool as a switch and do something like this. This may not be the best way to do it, but it's just the first thing that came to mind.
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
#include <iostream>

using namespace std;

int main() {

	char nextDigit;
	long int decimalValue = 0;

	cin.unsetf(ios_base::skipws);

	cin >> nextDigit;

	bool ValidInput = false;

	while (ValidInput == false)
	{
		while (nextDigit != '\n') {
			if (nextDigit != '0' && nextDigit != '1') //If character is not 0 && not 1
			{
				cout << "Invalid Binary Entry. Try again." << endl;
				ValidInput = false;
				cin >> nextDigit;
				if (nextDigit == '\n')
					cin >> nextDigit;
				break;
			}
			ValidInput = true;
			decimalValue = ((decimalValue * 2) + nextDigit - 48);
			cin >> nextDigit;
		}
	}

	cout << "Decimal value is: " << decimalValue << endl;


	return 0;
}


Please ask questions about anything that's confusing and i'll try to clear it up.
I tried out that code. It is cool what you did with the boolean stuff! But actually, it does the same thing as my own attempt when I tried:

1
2
3
4
5
6
7
8
9
10
11
12
while (nextDigit != '\n') {
		while (nextDigit != '0' && nextDigit != '1') 
		{
			cout << "Invalid Binary Entry. Enter again: " << endl;
			cin >> nextDigit;
		}
		decimalValue = ((decimalValue * 2) + nextDigit - 48);
		cin >> nextDigit;
	}

	cout << "Decimal value is: " << decimalValue << endl;


When you enter a number like 9393939, it prints the error statement multiple times. It actually prints it more times as your string is longer, so 93993993939393 would 10 or so iterations of "Invalid input".

Would you know how I could alter my code to just get it to do it once?
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
#include <iostream>

using namespace std;

int main() {

	char nextDigit;
	long int decimalValue = 0;

	cin.unsetf(ios_base::skipws);

	cin >> nextDigit;

	bool ValidInput = false;

	while (ValidInput == false)
	{
		while (nextDigit != '\n') {
			if (nextDigit != '0' && nextDigit != '1') //If character is not 0 && not 1
			{
				cout << "Invalid Binary Entry. Try again." << endl;
				ValidInput = false;
				cin >> nextDigit;
				while (nextDigit != '\n')
				{
					cin >> nextDigit;
				}
				cin >> nextDigit;
				break;
			}
			ValidInput = true;
			decimalValue = ((decimalValue * 2) + nextDigit - 48);
			cin >> nextDigit;
		}
	}

	cout << "Decimal value is: " << decimalValue << endl;


	return 0;
}
Alas, it works! Now I should probably figure out why haha. Thank you
Oops. I didn't mean to put the cin right before the while (nextDigit!='\n')

It is not required.

Let's go through the logic.
So let's say I type in 9393

The buffer gets '9' '3' '9' '3' '\n'

So we get into the while loop and so far '9' has been read in. We still have '3' '9' '3' '\n' to go through

in our while loop we check if the current digit is the newline ('\n')
If it is not the newline, we get the next character '3'

We still have '9' '3' and '\n' in the buffer

The while loop keeps going

we get '9' we still have '3' and '\n' in the buffer

we get the '3' and all that is left in the buffer is '\n'

So we call that cin >> nextDigit and now nextDigit = '\n' so our while loop ends

The last cin call is just to get the next input for the next number the user tries to type in.

But yeah, the first cin is not required and it can be removed so the code would be
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
#include <iostream>

using namespace std;

int main() {

	char nextDigit;
	long int decimalValue = 0;

	cin.unsetf(ios_base::skipws);

	cin >> nextDigit;

	bool ValidInput = false;

	while (ValidInput == false)
	{
		while (nextDigit != '\n') {
			if (nextDigit != '0' && nextDigit != '1') //If character is not 0 && not 1
			{
				cout << "Invalid Binary Entry. Try again." << endl;
				ValidInput = false;
				while (nextDigit != '\n')
				{
					cin >> nextDigit;
				}
				cin >> nextDigit;
				break;
			}
			ValidInput = true;
			decimalValue = ((decimalValue * 2) + nextDigit - 48);
			cin >> nextDigit;
		}
	}

	cout << "Decimal value is: " << decimalValue << endl;


	return 0;
}
Last edited on
It makes sense a little bit when you explain it, thanks! When I try to implement my own version, that's where things become wobbly. I tried to implement the boolean statements and if/elses inside of a while loop:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
char nextDigit;
	long int decimalValue = 0;
	bool keepLooping = true;

	cin.unsetf(ios_base::skipws);

	do {

		cin >> nextDigit;

		if (nextDigit != '0' && nextDigit != '1') {
			cout << "Invalid Binary Entry. Enter again: " << endl;
			keepLooping = false;
		}
		else {
			decimalValue = ((decimalValue * 2) + nextDigit - 48);
		}
	} while (keepLooping);

	cout << "Decimal value is: " << decimalValue << endl;


I'm almost there! But I need an extra push.

If I enter 10101, I get the error message, but then I get 21 in the next line, which is good.

If I enter any wrong number, like 9393, I will get the error message. Then it will tell me the decimal is 0, and always 0 no matter what the wrong input number was.

How can I get the last step down?
Last edited on
Here's another way to do it.
- Rather than using the whole std namespace, it's good practice to use only the names that you need.
- I think the switch statement makes the logic clearer.
- I've changed the magic constant 48 to '0' to make it clearer what's going on.
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
#include <iostream>

using std::cin;
using std::cout;
using std::ios_base;
using std::endl;

int main() {

    char nextDigit;
    long int decimalValue = 0;
    bool done = false;

    cin.unsetf(ios_base::skipws);

    while (!done && cin >> nextDigit) {
        switch(nextDigit) {
        case '0':
        case '1':
            decimalValue = ((decimalValue * 2) + nextDigit - '0');
            break;
        case '\n':
            done = true;
            break;
        default:
            cout << "invalid entry\"" << nextDigit << "\". Try again\n";
            decimalValue = 0;
            cin.ignore(1000000, '\n');
            break;
        }
    }

    cout << "Decimal value is: " << decimalValue << endl;
    return 0;
}

This looks pretty cool. I'll bookmark it to study from in the weeks to come. We haven't learned about switch and this case 0 1 2 3 thing, I think that's next week. It looks very neat.

My apologies to bother you guys, in my last attempt of solving it, I believe I am so close! But still
there are 2 small errors that I cannot find the fix behind. Is there any changes to my code here I can do?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
        char nextDigit;
	long int decimalValue = 0;
	bool keepLooping = true;

	cin.unsetf(ios_base::skipws);

	do {

		cin >> nextDigit;

		if (nextDigit != '0' && nextDigit != '1') {
			cout << "Invalid Binary Entry. Enter again: " << endl;
			keepLooping = false;
		}
		else {
			decimalValue = ((decimalValue * 2) + nextDigit - '0');
		}
	} while (keepLooping);

	cout << "Decimal value is: " << decimalValue << endl;
Last edited on
If I enter 10101, I get the error message, but then I get 21 in the next line, which is good.

The last character read is a newline ('\n'). The test at line 11 is true, so it prints the message. The way around this is to check for a newline BEFORE you check for an invalid digit.

If I enter any wrong number, like 9393, I will get the error message. Then it will tell me the decimal is 0, and always 0 no matter what the wrong input number was.

If you enter 9393, it fails on the first '9'. Line 12 prints the "invalid" message. Line 13 sets keepLooping to false, which causees the loop to end at line 18. Then line 20 dutifully prints the decimal value, which is 0 because it hasn't added anything to it.

This code fixes both problems:
1
2
3
4
5
6
7
8
9
10
11
12
13
    do {
        cin >> nextDigit;

        if (nextDigit == '\n') {
            break;
        } else if (nextDigit != '0' && nextDigit != '1') {
            cout << "Invalid Binary Entry. Enter again: " << endl;
            cin.ignore(1000000, '\n');
            decimalValue = 0;
        } else {
            decimalValue = ((decimalValue * 2) + nextDigit - '0');
        }
    } while (true);

Notice that when you enter invalid input, line 8 skips everything through the newline and sets decimalValue back to zero. The loop will run again, reading from the start of the next input line and with a freshly zeroed value for decimalValue.

Now that the loop is working for invalid input, it becomes a do-while(true) loop. The only way out of the loop is when it sees a newline.
Topic archived. No new replies allowed.