C++ - Unsigned integers - c++

I have the following program written in C++:
The problem with this program is that if the user inputs a negative number, it is NOT caught by the line if(!cin). I thought that unsigned integers can NOT accept negative numbers. Then why if I enter a negative number to size, it is NOT caught by if(!cin) and the program continues execution with no error messages?
I cannot make use of if(size < 0). I want to show how unsigned integers can solve the problem of negative input.

The difference between unsigned and signed integers on most platforms is a sign-bit ... other than that, the actual binary value is the same, it's just interpreted two different ways depending on the sign-ness of the type that the binary value represents. So you can definitely "represent" a negative value input as a unsigned value ... it won't be re-interpreted as that value, but it can definitely be input as that value without an error being set on the stream.

Not a c++ guru or anything but, have you tried using cin.fail() instead of !cin and clear out your buffer with cin.clear()
deeper explaination

C and C++ allow you to assign a negative value to an object of an unsigned type. The result is the original value reduced modulo 2^n, where n is the size of the unsigned type. So, for example, unsigned i = -1; initializes i to UINT_MAX.

The check if(!cin) will only indicate that nothing was read, like the end of a file.
An unsigned integer doesn't force the input to be positive; it just means that the value will always be interpreted as positive (see sign bit), which can have dramatic effects if the number is in fact negative.
Your best bet is probably to input a signed integer and then test in your code whether it is positive.

If you want to prevent the user from entering negative numbers, take input as a signed number and check that it's equal to or greater than zero.
The standard basically says that when you try to assign a number to an integral type that is outside of the range of the type, multiples of the magnitude of the type will be added or subtracted until the value is within the range.
It just so happens that with values expressed as 2-s complement and within the ranges of signed and unsigned ints, this means that the exact same bit pattern will be assigned to any value. Negative one has a bit pattern of all ones, which translates to the highest possible value for the unsigned int, and is equivalent to -1 + 232 or the original value plus the magnitude of an unsigned int.

Or you could just use a larger signed integral type.
long long n = -1;
cout << "Enter a number: ";
cin >> n;
if( !cin.good() )
cout << "Not a valid number." << endl;
else if( n > UINT_MAX )
cout << "Overflow, value is more than UINT_MAX." << endl;
else if( n < 0 )
cout << "Negative, value is less than 0." << endl;
else {
unsigned int m = (unsigned int)n;
cout << "Valid unsigned int was input: " << m << "." << endl;
}

Related

How can I capture an unsigned value without casting?

