0

I'm supposed to be writing a program that can convert a decimal number to binary. I have the code for the conversion working, but when I try to send an error when the user enters a number beyond the max/min for my type (unsigned short) using an if/else statement. When I enter what should be an invalid number the program jumps down to the conversion statement and either prints the max binary number (if entering something over 655355) or will go backwards counting down from the max (if entering in a negative number).

I thought wrote everything correctly.

#include <iostream>
#include <cmath>
#include <climits>
using namespace std;

// This converts the number to binary, it divides the imputed number by two, printing the reminders//

void bin(unsigned short nub)
{
    if (nub <=1)
    {
        cout << nub;
        return;
    }

    unsigned short rem;
    rem = nub % 2;
    bin( nub / 2);
    cout << rem;
}

int main()
{
    unsigned short dd;
    unsigned short bigNumber = pow(2,sizeof(unsigned short)*8)-1;

    cout << "\nPlease enter an unsigned short int between 0 and " << bigNumber << ": ";
    cin >> dd;


    //Should be printed if user imputs a number larger than the data type//

    if ( dd > bigNumber )
    {
        cout << "\nThe number is invalid. Please try again.\n\n";
    }

    //Should be printed if user imputs a negative number//

    else if (dd < 0)
    {
     cout << "\nThe number is invalid. Please try again.\n\n";
    }

    //Prints the binary number//

    else
    {
        cout << "\nThe Binary version of " << dd << " is ";
        bin(dd);
        cout << endl << endl;
    }


    return 0;
}
  • 1
    Since both `dd` and `bigNumber` are the same type and `bigNumber` is set to the maximum possible value for the type, `dd` can't ever be bigger, can it? –  Jul 10 '14 at 00:16
  • 1
    Have a look at [`bitset::to_string()`](http://en.cppreference.com/w/cpp/utility/bitset/to_string). – user657267 Jul 10 '14 at 00:24
  • Why not just use bitset (http://www.cplusplus.com/reference/bitset/bitset/) – Ed Heal Jul 10 '14 at 00:24
  • The other answers tell you why your `if` won't work, but have you tried a `try ... catch` and try to catch `overflow_error` and/or `underflow_error` exceptions? – triple_r Jul 10 '14 at 04:46

4 Answers4

1

You are running into an overflow yourself. Use another datatype for dd which is capable of holding values larger than 65535 (e.g. an unsigned int).

  • that could also cause a 'silent' overflow, if the input value is enought big – damgad Jul 10 '14 at 00:24
  • Of course, this was just thought as a mere example to give a hint on how to overcome the basic problem of using a datatype that is too limited such that the first comparison will never fail. – Christoph Freundl Jul 10 '14 at 00:31
0

You're having issues with overflow, especially from unsigned numbers.

Here's your first problem:

    unsigned short dd;
    // ...
    else if (dd < 0)

You have declared that dd is unsigned, so it is a meaningless comparison.

Next, you have done

    if(dd > bigNumber)

where bigNumber is the largest value an unsigned short can hold. Again, this is a meaningless comparison. To fix it, you'd need to make dd a larger data type; why not use an unsigned int?

Finally, a style tip. Instead of the monstrous pow(2,sizeof(unsigned short)*8)-1 contraption, use USHRT_MAX, available in <climits>.

George Hilliard
  • 15,402
  • 9
  • 58
  • 96
0

The problem is that you are comparing already overflowed value dd. It will never exceed the max value which it can hold.

As other people suggested you can use larger data type for dd but in some cases that would also case a 'silent' overflow.

Imagine that the entered value is big enough to overflow even unsigned int (or any other). You will have the same problem. Less frequently but you will have.

There is no easy way to prevent that, you could check answer to this question how you could do that.

Community
  • 1
  • 1
damgad
  • 1,446
  • 9
  • 24
0

If the input was too big for the data type, then the stream is put into a failure state. So you can check for the failure state. Your existing code didn't do this; what it would do in this case is do bin on whatever garbage was in the uninitialized variable dd.

Here is some sample code, actually using a loop (your code said "Please try again" and then exited!):

for (;;)
{
    cout << "Please enter a number between 0 and " << USHRT_MAX << ": ";
    cin >> dd;

    if ( !cin )
    {
        if ( cin.eof() )
            break;                    // exit loop entirely if the input is closed

        cout << "Not a valid unsigned short, please try again\n";
        cin.clear();                  // cancel the failure state
        string s; getline(cin, s);     // discard rest of line
        continue;
    }

    cout << "The Binary version of " << dd << " is ";
    bin(dd);
    cout << endl;
    break;
}

If you want to use a more limited range than 0...USHRT_MAX you can change if ( !cin ) to if ( !cin || dd < 12345 ) for example.

M.M
  • 138,810
  • 21
  • 208
  • 365