How can I capture an unsigned value without casting? - c++

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.

Related

Is there any char data type alternative ( 1-byte value ) to represent numeric values?

I've this issue:
#include <iostream>
int main() {
unsigned char little_number_from_0_to_255 = 0;
std::cout << "How old are you (for example)? _";
std::cin >> little_number_from_0_to_255;
std::cout << "You are " << little_number_from_0_to_255 << " year/s old.";
}
In brief,
even if in this case what follows would'nt care much,
i'd like to avoid the waste of 1 byte (if compared to a short int type) for each variable i need to store when its value is so tiny,
but in all my attempts the un/signed char type variable is always interpreted as the ASCII representation of the first digit of the number I input the un/signed into.
Is there in C++ any good way to have a 1 byte data type, the value of could be only numeric (with all the arithmetic etc., like un/signed char) but without having to deal with the automatic ASCII representation (unlike un/signed char)?
If not, how could i "circumvent" the problem?
Is there a way to avoid that, even if I say that I'm 61, in the variable there will be 54 (decimal) and i will realize that i'm a liar 'cause in reality i'm only 6?
A way to say the computer that it has to grab the whole number and that it hasn't to look only at the first character input?
--I've already read of '+' just before the char variable, but this works only for output, and isn't my case.
Is there in C++ any good way to have a 1 byte data type, the value of could be only numeric (with all the arithmetic etc., like un/signed char) but without having to deal with the automatic ASCII representation (unlike un/signed char)?
You could define a wrapper class that stores a single byte integer type such as std::int8_t as a member, and implicitly converts to a non-character integer type such as int. Whether this is "good" is subjective and depends on use case.
If not, how could i "circumvent" the problem?
You can use an intermediate variable of non-character integer type when dealing with character streams:
std::uint8_t little_number_from_0_to_255 = 0;
// input
unsigned input;
std::cout << "How old are you (for example)? _";
std::cin >> input;
little_number_from_0_to_255 = input;
// output
unsigned output = little_number_from_0_to_255
std::cout << "You are " << output << " year/s old.";

Casting from size_t to char and around

I'm making the transition from C to C++11 now and I try to learn more about casting.
At the end of this question you see a small program which asked a number as input and then shows it as number and as character. Then it is cast to a char, and after that I cast it back to a size_t.
When I give 200 as input, the first cout prints 200, but the second cout prints 18446744073709551560.
How do I made it to print 200 again? Do I use the wrong cast? I have already tried different cast as dynamic and reintepret.
#include<iostream>
using namespace std;
int main(){
size_t value;
cout << "Give a number between 32 and 255: ";
cin >> value;
cout << "unsigned value: " << value << ", as character: `" << static_cast<char>(value) << "\'\n";
char ch = static_cast<char>(value);
cout << "unsigned value: " << static_cast<size_t>(ch) << ", as character: `" << ch << "\'\n";
}
size_t is unsigned, plain char's signed-ness is implementation-defined.
Casting 200 to a signed char will yield a negative result as 200 is larger than CHAR_MAX which is 127 for the most common situation, an 8-bit char. (Advanced note - this conversion is also implementation-defined but for all practical purposes you can assume a negative result; in fact usually -56).
Casting that negative value back to an unsigned (but wider) integer type will yield a rather large value, because unsigned arithmetic wraps around.
You might cast the value to an unsigned char first (yielding the expected small positive value), then cast that the wider unsigned type.
Most compilers have a switch that lets you toggle plain char over to unsigned so you could experiment with that. When you come to write portable code, try to write code that will work correctly in both cases!

Why does int8_t and user input via cin shows strange result [duplicate]

This question already has answers here:
uint8_t can't be printed with cout
(8 answers)
Closed 8 years ago.
A tiny piece of code drives me crazy but hopefully you can prevent me from jumping out of the window. Look here:
#include <iostream>
#include <cstdint>
int main()
{
int8_t i = 65;
int8_t j;
std::cout << "i = " << i << std::endl; // the 'A' is ok, same as uchar
std::cout << "Now type in a value for j (use 65 again): " << std::endl;
std::cin >> j;
std::cout << "j = " << j << std::endl;
if (i != j)
std::cout << "What is going on here?????" << std::endl;
else
std::cout << "Everything ok." << std::endl;
return 0;
}
If I use int instead of int8_t everything ok. I need this as 8-bit unsigned integers, not bigger. And btw. with unsigned char it's the same behaviour - of course - as with int8_t.
Anyone with a hint?
int8_t is a typedef for an integer type with the required characteristics: pure 2's-complement representation, no padding bits, size of exactly 8 bits.
For most (perhaps all) compilers, that means it's going to be a typedef for signed char.(Because of a quirk in the definition of the term signed integer type, it cannot be a typedef for plain char, even if char happens to be signed).
The >> operator treats character types specially. Reading a character reads a single input character, not sequence of characters representing some integer value in decimal. So if the next input character is '0', the value read will be the character value '0', which is probably 48.
Since a typedef creates an alias for an existing type, not a new distinct type, there's no way for the >> operator to know that you want to treat int8_t as an integer type rather than as a character type.
The problem is that in most implementations there is no 8-bit integer type that's not a character type.
The only workaround is to read into an int variable and then convert to int8_t (with range checks if you need them).
Incidentally, int8_t is a signed type; the corresponding unsigned type is uint8_t, which has a range of 0..255.
(One more consideration: if CHAR_BIT > 8, which is permitted by the standard, then neither int8_t nor uint8_t will be defined at all.)
int8_t and uint8_t are almost certainly character types (Are int8_t and uint8_t intended to behave like a character?) so std::cin >> j will read a single character from stdin and interpret it as a character, not as a number.
int8_t is likely the same as char, which means cin >> j will simply read a single character ('6') from input and store it in j.
int8_t is defined as a typedef name for signed char. So operator >> used with an object of type int8_t behaves the same way as it would be used for an object of type signed char
The _t types aren't first class types, they are typedef aliases the observe certain constraints, e.g. int8_t is a type that can store a signed, 8-bit value.
On most systems, this will mean they are typedefd to char. And because they are a typedef and not a first-class type, you are invoking cin.operator<<(char) and cin.operator>>(char).
When you input "65", cin.operator>>(char) consumes the '6' and places it's ascii value, 54, into variable j.
To work around this you'll need to use a different type, possibly the easiest method being just to use a larger integer type and apply constraints and then cast down:
int8_t fetchInt8(const char* prompt) {
int in = 0;
for ( ; ; ) { // endless loop.
std::cout << prompt << ": ";
std::cin >> in;
if (in >= std::numeric_limits<int8_t>::min()
&& in <= std::numeric_limits<int8_t>::max()) {
std::cout << "You entered: " << in << '\n';
// exit the loop
break;
}
std::cerr << "Error: Invalid number for an int8\n";
}
return static_cast<int8_t>(in);
}
Note that int8_t is signed, which means it stores -128 thru +127. If you want only positive values, use the uint8_t type.

C++ - Unsigned integers

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;
}

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.