Signed Hexadecimal to decimal in C++ - c++

By using std::hex and std::dec, it is possible to parse hexadecimal from a string and convert it to a decimal number in C++. But what if the hexadecimal number is signed?
The following code for example will result 241 which is correct if the input "F1" is unsigned hex, but the result should be -15 if the input was a signed hex. Is there a C++ function that can process signed hex values?
int n;
stringstream("F1") >> std::hex >> n;
std::cout << std::dec << "Parsing \"F1\" as hex gives " << n << '\n';

When you say "signed hex" you mean if you were to represent the bitwise representation of a char in hexadecimal then F1 would be -15. However, -15 in signed hex is simply -F.
If you want to get -15 from this bitwise representation you'll have to do something like the following:
std::string szTest = "F1";
unsigned char chTest = std::stoi( szTest, nullptr, 16 );
char chTest2 = *reinterpret_cast<char*>(&chTest);
std::cout << szTest << ": " << static_cast<int>(chTest2) << std::endl;
return 0;

Related

Converting HEXA 64 bits numbers to int

I'm making a college job, a conversion between hexa numbers enclosed in a stringstream. I have a big hexa number (a private key), and I need to convert to int, to put in a map<int,int>.
So when I run the code, the result of conversion is the same for all the two hexa values inserted, what is incorrect, it should be differente results after conversion. I think it's an int sizes stack problem, because when I insert short hexas, it works greatly. As shown below the hexa has 64 bits.
Any idea to get it working?
int main()
{
unsigned int x;
std::stringstream ss;
ss << std::hex << "0x3B29786B4F7E78255E9F965456A6D989A4EC37BC4477A934C52F39ECFD574444";
ss >> x;
std::cout << "Saida" << x << std::endl;
// output it as a signed type
std::cout << "Result 1: " << static_cast<std::int64_t>(x) << std::endl;
ss << std::hex << "0x3C29786A4F7E78255E9A965456A6D989A4EC37BC4477A934C52F39ECFD573344";
ss >> x;
std::cout << "Saida 2 " << x << std::endl;
// output it as a signed type
std::cout << "Result 2: " << static_cast<std::int64_t>(x) << std::endl;
}
Firstly, the HEX numbers in your examples do not fit into an unsigned int.
You should clear the stream before loading the second HEX number there.
...
std::cout << "Result 1: " << static_cast<std::int64_t>(x) << std::endl;
ss.clear();
ss << std::hex << "0x3C29786A4F7E78255E9A965456A6D989A4EC37BC4477A934C52F39ECFD573344";
ss >> x;
...
Each hexadecimal digit equates to 4 bits (0xf -> 1111b). Those hex strings are both 64 x 4 = 256 bits long. You're looking at a range error.
You need to process the input 16 characters at a time. Each character is 4 bits. The 16 first characters will give you an unsigned 64-bit value. (16x4 is 64)
Then you can put the fist value in a vector or other container and move on to the next 16 characters. If you have questions about string manipulation, search this site for similar questions.

How to avoid 0xFF prefix when converting char to short?

When I do:
cout << std::hex << (short)('\x3A') << std::endl;
cout << std::hex << (short)('\x8C') << std::endl;
I expect the following output:
3a
8c
but instead, I have:
3a
ff8c
I suppose that this is due to the way char—and more precisely a signed char—is stored in memory: everything below 0x80 would not be prefixed; the value 0x80 and above, on the other hand, would be prefixed with 0xFF.
When given a signed char, how do I get a hexadecimal representation of the actual character inside it? In other words, how do I get 0x3A for \x3A, and 0x8C for \x8C?
I don't think a conditional logic is well suited here. While I can subtract 0xFF00 from the resulting short when needed, it doesn't seem very clear.
Your output might make more sense if you looked at it in decimal instead of hexadecimal:
std::cout << std::dec << (short)('\x3A') << std::endl;
std::cout << std::dec << (short)('\x8C') << std::endl;
output:
58
-116
The values were cast to short, so we are (most commonly) dealing with 16 bit values. The 16-bit binary representation of -116 is 1111 1111 1000 1100, which becomes FF8C in hexadecimal. So the output is correct given what you requested (on systems where char is a signed type). So not so much the way the char is stored in memory, but more the way the bits are interpreted. As an unsigned value, the 8-bit pattern 1000 1100 represents -116, and the conversion to short is supposed to preserve this value, rather than preserving the bits.
Your desired output of a hexadecimal 8C corresponds (for a short) to the decimal value 140. To get this value out of 8 bits, the value has to be interpreted as an unsigned 8-bit value (since the largest signed 8-bit value is 127). So the data needs to be interpreted as an unsigned char before it gets expanded to some flavor of short. For a character literal like in the example code, this would look like the following.
std::cout << std::hex << (unsigned short)(unsigned char)('\x3A') << std::endl;
std::cout << std::hex << (unsigned short)(unsigned char)('\x8C') << std::endl;
Most likely, the real code would have variables instead of character literals. If that is the case, then rather than casting to an unsigned char, it might be more convenient to declare the variable to be of unsigned char type. Which is possibly the type you should be using anyway, based on the fact that you want to see its hexadecimal value. Not definitively, but this does suggest that the value is seen simply as a byte of data rather than as a number, and that suggests that an unsigned type is appropriate. Have you looked at std::byte?
One other nifty thought to throw out: the following also gives the desired output as a reasonable facsimile of using an unsigned char variable.
#include <iostream>
unsigned char operator "" _u (char c) { return c; } // Suffix for unsigned char literals
int main()
{
std::cout << std::hex << (unsigned short)('\x3A'_u) << std::endl;
std::cout << std::hex << (unsigned short)('\x8C'_u) << std::endl;
}
A more straightforward approach is to cast a signed char to an unsigned char. In other words, this:
cout << std::hex << (short)(unsigned char)('\x3A') << std::endl;
cout << std::hex << (short)(unsigned char)('\x8C') << std::endl;
produces the expected result:
3a
8c
Not sure this is particularly clear, though.

