How to log a hex string in c++ with ostringstream? - c++

I'm trying to log hex values to an ostringstream, but it's not working. I'm trying:
unsigned char buf[4];
buf[0] = 0;
buf[1] = 1;
buf[2] = 0xab;
buf[3] = 0xcd;
std::ostringstream e1;
e1 << "0x" << std::setfill('0') << std::setw(3) << std::hex << buf[0] << " " << "0x" << std::setfill('0') << std::setw(3) << std::hex << buf[1] << " " << "0x" << std::setfill('0') << std::setw(3) << std::hex << buf[2] << " " << "0x" << std::setfill('0') << std::setw(3) << std::hex << buf[3];
std::cout << e1.str() << std::endl;
I'm expecting to get something like "0x00 0x01 0xab 0xcd" but instead I get "0x00".
I also tried breaking it up like
e1 << "0x" << std::setfill('0') << std::setw(3) << std::hex << buf[0];
e1 << " ";
e1 << "0x" << std::setfill('0') << std::setw(3) << std::hex << buf[1];
e1 << " ";
e1 << "0x" << std::setfill('0') << std::setw(3) << std::hex << buf[2];
e1 << " ";
e1 << "0x" << std::setfill('0') << std::setw(3) << std::hex << buf[3];
but get the same thing.

I assume, that the mainproblem here is the interpretation of char by your stringstream. Try to cast it to int and everything works like charm:
#include <iostream>
#include <sstream>
#include <iomanip>
using namespace std;
int main()
{
unsigned char buf[4];
buf[0] = 0;
buf[1] = 1;
buf[2] = 0xab;
buf[3] = 0xcd;
ostringstream e1;
for (uint i=0; i< sizeof(buf); ++i)
{
e1 << "0x" << std::setw(2) << std::setfill('0') << std::hex << static_cast<int>(buf[i]) << " ";
}
cout << e1.str() << endl;
return 0;
}
This gives you your desired output:
0x00 0x01 0xab 0xcd

The issue is that the characters are not treated as integers in output stream and so the integer manipulators do not affect their output.
Basically ... replace
unsigned char buf[4];
With
unsigned int buf[4];

This works:
e1 << "0x" << std::setfill('0') << std::setw(2) << std::hex << (int)buf[0]
<< " " << "0x" << std::setfill('0') << std::setw(2) << std::hex << (int)buf[1]
<< " " << "0x" << std::setfill('0') << std::setw(2) << std::hex << (int)buf[2]
<< " " << "0x" << std::setfill('0') << std::setw(2) << std::hex << (int)buf[3];
I've added casts to (int) and change setw(2).

Related

_mm256_movemask_epi8 to uint64_t

Can someone please explain me why tr2 and tr4 show different result:
auto test1 = _mm256_set1_epi8(-1);
uint64_t tr2 = _mm256_movemask_epi8(test1);
uint32_t tr3 = _mm256_movemask_epi8(test1);
uint64_t tr4 = tr3;
_mm256_movemask_epi8(test1) should return int32, so assigning it to int64 should just assign lower bits.
Instead, tr2 prints 0xFFFFFFFFFFFFFFFF and tr4 prints 0x00000000FFFFFFFF
Is there any performance in doing it as tr4?
I'm new to both C++ and intrinsics so maybe I'm missing something obvious.
I'm using Visual Studio 2019 C++ compiler.
As Paul above said, this has to do with assignment of signed/unsigned with bigger integers. Here's an example:
#include <iostream>
#include <iomanip>
int main()
{
int32_t negInt = -1;
uint32_t unInt = static_cast<uint32_t>(negInt);
int64_t negBigInt = static_cast<int64_t>(negInt);
uint64_t unBigInt = static_cast<uint64_t>(negInt);
uint64_t fromUnsigned = static_cast<uint64_t>(unInt);
std::cout << std::hex;
std::cout << "0x" << std::setfill('0') << std::setw(16) << negInt << "\n";
std::cout << "0x" << std::setfill('0') << std::setw(16) << unInt << "\n";
std::cout << "0x" << std::setfill('0') << std::setw(16) << negBigInt << "\n";
std::cout << "0x" << std::setfill('0') << std::setw(16) << unBigInt << "\n";
std::cout << "0x" << std::setfill('0') << std::setw(16) << fromUnsigned << "\n";
}
This prints:
0x00000000ffffffff
0x00000000ffffffff
0xffffffffffffffff
0xffffffffffffffff
0x00000000ffffffff
So Paul is right, but notably this doesn't happen if you assign a signed number to higher bit-width fields.

Convert string into hex format and append "0x " to hex value

I need to convert string to hex format and append "0x" prefix to hex value.
For Example:
Input: std::string s = "0x06A4";
Output: int num = 0x06A4
I have tried this code:
{
std::stringstream ss;
std::string s = "0x06A4";
int num = std::stoi(s, 0, 16);
std::cout << "value in decimal = " << num << '\n';
std::cout << "value in hexadecimal = " << std::hex << num << '\n';
ss << "0x" << std::hex << num << '\n'; //
std::string res = ss.str();
std::cout << "result " << res << '\n';
}
#yogita, std::hex is just one of the configuration you need. You are probably missing the setfill and the setw configuration, as following:
#include <iostream>
#include <sstream>
#include <iomanip>
int main()
{
std::stringstream ss;
std::string s = "0x06A4";
int num = std::stoi(s, nullptr, 16);
std::cout << "value in decimal = " << num << '\n';
std::cout << "value in hexadecimal = " << std::hex << num << '\n';
ss << "0x" << std::hex << std::setfill('0') << std::setw(4) <<num << '\n';
std::string res = ss.str();
std::cout << "result " << res << '\n';
return 0;
}

