1

In C++, how can I input a number to unsigned char variable? In C, I can accept the input using %hhu format specifier:

unsigned char var_name;
scanf("%hhu", &var_name);
//lets say I inputted 27
printf("%hhu", var_name);
//the output is 27

How can I do that in C++? The code below is my attempt to do this in C++, but it does a wrong thing. How can I write equivalent code in C++?

unsigned char var_name;
std::cin >> var_name;
//Input 27 again
std::cout << var_name;
//The output is just 2, how can I make the '7' appear?
digito_evo
  • 3,216
  • 2
  • 14
  • 42
  • 2
    same as with any other variable `std::cin >> var_name;` – 463035818_is_not_an_ai Aug 02 '22 at 07:39
  • But if I enter 12(essentially any number that are more than one digit long) to that var, then I print the value, it just print the first digit of the value I inputted(in this case 1). Why? –  Aug 02 '22 at 07:46
  • @manungsa Because reading one `char` reads one character, and a digit is one character. – molbdnilo Aug 02 '22 at 07:47
  • Related: [How can you assign an integer value to a char datatype?](https://stackoverflow.com/questions/29547689/how-can-you-assign-an-integer-value-to-a-char-datatype) – Jason Aug 02 '22 at 08:01
  • @463035818_is_not_a_number That C++ code is non-working code... It does not print what is required! I don't see an issue with the question. – hyde Aug 02 '22 at 09:41
  • 1
    In fact, I think this is non-trivial in C++, if the desire is to be able to read an integer from an `std::istream` to `unsigned char` variable... A helper class is probably needed. – hyde Aug 02 '22 at 09:46
  • Review [Standard Input for Unsigned Character](https://stackoverflow.com/a/25087572/2410359). – chux - Reinstate Monica Aug 02 '22 at 09:50
  • [Why does int8_t and user input via cin shows strange result](https://stackoverflow.com/q/24617889/995714), [Why std::(i)ostream treat signed / unsigned char as a text and not an integer?](https://stackoverflow.com/q/36843616/995714) – phuclv Aug 02 '22 at 09:55
  • Does this answer your question? [Why std::(i)ostream treat signed / unsigned char as a text and not an integer?](https://stackoverflow.com/questions/36843616/why-stdiostream-treat-signed-unsigned-char-as-a-text-and-not-an-integer) – phuclv Aug 02 '22 at 09:55
  • 2
    @phuclv None of the answers under that question actually offer a solution, they just explain what happens. So it's not a very good duplicate candidate. – hyde Aug 02 '22 at 09:57
  • @hyde the issue was(!) that OP was refering to a problem with C++ code they didnt show. In its current state imho the question should not be closed – 463035818_is_not_an_ai Aug 02 '22 at 10:50

3 Answers3

0

You are only getting a 2 when printing the variable because of cin.

The maximum size of an unsigned char in C++ is usually 8 bits, which is fine for any actual character, and any digit up to 255. However this number depends on the compiler and the system. The maximum value that can be stored is in the header, as UCHAR_MAX.

Your issue here is that you are using cin, which only ever reads the first 'character' of an input if it is storing that input as a char. There are several ways around this, including taking the input as an integer and then converting to a char, or making your program work with an integer.

Hope this helps :)

  • Code is not working as expected. Expectation is to print `27`, it prints just `2`. There are two meanings of "expected" here, and the important one is, what is expected by the requirements (which is same output than the C code above). – hyde Aug 02 '22 at 09:54
  • Sorry about that I'll change it :) – Guy Lawrence-Downs Aug 02 '22 at 10:11
0

This happens because when reading an unsigned char from std::istream, a character is read. That's just what happens, that's how std::istream works. It also makes a lot of sense, because it's quite common to want to read a single character.

The trivial solution is to use a temp variable:

unsigned char var_name;
unsigned int tmp;
std::cin >> tmp; // input 27
// optionally add checking that tmp is small enough
var_name = tmp; // truncation of unsigned ints is well defined
std::cout << var_name; // should print 27
hyde
  • 60,639
  • 21
  • 115
  • 176
  • A more interesting solution would be to write a wrapper like `template class as_number { ....`, which would allow doing `std::cin >> as_number{tmp};`. – hyde Aug 02 '22 at 10:03
0

When var_name is of type unsigned char, then the line

std::cin >> var_name;

is similar to

std::scanf("%c", &var_name);

i.e. C++ will assume that you want to read a single character and write the character code into var_name.

If you instead want to read a number and write that number into var_name, then you cannot use the data type char or unsigned char when using operator >>, even if the data type is technically able to represent the desired range of values. Instead, you will first have to use a variable with a larger data type, such as unsigned short, for reading the number. Afterwards, you can assign it to another variable of type unsigned char:

unsigned char var_name;
unsigned short temp;

std::cin >> temp;

if ( std::cin )
{
    var_name = static_cast<unsigned char>( temp );
    std::cout << var_name << '\n';
}
else
{
    //TODO: handle error
}

The static_cast is not necessary, but some compilers may emit a warning due to the truncation, which will probably be suppressed by the cast. Also, using the cast makes the code more readable, because it becomes obvious that the value is being truncated.

However, I generally do not recommend that you use operator >> for user input, because it will do strange things, such as

  • not always read one line of input at a time, and
  • accept garbage such as "6sdfj23jlj" as valid input for the number 6, although the input should probably be rejected in this case.

If you want to read a number from the user with proper input validation, I recommend that you take a look at my function get_int_from_user in this answer of mine to another question.

Andreas Wenzel
  • 22,760
  • 4
  • 24
  • 39