Comparing int and char with cast - c++

Why doesn't the function print "true" when '1' is input for both variables? How can I fix this?
int main() {
int i;
char c;
cout << "Type int: ";
cin >> i;
cout << "Type char: ";
cin >> c;
if (i == (int)c)
cout << "true" << endl;
else
cout << "false" << endl;
}

Even though char is an integer type, it is treated by the >> operator differently from other integer types.
For non-char integer recipient variable the >> operator treats the input as a representation of an integer value. The entire representation is consumed from the input, converted to integer and stored in the recepient variable. For example, if you enter 8 as the input, the recipient variable (say, an int) will receive integer value 8. If you enter 42 as the input, the recipient variable will receive integer value 42.
But for char recipient variable the >> operator treats the input as a mere character sequence. Only the first character of that sequence is consumed and immediately stored in the recipient variable. For example, if you enter 8 as the input, a char recipient variable will receive character '8', which corresponds to integer value of 56. If you enter 42 as the input, the recipient variable will receive character '4', which corresponds to integer value of 52.
That is what leads to the inequality in your case.

Like other input stream objects, std::cin is designed to work differently when you read into different types.
For an int, it reads the numbers you write into the console and parses them into internal integer form. This is convenient: "formatted extraction" means we get a useful int right away and don't need to any conversions from string to number.
For a char, it reads the actual letter or digit or punctuation that you wrote into the console; it does not parse it. It simply stores that character. In this case, c is 49 because that is the ASCII value of '1'.
If you wanted to see whether the int contained 1 and the char contained '1' to match, then you can exploit the property of ASCII that all the digits are found in sequential order starting from 48, or '0':
if (`i` == `c`-'0')
However, if you do this, you should verify that:
Your platform uses ASCII;
c contains a digit ('0', '1', ..., '9').
Generally avoid these hacks if you can. There's usually another way to check your inputs.

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.";

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.

Taking user input of an integer that can only be limited 1 digit

i'm currently learning c++ and have a project that I'm currently working on. My program in its entirety is to randomize 3 numbers from values 0-9 or set them myself. I was able to get the randomize numbers to work but not the setting of numbers myself. The issue being that when i tried to have the numbers as the int data type it produced 3 numbers for one input. It should be that x = 1, y = 2, z =3.... vales are: 123. To counter this issue I made the data type a character instead but it bugs me that random numbers are int values and my set numbers are char values. This is my current code below:
if ( userInput == 's') {
cout << "Enter three distinct digits each in the range 0..9 (e.g. 354)";
char num1 = ' ';
char num2 = ' ';
char num3 = ' ';
cin >> num1 >> num2 >> num3;
cout << endl << "Values to guess are: " << num1 << num2 << num3;
This might help you understand better what you're looking for.
Consider for example using:
int x;
cin >> x; // read an integer from the standard input stream (ignoring initial white space)
This will read a single integer from standard in, while
char c;
cin >> c; // read a character from standard input stream (ignoring initial white space)
read a single character from standard in (generally an ASCII character value).
If you have the following in standard input:
354
the first will finish with x = 354 and the second with c = '3' // = 51.
From my understanding you want to read 3 digits from standard in and store them in 3 separate numeric data types. You can do this using the following code:
uint8_t get_digit() {
char c;
cin >> c; // read a single non-whitespace character
if (! is_digit(c) ) return -1; // Error did not read a digit return bogus number
return (uint8_t)(c - '0'); // convert ascii digit to number and return value
}
This code will read a single character and check if it was a digit, if not it returns a bogus result (-1) othewise it returns the numeric value of the digit.

Why is character 'a' not converted to 97 automatically?

char input1;
std::cout << "input1 : ";
std::cin >> input1;
int input2;
std::cout << "input2 : ";
std::cin >> input2;
std::cout << input1 << std::endl;
std::cout << input2 << std::endl;
return 0;
I wrote 'a' at input1 and 'a' at input2.
Ouput is like this.
input1 : a
input2 : a
a
-858993460
I'm curious...'a' charter is 97 in dec. why does it print -858993460?
'a' is not converted to 97 automatically? why?
a, as a string, is not convertible to an int by the rules std::cin follows. Consider this: a is not a valid integer in base 10. std::cin will fail to convert the string "a" to an int.
The reason it prints -858993460 is because the int is not initialized, so it could print anything, or nothing, or do whatever it desires (look up undefined behaviour).
Try something like this instead:
char input2_chr;
std::cin >> input2_chr;
int input2 = input2_chr;
I think the input simply failed, and the value you're seeing is the result of undefined behavior (input2 was never written to).
If you try to read an integer, the character 'a' is not valid so it wouldn't be accepted by the >> operator.
You seem to somehow expect that the input should convert the character to the ASCII code for that character in order to give you the integer-typed result you requested. This reasoning is not supported by the language.
In the first, you asked to input a character, so you got the first
non-whitespace character in the stream. In the second, you asked to
input an integer, so the stream skips whitespace (as it always does with
>>) and attempted to parse an integer. Since "a" cannot be the
start of an integral value, the stream set an error status (the
failbit) and returned, without modifying input2. When you output
the uninitialized variable, you have undefined behavior. (You should
never use a variable you've input without first checking whether the
input succeeded or not.)
From what you describe, it sounds like you are trying to input some
binary format. To do that, you must open the stream in binary mode,
ensure that it is imbued with the "C" locale, and then use
istream::get or istream::read. (Of course, you have to know what
the binary format is that you are reading, in order to be able to
convert the unformatted bytes you read into the actual information you
need.)
As e.g. Aardvard already has answered, you're seeing an arbitrary original value, in the C++ standard called an indeterminate value, because the input operation failed and input2 was not assigned a new value.
To output a decimal representation of the value of a char variable, simply convert it to int in order to direct the output stream to treat as integer.
The easiest way to convert it to int is to encourage an implicit promotion by using the variable in an expression, such as simply adding a + sign in front of it:
#include <iostream>
using namespace std;
int main()
{
char const ch = 'a';
cout << "'" << ch << "' = " << +ch << endl;
}
Output:
'a' = 97
Because you are reading an integer at input2. a isn't an integer. Therefore nothing will be read, and the original value of input2 will be maintained.
In this case, it will be some random value, cause input2 isn't initialized.
You can check whether the read succeeded by checking cin.good()

Using C++ hex and cin

If you have the following code:
cout << hex << 10;
The output is 'a', which means the decimal 10 is converted into its hexadecimal value.
However, in the code below...
int n;
cin >> hex >> n;
cout << n << endl;
When input is 12, the output becomes 18. Can anyone explain the details of the conversion? How did it became a decimal value?
I'm interested in the point where it became an int. If broken down, it would be:
(( cin >> hex ) >> n);
Is this correct?
The hex manipulator only controls how a value is read - it is always stored using the same internal binary representation. There is no way for a variable to "remember" that it was input in hex.
"12" in hex is "18" in decimal. When you put in "12" into a hex cin stream, the internal value is 18 decimal. When you output to a stream which is by default decimal, you see the decimal value - "18".
It reads 0x12 (a hex value) and stores it in n, which you then print in decimal. Variables simply contain values, they do not contain information about the base (actually they store everything in base 2).