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.
Related
#include <iostream>
using namespace std;
int main()
{
unsigned long maximum = 0;
unsigned long values[] = {60000, 50, 20, 40, 0};
for(short value : values){
cout << "Current value:" << value << "\n";
if(value > maximum)
maximum = value;
}
cout << "Maximum value is: " << maximum;
cout << '\n';
return 0;
}
Outputs are:
Current value:-5536
Current value:50
Current value:20
Current value:40
Current value:0
Maximum value is: 18446744073709546080
I know I should not use short inside for loop, better use auto, but I was just wondering, what is going on here?
I'm using Ubuntu with g++ 9.3.0 I believe.
The issue is with short value when element 60000 is reached.
That's too big to fit into a short on your platform, so your short is overflowed, with implementation-defined results.
What seems to be happening in your case is that 60000 wraps round to the negative -5536, then converted (in a well-defined) way to an unsigned long, which in your case is 264 - 5536: that's equal to the maximum displayed by your program.
One fix is to use the idiomatic
for(auto&& value: values){
The problem is pretty much simple, the 2-bytes short type integer can hold only the values between -32,768 to 32,767. Afterwards, it get overflowed. You've given 60000, which is obviously an overflow for a short int.
When you use auto here, the value get converted into an appropriate type which could hold such a large number (note that it's up to the platform in which you're running the program.)
In my case, the value is get converted into unsigned long which ranges between 0 to 4,294,967,295.
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.
I've wrote a small program to convert a char to an int. The program reads in chars of the form '1234' and then outputs the int 1234:
#include <iostream>
using namespace std;
int main(){
cout << "Enter a number with as many digits as you like: ";
char digit_char = cin.get(); // Read in the first char
int number = digit_char - '0';
digit_char = cin.get(); // Read in the next number
while(digit_char != ' '){ // While there is another number
// Shift the number to the left one place, add new number
number = number * 10 + (digit_char - '0');
digit_char = cin.get(); // Read the next number
}
cout << "Number entered: " << number << endl;
return 0;
}
This works fine with small chars, but if I try a big char (length 11 and above) like 12345678901 the program returns the wrong result, -539222987.
What's going on?
12345678901 in binary is 34 bits. As a result, you overflowed the integer value and set the sign bit.
Type int is not wide enough to store such big numbers. Try to use unsigned long long int instead of the type int.
You can check what maximum number can be represented in the given integer type. For example
#include <iostream>
#include <limits>
int main()
{
std::cout << std::numeric_limits<unsigned long long int>::max() << std::endl;
}
In C you can use constant ULLONG_MAX defined in header <limits.h>
Instead of using int, try to use unsigned long long int for your variable number.
That should solve your problem.
Overflowed integer. Use unsigned long long int.
I have the following c++ code:
#include <iostream>
using namespace std;
int main()
{
long long int currentDt = 467510400*1000000;
long long int addedDt = 467510400*1000000;
if(currentDt-addedDt >= 0 && currentDt-addedDt <= 30*24*3600*1000000)
{
cout << "1" << endl;
cout << currentDt-addedDt << endl;
}
if(currentDt-addedDt > 30*24*3600*1000000 && currentDt-addedDt <= 60*24*3600*1000000)
{
cout << "2" << endl;
cout << currentDt-addedDt << endl;
}
if(currentDt-addedDt > 60*24*3600*1000000 && currentDt-addedDt <= 90*24*3600*1000000)
{
cout << "3" << endl;
cout << currentDt-addedDt << endl;
}
return 0;
}
Firstly, I get a warning for integer overflow, which strikes me as odd because the number 467510400*1000000 falls well within the range of a long long int, does it not? Secondly, I get the following output:
1
0
3
0
If in both cases currentDt-addedDt evaluates to 0, how could the third if statement possibly evaluate to true?
467510400*1000000 is within the range of long long, but it's not within the range of int. Since both literals are of type int, the type of the product is also of type int - and that will overflow. Just because you're assigning the result to a long long doesn't change the value that gets assigned. For the same reason that in:
double d = 1 / 2;
d will hold 0.0 and not 0.5.
You need to explicitly cast one of the literals to be of a larger integral type. For example:
long long int addedDt = 467510400LL * 1000000;
long long int currentDt = 467510400ll*1000000ll;
long long int addedDt = 467510400ll*1000000ll;
Note the two lowercase letter "l"s following the digits. These make your constants long long. C++ normally interpret strings of digits in source as plain ints.
The problem you are having is that all of your integer literals are int. When you multiply them they overflow giving you the unexpected behavior. To correct this you can make them long long literals using 467510400ll * 1000000ll
It because
60*24*3600*1000000 evaluates to -25526272
use
60LL*24LL*3600LL*1000000LL
instead (note the 'LL' suffix)
You have tagged this with C++.
My minimal change to your code would use the c++ static_cast to promote at least one of the literal numbers (of any overflow generating expression) to an int64_t (found in include file cstdint).
Example:
// 0 true
if(currentDt-addedDt >= 0
&& // true because vvvv
// 0 true
currentDt-addedDt <= 30*24*3600*static_cast<int64_t>(1000000))
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
(for test 1, the result of the if clause is true.
for test 2 and 3 is false)
Upon finding the static_cast, the compiler promotes the 3 other integers (in the clause) to int64_t, and thus generates no warnings about overflow.
Yes, it adds a lot of chars for being, in some sense, 'minimal'.
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;
}