How can I capture an unsigned value without casting?
I am writing a simple program to calculate the LCF and the GCD of an array of numbers. In order to properly calculate them, the numbers should be always positive intergers, for I which chose the type "unsigned long long int". However, I still did not find a way to prevent the user to enter a negative value without casting.
Whenever I use std::cin >> variable, the program allows the user to enter a negative number. In case of unsigned values, the number will be the range-minus-value of the size of type. In case of unsigned short interger, if a user enters -5, the value stored in the variable will be 65.531.
Here is the part of the code I am trying to improve:
#include<iostream>
#include<stdlib.h>
using namespace std;
typedef unsigned long long int ulli;
/* many lines of code, variables already declared */
// array_list_of_numbers is of type UNsigned long long int
// var_verify_if_negative is of type signed long long int
cout << "Please inform the numbers." << endl;
for ( iterador1 = 0 ; iterador1 < size_of_the_list ; ++iterador1){
cout << "Please, inform number "<< iterador1+1 << ": ";
cin >> var_verify_if_negative;
while (var_verify_if_negative <= 0){
cout << "Number must be equal or greater than 1!" << endl;
cout << "Try again: ";
cin >> var_verify_if_negative;
/*end while*/}
array_list_of_numbers[iterador1] = (ulli)var_verify_if_negative; // << here is the casting
/*end for*/}
However, if I use casting of a signed variable, there is no point of using unsigned data type at all. It would be better to declare the variables already as signed and perform the check.
The original code was:
cout << "Please inform the numbers." << endl;
for ( iterador1 = 0 ; iterador1 < size_of_the_list ; ++iterador1){
cout << "Please, inform number "<< iterador1+1 << ": ";
cin >> array_list_of_numbers[iterador1];
/*end for*/}
Which allows wrong input.
How can I test if a user entered a signed value using std::cin ?
Why not simply read a (signed) long and refuse it when its negative and use it otherwise ?
If you really need the full range of an unsigned long you would need to read a string first, check if it starts with a '-' (and refuse) and convert to unsigned long otherwise.
Unfortunately, there is no specific extractor which would refuse signed integers for standard stream, instead, signed integer is converted to unsigned value (which is actually undefined behavior for negative numbers).
However, your whole approach is somewhat flawed. If you want to disallow numbers which are less than 0, the best you can do is to actually accept signed integers, and than check the number to be greater than zero and report error (and refuse the input) when it is not.
The best case scenario would have been for the stream extractor to report failure when a negative number is entered when the expected type is an unsigned type.
unsigned int num;
while ( !(in >> num) )
{
std::cerr << "Wrong input. Try again...";
}
However, the standard specifies that it's OK to enter negative number even when the expected type is an unsigned type.
When the type is an unsigned type, the standard library uses the %u format specifier in the core conversion logic. From https://en.cppreference.com/w/cpp/locale/num_get/get:
If the type of v is unsigned, will use conversion specifier %u
Now, if you look at how the standard library deals with %u (https://en.cppreference.com/w/cpp/io/c/fscanf#Parameters), the conversion is performed by strtoul.
From strtoul documentation:
If the minus sign was part of the input sequence, the numeric value calculated from the sequence of digits is negated as if by unary minus in the result type, which applies unsigned integer wraparound rules.
Your best bet is to read into a signed type and make sure it is a non-negative number before proceeding to use it.

Is there a max int length a user can input?

I made a little program to determine the length of a user-provided integer:
#include <iostream>
using namespace std;
int main()
{
int c=0; //counter for loop
int q=1; //quotient of number upon division
cout << "Hello Cerberus! Please enter a number." << endl;
cin >> q;
if(q > -10 && q < 10)
{
cout << "The number you entered is 1 digit long." << endl;
}
else
{
while(q != 0)
{
q=q/10;
c++;
}
cout << "The number you entered is " << c << " digits long." << endl;
}
return 0;
}
It works quite nicely, unless the numbers get too big. Once the input is 13 digits long or so, the program defaults to "The number you entered is 1 digit long" (it shouldn't even present that solution unless the number is between -10 and 10).
Is there a length limit for user-input integers, or is this demonstrative of my computer's memory limits?
It's a limit in your computer's architecture. Every numeric type has a fixed upper limit, because the type describes data with a fixed size. For example, your int is likely to take up either four or eight bytes in memory (depending on CPU; based on your observations, I'd say the former), and there are only so many combinations of bits that can be stored in so many bytes of memory.
You can determine the range of int on your platform using std::numeric_limits, but personally I recommend sticking with the fixed-width type aliases (e.g. int32_t, int64_t) and picking whichever ones have sufficient range for your application.
Alternatively, there do exist so-called "bigint" libraries that are essentially classes wrapping integer arrays and adding clever functionality to make arbitrarily-large values work as if they were of arithmetic types. That's probably overkill for you here though.
Just don't be tempted to start using floating-point types (float, double) for their magic range-enhancing abilities; just like with the integral types, their precision is fundamentally limited, but using floating-point types adds additional problems and concerns on top.
There is no fundamental limit on user input, though. That's because your stream is converting text characters, and your stream can basically have as many text characters in it as you could possibly imagine. At that level, you're really only limited by available memory.

Need help displaying a 2's compliment in 16-bit binary [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Efficiently convert between Hex, Binary, and Decimal in C/C++
Im taking an Assembly Language class and was asked to write an application to accept a signed integer as input and output the corresponding 2's complement. I've been all over the internet trying to find code that would help, but the only thing that I can find is code that converts into exact binary (not the 16-bit format that I need with the leading zeroes). This is the code I have so far:
#include<iostream>
#include<string>
using namespace std;
string binaryArray[15] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
void toBinary(int);
void convertNegative();
int main()
{
cout << "This app converts an integer from -32768 to 32767 into 16-bit 2's complement binary format" << endl;
cout << "Please input an integer in the proper range: ";
int num;
cin >> num;
if (num < -32768 || num > 32767)
cout << "You have entered an unacceptable number, sorry." << endl;
if (num < 0)
{
toBinary(num);
convertNegative();
}
else
toBinary(num);
cout << endl;
system("pause");
return 0;
}
My toBinary function was the function you can find on the internet for decimal to binary, but it only works if I am outputting to the console, and it doesn't work on negative numbers, so I can't take the 2's complement. Any ideas?
To compute the two's complement of a number, you invert the number (change all of its 0 bits to 1, and all of its 1 bits to 0), and then add one. It's that simple. But you'd only need to do that if the number is negative in the first place; the two's complement of a non-negative number is simply the number itself (unconverted).
But you're taking a number as input, and storing it in your variable 'num'. That variable IS in two's complement form. That's how your computer stores it. You don't need to "convert" it to two's complement form at all! If you simply shift the bits off one at a time & print them, you get the two's complement of that number. Just shift them in the right order & pick off the leftmost bit each time, and you've got your solution. It's really short & simple.

Reading 'unsigned int' using 'cin'

I am trying to read an unsigned int using cin as follows:
#include <limits.h>
#include <iostream>
using namespace std;
int main(int argc, char* argv[])
{
unsigned int number;
// UINT_MAX = 4294967295
cout << "Please enter a number between 0 and " << UINT_MAX << ":" << endl;
cin >> number;
// Check if the number is a valid unsigned integer
if ((number < 0) || ((unsigned int)number > UINT_MAX))
{
cout << "Invalid number." << endl;
return -1;
}
return 0;
}
However, whenever I enter a value greater than the upper limit of unsigned integer (UINT_MAX), the program displays 3435973836. How do I check if the input given by user falls between 0 to UINT_MAX?
Two things:
Checking if an unsigned integer is < 0 or > UINT_MAX is pointless, since it can never reach that value! Your compiler probably already complains with a warning like "comparison is always false due to limited range of type".
The only solution I can think of is catching the input in a string, then use old-fashioned strtoul() which sets errno in case of overflow.
I.e.:
#include <stdlib.h>
unsigned long number;
std::string numbuf;
cin >> numbuf;
number = strtoul(numbuf.c_str(), 0, 10);
if (ULONG_MAX == number && ERANGE == errno)
{
std::cerr << "Number too big!" << std::endl;
}
Note: strtoul returns an unsigned long; there's no function strtou(), returning an unsigned int.
Your check makes no sense (which a compiler with properly enabled warnings would tell you) as your value is never under 0 and never over UINT_MAX, since those are the smallest and biggest value a variable of the type unsigned int (which number is) can hold.
Use the stream state to determine if reading into the integer worked properly.
You could read into an unsigned long long and test that against the unsigned int limit.
When users enter a number higher than UINT_MAX, cin caps it at UINT_MAX anyway. The value cannot be negative, either.
If you need to extend the range, use unsigned long long for input, and cast to unsigned int after the check. This will not guard against numbers that are outside of range of unsigned long long, though.
For a general-purpose solution, you can read a string, and do a conversion yourself using unsigned long long as your result.
If you try to read it into an unsigned int you are going to have to limit yourself to the constraints of an unsigned int.
The most general way to do what you're asking is to read the input as a string and parse it to make sure it's in the proper range. Once you have validated it, you can convert it to an unsigned int.

Can assigning smaller integer type to a larger integer type be unsafe?

Apart from the case where smaller type is signed and is < 0 and larger is unsigned, are there any other cases where assigning smaller int type to a larger int type can be unsafe?
As far as I know, there is no problem assigning smaller integer types to larget integer types.
The problem is the other way around.
I think No. Because the larger type can accomodate all the bit information of the smaller type. The only problem could be the signed/unsigned things (as its always the case when mixing signed with unsigned). But then you can get back the original value anytime. No loss of information.
signed short s = -1;
unsigned int i = s;
signed short originalValue = (signed short)i;
cout << s << endl;
cout << i << endl;
cout << originalValue << endl;
Output:
-1
4294967295
-1
Online Demo : http://ideone.com/z3G9x