在尝试在GCC / Linux C ++中复制PHP的bin2hex($s)
和pack('H*',$s)
(在PHP 5.4.3+中称为hex2bin($s)
)时,我似乎已经弄明白了,除了它因为一些奇怪的原因而丢弃标点符号。你能弄清楚我在hex2bin()函数中可能做错了什么吗?我将PHP的bin2hex()与我的比较,它似乎正常工作,所以问题在于hex2bin()。
#include <strings.h>
#include <string>
#include <stdio.h>
#include <stdlib.h>
using namespace std;
string bin2hex(string s) {
int nLen = s.length();
string sOut;
char cBuff[2];
for (int i = 0; i < nLen; i++) {
sprintf(cBuff,"%.2x",s[i]);
sOut.append(cBuff);
cBuff[0] = '\0';
}
return sOut;
}
string hex2bin(string s) {
int nLen = s.length();
string sOut;
char cBuff1[2];
char cBuff2[2];
char cBuff[1];
int n,n1,n2;
for (int i = 0; i <= nLen; i+=2) {
sprintf(cBuff1,"%c",s[i]);
sprintf(cBuff2,"%c",s[i+1]);
n1 = atoi(cBuff1);
n2 = atoi(cBuff2);
n = (n1 * 16) + n2;
sprintf(cBuff,"%c",n);
sOut.append(cBuff);
cBuff[0] = '\0';
cBuff1[0] = '\0';
cBuff2[0] = '\0';
}
return sOut;
}
int main() {
string s;
string sResult;
s = "This is a 123 test.";
sResult = bin2hex(s);
printf("ENCODED: %s\n",sResult.c_str());
sResult = hex2bin(sResult);
printf("UNENCODED: %s\n",sResult.c_str());
return 1;
}
这会发出:
ENCODED: 5468697320697320612031323320746573742e
UNENCODED: This is a 123 test
好吧,袖子卷起来:让我们来看看C ++版本:
std::hex
)hex2bin
可以优化,但我选择“更简单”hex2bin
上添加了一些输入消毒#include <string>
#include <sstream>
#include <iomanip>
std::string bin2hex(std::string const &s) {
std::ostringstream oss;
for (unsigned char ch : s)
oss << std::hex << std::setw(2) << std::setfill('0') << (int) ch;
return oss.str();
}
#include <cassert>
std::string hex2bin(std::string const& s) {
assert(s.length() % 2 == 0);
std::string sOut;
sOut.reserve(s.length()/2);
std::string extract;
for (std::string::const_iterator pos = s.begin(); pos<s.end(); pos += 2)
{
extract.assign(pos, pos+2);
sOut.push_back(std::stoi(extract, nullptr, 16));
}
return sOut;
}
#include <iostream>
int main() {
std::cout << "ENCODED: " << bin2hex("This is a 123 test.") << "\n";
std::cout << "DECODED: " << hex2bin(bin2hex("This is a 123 test.")) << "\n";
}
输出:
ENCODED: 5468697320697320612031323320746573742e
DECODED: This is a 123 test.
除了期限'.'
之外的所有时间你都很幸运:十六进制数字没有使用实际的十六进制值。然而,在你获得2e
期间,你试图使用e
解码atoi("e")
,大致:这将无法正常工作,因为atoi()
需要一个十进制值。您可以使用strtol(str, 0, 16)
来解码十六进制值。
请注意,使用sprintf()
时有一些缓冲区溢出:此函数写入终止空字符。一般来说,你最好去snprintf()
以避免缓冲区溢出。此外,在解码例程中,您可以访问超出字符串末尾的值(使用i <= nLen
和nLen = s.length()
然后访问s[i]
和s[i+1]
)。当然,代码太复杂了:
#include <string>
#include <sstream>
#include <iostream>
#include <iomanip>
std::string bin2hex(std::string s) {
std::ostringstream out;
out << std::hex << std::setfill('0');
for (char c: s) {
out << std::setw(2) << int(c);
}
return out.str();
}
std::string hex2bin(std::string s) {
std::string rc;
int nLen = s.length();
int tmp;
for (int i(0); i + 1 < nLen; i += 2) {
if (std::istringstream(s.substr(i, 2)) >> std::hex >> tmp) {
rc.push_back(tmp);
}
}
return rc;
}
int main() {
std::string s;
std::string sResult;
s = "This is a 123 test.";
sResult = bin2hex(s);
std::cout << "ENCRYPTED: " << sResult << '\n';
sResult = hex2bin(sResult);
std::cout << "UNENCRYPTED: " << sResult << '\n';
return 1;
}
您的代码不能正确转换十六进制数字,因为atoi只能处理十进制数字。试试这个
sprintf(cBuff1,"%c",s[i]);
sprintf(cBuff2,"%c",s[i+1]);
n1 = strtoul(cBuff1, 0, 16);
n2 = strtoul(cBuff2, 0, 16);
你的for循环也应该是
for (int i = 0; i < nLen; i+=2) {
n1 = atoi(cBuff1);
n2 = atoi(cBuff2);
n = (n1 * 16) + n2;
如果cbuff1
,比如"a"
,那么这将不起作用,因为a
不是数字。它适用于'0-9'但不是'a-f'的数字。
您需要将非数字转换为数字值。
将十六进制值字符串转换为字节有很多种方法。我觉得这很不错:
int hexchar(char c)
{
if (c >= '0' && c <= '9') return c - '0';
// if you need to support upper-case hex:
// c = tolower(c);
if (c >= 'a' && c <= 'f') return c - 'a' + 10;
// If we get here, panic
cout << "Error, invalid hex digit:" << c << endl;
return -1;
}
int hexbyte(string s)
{
for(i = 0; i < s.length(); i+=2)
{
char c = hexbyte(s[i]);
c <<= 4;
c += hexbyte(s[i+1];
cout << c;
}
}
尝试这些简单的例程,适用于C和C ++
/*------------------------------------------+
| bin2hex bin2hex bin2hex |
+------------------------------------------*/
static char *bin2hex(unsigned char *s, long L)
{
static char hex[2048];
long i,l=0;
for (i=0; i<L; i++) l+=sprintf(&hex[l], "%02x", 0xFF & (*(s+i)));
hex[l]=0;
return hex;
}
/*------------------------------------------+
| hex2bin hex2bin hex2bin |
+------------------------------------------*/
static char *hex2bin( char *s)
{
static char bin[2048];
unsigned int i,e,l=0,L=strlen(s);
for (i=0; i<L; i+=2) { sscanf(s+i, "%02x",&e); bin[l++]=(char)e; }
bin[l]=0;
return bin;
}