将 unsigned char * 转换为 hexstring
Converting unsigned char * to hexstring
下面的代码采用一个十六进制字符串(每个字节都表示为其对应的十六进制值)
将其转换为 unsigned char * 缓冲区,然后再转换回十六进制字符串。
此代码正在测试从 unsigned char* 缓冲区到十六进制字符串的转换
我需要通过网络将其发送到接收进程。
我选择了十六进制字符串,因为 unsigned char 可以在 0 到 255 的范围内,并且 127 之后没有可打印字符。
下面的代码只是告诉了让我烦恼的部分。它在评论中。
#include <iostream>
#include <sstream>
#include <iomanip>
using namespace std;
// converts a hexstring to corresponding integer. i.e "c0" - > 192
int convertHexStringToInt(const string & hexString)
{
stringstream geek;
int x=0;
geek << std::hex << hexString;
geek >> x;
return x;
}
// converts a complete hexstring to unsigned char * buffer
void convertHexStringToUnsignedCharBuffer(string hexString, unsigned char*
hexBuffer)
{
int i=0;
while(hexString.length())
{
string hexStringPart = hexString.substr(0,2);
hexString = hexString.substr(2);
int hexStringOneByte = convertHexStringToInt (hexStringPart);
hexBuffer[i] = static_cast<unsigned char>((hexStringOneByte & 0xFF)) ;
i++;
}
}
int main()
{
//below hex string is a hex representation of a unsigned char * buffer.
//this is generated by an excryption algorithm in unsigned char* format
//I am converting it to hex string to make it printable for verification pupose.
//and takes the hexstring as inpuit here to test the conversion logic.
string inputHexString = "552027e33844dd7b71676b963c0b8e20";
string outputHexString;
stringstream geek;
unsigned char * hexBuffer = new unsigned char[inputHexString.length()/2];
convertHexStringToUnsignedCharBuffer(inputHexString, hexBuffer);
for (int i=0;i<inputHexString.length()/2;i++)
{
geek <<std::hex << std::setw(2) << std::setfill('0')<<(0xFF&hexBuffer[i]); // this works
//geek <<std::hex << std::setw(2) << std::setfill('0')<<(hexBuffer[i]); -- > this does not work
// I am not able to figure out why I need to do the bit wise and operation with unsigned char "0xFF&hexBuffer[i]"
// without this the conversion does not work for individual bytes having ascii values more than 127.
}
geek >> outputHexString;
cout << "input hex string: " << inputHexString<<endl;
cout << "output hex string: " << outputHexString<<endl;
if(0 == inputHexString.compare(outputHexString))
cout<<"hex encoding successful"<<endl;
else
cout<<"hex encoding failed"<<endl;
if(NULL != hexBuffer)
delete[] hexBuffer;
return 0;
}
// output
// can some one explain ? I am sure its something silly that I am missing.
unsigned char
的输出类似于 char
的输出,这显然不是 OP 所期望的。
我在 coliru 上测试了以下内容:
#include <iomanip>
#include <iostream>
int main()
{
std::cout << "Output of (unsigned char)0xc0: "
<< std::hex << std::setw(2) << std::setfill('0') << (unsigned char)0xc0 << '\n';
return 0;
}
并得到:
Output of (unsigned char)0xc0: 0�
这是从可用运算符中选择的 std::ostream::operator<<()
引起的。我查看了 cppreference
找到
template< class Traits >
basic_ostream<char,Traits>& operator<<( basic_ostream<char,Traits>& os,
unsigned char ch );
前者(在 M.M 的帮助下)。
OP 建议修复:按位并使用 0xff
,这似乎有效。在 coliru.com 中检查:
#include <iomanip>
#include <iostream>
int main()
{
std::cout << "Output of (unsigned char)0xc0: "
<< std::hex << std::setw(2) << std::setfill('0') << (0xff & (unsigned char)0xc0) << '\n';
return 0;
}
输出:
Output of (unsigned char)0xc0: c0
真的,这似乎行得通。为什么?
0xff
是一个 int
常量(严格来说:一个 integer literal)并且类型为 int
。因此,按位 And 也将 (unsigned char)0xc0
提升为 int
,产生类型 int
的结果,因此,应用 int
的 std::ostream::operator<<
.
这是解决这个问题的一个选项。我可以提供另一个 - 只需将 unsigned char
转换为 unsigned
.
unsigned char
到 int
的提升引入了可能的符号位扩展(在这种情况下是不希望的),当 unsigned char
转换为时不会发生这种情况unsigned
。 unsigned
的输出流运算符也提供了预期的输出:
#include <iomanip>
#include <iostream>
int main()
{
std::cout << "Output of (unsigned char)0xc0: "
<< std::hex << std::setw(2) << std::setfill('0') << (unsigned)(unsigned char)0xc0 << '\n';
const unsigned char c = 0xc0;
std::cout << "Output of unsigned char c = 0xc0: "
<< std::hex << std::setw(2) << std::setfill('0') << (unsigned)c << '\n';
return 0;
}
输出:
Output of (unsigned char)0xc0: c0
Output of unsigned char c = 0xc0: c0
C++20 方式:
unsigned char* data = new unsigned char[]{ "Hello world\n\t\r[=10=]" };
std::size_t data_size = sizeof("Hello world\n\t\r[=10=]") - 1;
auto sp = std::span(data, data_size );
std::transform( sp.begin(), sp.end(),
std::ostream_iterator<std::string>(std::cout),
[](unsigned char c) -> std::string {
return std::format("{:02X}", int(c));
});
或者如果您想将结果存储到字符串中:
std::string result{};
result.reserve(size * 2 + 1);
std::transform( sp.begin(), sp.end(),
std::back_inserter(result),
[](unsigned char c) -> std::string {
return std::format("{:02X}", int(c));
});
Output:
48656C6C6F20776F726C640A090D00
下面的代码采用一个十六进制字符串(每个字节都表示为其对应的十六进制值) 将其转换为 unsigned char * 缓冲区,然后再转换回十六进制字符串。 此代码正在测试从 unsigned char* 缓冲区到十六进制字符串的转换 我需要通过网络将其发送到接收进程。 我选择了十六进制字符串,因为 unsigned char 可以在 0 到 255 的范围内,并且 127 之后没有可打印字符。 下面的代码只是告诉了让我烦恼的部分。它在评论中。
#include <iostream>
#include <sstream>
#include <iomanip>
using namespace std;
// converts a hexstring to corresponding integer. i.e "c0" - > 192
int convertHexStringToInt(const string & hexString)
{
stringstream geek;
int x=0;
geek << std::hex << hexString;
geek >> x;
return x;
}
// converts a complete hexstring to unsigned char * buffer
void convertHexStringToUnsignedCharBuffer(string hexString, unsigned char*
hexBuffer)
{
int i=0;
while(hexString.length())
{
string hexStringPart = hexString.substr(0,2);
hexString = hexString.substr(2);
int hexStringOneByte = convertHexStringToInt (hexStringPart);
hexBuffer[i] = static_cast<unsigned char>((hexStringOneByte & 0xFF)) ;
i++;
}
}
int main()
{
//below hex string is a hex representation of a unsigned char * buffer.
//this is generated by an excryption algorithm in unsigned char* format
//I am converting it to hex string to make it printable for verification pupose.
//and takes the hexstring as inpuit here to test the conversion logic.
string inputHexString = "552027e33844dd7b71676b963c0b8e20";
string outputHexString;
stringstream geek;
unsigned char * hexBuffer = new unsigned char[inputHexString.length()/2];
convertHexStringToUnsignedCharBuffer(inputHexString, hexBuffer);
for (int i=0;i<inputHexString.length()/2;i++)
{
geek <<std::hex << std::setw(2) << std::setfill('0')<<(0xFF&hexBuffer[i]); // this works
//geek <<std::hex << std::setw(2) << std::setfill('0')<<(hexBuffer[i]); -- > this does not work
// I am not able to figure out why I need to do the bit wise and operation with unsigned char "0xFF&hexBuffer[i]"
// without this the conversion does not work for individual bytes having ascii values more than 127.
}
geek >> outputHexString;
cout << "input hex string: " << inputHexString<<endl;
cout << "output hex string: " << outputHexString<<endl;
if(0 == inputHexString.compare(outputHexString))
cout<<"hex encoding successful"<<endl;
else
cout<<"hex encoding failed"<<endl;
if(NULL != hexBuffer)
delete[] hexBuffer;
return 0;
}
// output
// can some one explain ? I am sure its something silly that I am missing.
unsigned char
的输出类似于 char
的输出,这显然不是 OP 所期望的。
我在 coliru 上测试了以下内容:
#include <iomanip>
#include <iostream>
int main()
{
std::cout << "Output of (unsigned char)0xc0: "
<< std::hex << std::setw(2) << std::setfill('0') << (unsigned char)0xc0 << '\n';
return 0;
}
并得到:
Output of (unsigned char)0xc0: 0�
这是从可用运算符中选择的 std::ostream::operator<<()
引起的。我查看了 cppreference
找到
template< class Traits >
basic_ostream<char,Traits>& operator<<( basic_ostream<char,Traits>& os,
unsigned char ch );
前者(在 M.M 的帮助下)。
OP 建议修复:按位并使用 0xff
,这似乎有效。在 coliru.com 中检查:
#include <iomanip>
#include <iostream>
int main()
{
std::cout << "Output of (unsigned char)0xc0: "
<< std::hex << std::setw(2) << std::setfill('0') << (0xff & (unsigned char)0xc0) << '\n';
return 0;
}
输出:
Output of (unsigned char)0xc0: c0
真的,这似乎行得通。为什么?
0xff
是一个 int
常量(严格来说:一个 integer literal)并且类型为 int
。因此,按位 And 也将 (unsigned char)0xc0
提升为 int
,产生类型 int
的结果,因此,应用 int
的 std::ostream::operator<<
.
这是解决这个问题的一个选项。我可以提供另一个 - 只需将 unsigned char
转换为 unsigned
.
unsigned char
到 int
的提升引入了可能的符号位扩展(在这种情况下是不希望的),当 unsigned char
转换为时不会发生这种情况unsigned
。 unsigned
的输出流运算符也提供了预期的输出:
#include <iomanip>
#include <iostream>
int main()
{
std::cout << "Output of (unsigned char)0xc0: "
<< std::hex << std::setw(2) << std::setfill('0') << (unsigned)(unsigned char)0xc0 << '\n';
const unsigned char c = 0xc0;
std::cout << "Output of unsigned char c = 0xc0: "
<< std::hex << std::setw(2) << std::setfill('0') << (unsigned)c << '\n';
return 0;
}
输出:
Output of (unsigned char)0xc0: c0
Output of unsigned char c = 0xc0: c0
C++20 方式:
unsigned char* data = new unsigned char[]{ "Hello world\n\t\r[=10=]" };
std::size_t data_size = sizeof("Hello world\n\t\r[=10=]") - 1;
auto sp = std::span(data, data_size );
std::transform( sp.begin(), sp.end(),
std::ostream_iterator<std::string>(std::cout),
[](unsigned char c) -> std::string {
return std::format("{:02X}", int(c));
});
或者如果您想将结果存储到字符串中:
std::string result{};
result.reserve(size * 2 + 1);
std::transform( sp.begin(), sp.end(),
std::back_inserter(result),
[](unsigned char c) -> std::string {
return std::format("{:02X}", int(c));
});
Output:
48656C6C6F20776F726C640A090D00