concatenating a Hexadecimal number with zeros

I have written a simple code to convert a fractional number to 24bit (3 bytes, 6 characters) Hexadecimal number.
Lets say if you enter 0.5, it provides the hexadecimal number as 0x400000.
0.1 = 0xccccd
0.001 = 0x20c5
While the answers are correct, What I'd like to do is preserve the 6 character representation, so i'd like 0.1 to be = 0x0ccccd and
0.001 to be = 0x0020c5.
I thought one possible method would be to convert the hexadecimal result to string and then use strlen to check number of digits and then concatenate the result with the appropriate zeros. The problem I have with this method is I'm not sure how to store the hex result in a variable.
I figured even if I convert the Hex number to string and find the number of zeros to concatenate, the program would be a bit clunky. There just might be a simpler way to achieve what I want to do. I just don't know how.
Hoping someone can show me the way forward. The program I wrote is below.
while(true){
float frac_no;
std::cout << "Enter a fractional number(0-1) or press 0 to exit:";
std::cin >> frac_no;
if(!frac_no){
break;
}
const int max_limit_24 = exp2(23); // The maximum value of 0x7FFFFF(1.0)
float inter_hex;
inter_hex = round(max_limit_24*frac_no);
int int_inter_hex = int(inter_hex);
std::cout << std::hex << "0x" << int_inter_hex << "\n" ;
}
#include <iomanip>
int val = 0x20c5;
std::cout << "0x" << std::setw(6) << std::hex << std::setfill('0') << val << '\n';
If you just need it to have the leading 0s on output. If you do want to store it as a string, you can use an std::stringstream instead of std::cout and get the string from it.

Storing hex in QBytearray, extracting it and converting it to decimal

int dd = 0xA5;
QByteArray p;
p.push_back (0xA5);
qDebug () << "SOP: " << (int)p[0];
This results in -91 whereas 0xA5 stands for 165 in decimal.
How to store hex in QBytearray, extract it and convert it to decimal?
-91 is just a representation of a char value.
char has a range of --127..127. You are storing the value 165, which is larger than 127.
However, unsigned char has a range of 0..255. So in this case you may read your value as an unsigned char:
qDebug() << "SOP: " << (unsigned char)p[0];
In addition you may use QString to display the corresponding hex value:
QString hex = QString("%1").arg((unsigned char)p[0] , 0, 16);
qDebug() << "Hex: " << hex;

Printing out the hex vale of an unsigned char array in C++

I want to print out the hex value of an unsigned char array using the cout function.
The most obvious approach would be something like the following.
unsigned char str[] = "foo bar baz\n";
for(unsigned short int i = 0; i < sizeof(str); i++){
std::cout << std::hex << str[i] << std::dec << ' ';
}
std::cout << std::endl;
Suprisingly, this outputs the following string:
foo bar baz
For some reason this does not print out the proper hexadecimal value of str
How can I cout the proper hex value of str?
To cout the proper hex value of an unsigned char, it will need to be converted to an integer first.
unsigned char str[] = "foo bar baz\n";
for(unsigned short int i = 0; i < sizeof(str); i++){
std::cout << std::hex << (int) str[i] << std::dec << ' ';
}
std::cout << std::endl;
Gives the following output.
66 6f 6f 20 62 61 72 20 62 61 7a 00
Which corresponds with the hex value of each unsigned char in str.
An explaination for this can be found in the following std::hex documentation.
std::hex
Sets the basefield format flag for the str stream to hex.
When basefield is set to hex, integer values inserted into the stream are expressed in hexadecimal base (i.e., radix 16). For input streams, extracted values are also expected to be expressed in hexadecimal base when this flag is set.
http://www.cplusplus.com/reference/ios/hex/