Convert a hexadecimal char value to its string literal to use on sstream

I need to print the exact hex value of a char variable using C++.
Here is my code:
#include <iostream>
#include <string>
#include <memory>
#include <sstream>
#include <iomanip>
int main()
{
char val = 0xfe;
std::stringstream ss1;
std::stringstream ss2;
ss1 << "#645" << std::setfill('0') << std::setw(2) << std::hex << val;
ss2 << "#645" << std::setfill('0') << std::setw(2) << std::hex << (int) val;
std::cout << ss1.str() << std::endl;
std::cout << ss2.str() << std::endl;
}
And my output:
#6450�
#645fffffffe
And what I expected:
#645FE
quick fix:
unsigned char val = 0xfe;
...
ss2 << "#645" << std::setfill('0') << std::setw(2) << std::hex << std::uppercase <<
(int) val;
or (as proposed by #Kerrek SB):
ss2 << "#645" << std::setfill('0') << std::setw(2) << std::hex << std::uppercase <<
static_cast<unsigned int>(static_cast<unsigned char>(val));
Note that if (on your platform) char defaults to signed char, then
0xfe is a negative number (-2).
In other words, if char is a signed char and sizeof(int) is 4, then
(int)val is 0xfffffffe. That is what you get.
-2 as signed char: 0xfe
-2 as int: 0xfffffffe
I wouldn't bother with streams manipulators when it's easier to do it yourself (exploiting the implicit conversion to unsigned char).
std::string hexb(unsigned char b) {
const char *s="0123456789ABCDEF";
return std::string(s[b>>4]) + s[b&0xf];
}
Usage:
std::cout<<hexb(val);

Generating a new guid string in c++ missing some zeros

I tried using the following code to generate a new guid string of 36 characters, but this sometimes prints only 35 or 34 characters. I suppose this is due to the 'zeros' in the guid, but I am unable to clearly see why. Is there a way I can correct this issue?
#include <string>
#include <sstream>
#include <iostream>
#include <windows.h>
#include <iomanip>
int main()
{
GUID guid;
CoCreateGuid(&guid);
std::ostringstream os;
os.width(8);
os << std::hex << std::setfill('0') << guid.Data1 << '-';
os.width(4);
os << std::hex << std::setfill('0') << guid.Data2 << '-';
os.width(4);
os << std::hex << std::setfill('0') << guid.Data3 << '-';
os.width(2);
os << std::hex << std::setfill('0')
<< static_cast<short>(guid.Data4[0])
<< static_cast<short>(guid.Data4[1])
<< '-'
<< static_cast<short>(guid.Data4[2])
<< static_cast<short>(guid.Data4[3])
<< static_cast<short>(guid.Data4[4])
<< static_cast<short>(guid.Data4[5])
<< static_cast<short>(guid.Data4[6])
<< static_cast<short>(guid.Data4[7]);
std::string s(os.str());
std::cout << s << std::endl;
std::cout << s.length() << std::endl;
}
Sample output:
f6979589-b13c-416d-bf49-1497d99cd88
35
Press any key to continue . . .
You need to directly set field size for any new value you output, like this:
int main()
{
GUID guid;
CoCreateGuid(&guid);
std::ostringstream os;
os.width(8);
os << std::hex << std::setfill('0') << guid.Data1 << '-';
os.width(4);
os << std::hex << std::setfill('0') << guid.Data2 << '-';
os.width(4);
os << std::hex << std::setfill('0') << guid.Data3 << '-';
os.width(2);
os << std::hex << std::setfill('0') << std::setw(2)
<< static_cast<short>(guid.Data4[0]) << std::setw(2)
<< static_cast<short>(guid.Data4[1])
<< '-' << std::setw(2)
<< static_cast<short>(guid.Data4[2]) << std::setw(2)
<< static_cast<short>(guid.Data4[3]) << std::setw(2)
<< static_cast<short>(guid.Data4[4]) << std::setw(2)
<< static_cast<short>(guid.Data4[5]) << std::setw(2)
<< static_cast<short>(guid.Data4[6]) << std::setw(2)
<< static_cast<short>(guid.Data4[7]);
std::string s(os.str());
std::cout << s << std::endl;
std::cout << s.length() << std::endl;
}

Is there a C++ way to format addresses and pointers with iostream?

I have something like
unsigned x = 16;
unsigned* p = &x;
std::cout << std::hex << std::setw(16) << std::setfill('0') << x << std::endl;
std::cout << std::hex << std::setw(16) << std::setfill('0') << p << std::endl;
output:
0000000000000010
000x7fffc35ba784
ostream::operator<< is overloaded for this? I can write this correctly with C, but I was wondering if there is a proper way to do this with iostream.
Use internal like this:
#include <iostream>
#include <iomanip>
int main()
{
unsigned x = 16;
unsigned* p = &x;
std::cout << std::hex << std::setw(16) << std::setfill('0') << x << std::endl;
std::cout << std::hex << std::setw(16) << std::setfill('0') << p << std::endl;
std::cout << std::internal << std::hex << std::setw(16) << std::setfill('0') << p << std::endl;
}
This gives:
0000000000000010
000x7fffd123c1a4
0x007fffd123c1a4