I have a string that represents a value in base64. I want to convert this string from base64 to hexadecimal. I'm working in C++ on Ubuntu 10.10. I have the following code:
std::string ssir = "DNQwSinfOUSSWd+U04r23A==";
std::string dec=(base64_decode(ssir));
std::stringstream ss;
for (int i=0; i<dec.size(); ++i) {
if (i != 0) ss << ':';
ss << std::hex << std::setw(2) << std::setfill('0') << static_cast<unsigned int>(dec[i]);//(int)(dec[i]);
}
std::string res;
res= ss.str();
cout<<"the ress is: "<<res<<std::endl;
The result is:
0c:ffffffd4:30:4a:29:ffffffdf:39:44:ffffff92:59:ffffffdf:ffffff94:ffffffd3:ffffff8a:fffffff6:ffffffdc
It is correct, besides those ffffffff. What can I do to fix this? If I want my hexadecimal result to be written to a std::vector<unsigned char> x
, what do I have to do?
Try using this cast instead:
static_cast<unsigned char>(dec[i])
int
is 32 bits wide and you only want to output 8 bits, which is how wide char
is. Presumably std::hex
is considering the input type when formatting the number. (Though I'm not quite sure where the sign extension is coming from, since you are casting to an unsigned type...)
@cdhowie's post is nearly correct. However, if you cast to a char
(signed or unsigned), the standard stream operators will attempt to write out the ASCII value of that character. You will either need another cast:
static_cast<int>(static_cast<unsigned char>(dec[i]))
or to explicitly truncate the value:
(static_cast<int>(dec[i]) & 0xFF)
(In both cases, your outer int
does not need to be unsigned
; in the first case, signed int
is wide enough to hold all unsigned char
values, and in the second, you are explicitly making the value positive.)
You can try another string to hex conversion method. I wrote two functions. The str_to_hex - is my method. str_to_hex2 - is your. I omit base64 encoding. And then I invoked 1M times my function and your. The execution time for str_to_hex is
time ./a.out
real 0m0.365s
user 0m0.360s
sys 0m0.010s
And the execution time for str_to_hex2 is:
time ./a.out
real 0m3.253s
user 0m3.220s
sys 0m0.000s
Ubuntu 10.04, 64bit, g++ 4.4.3, -O3 option.
The code of testing programm is below.
#include <string>
#include <iostream>
#include <sstream>
#include <iomanip>
void str_to_hex() {
std::string ssir = "DNQwSinfOUSSWd+U04r23A==";
static const char *hex = "0123456789ABCDEF";
std::string result;
result.reserve(ssir.size() * 3);
for (std::string::const_iterator i = ssir.begin(), end = ssir.end(); i != end; ++i) {
if (i != ssir.begin())
result.push_back(':');
result.push_back(hex[*i >> 4]);
result.push_back(hex[*i & 0xf]);
}
}
void str_to_hex2() {
std::string ssir = "DNQwSinfOUSSWd+U04r23A==";
std::stringstream ss;
for (int i=0; i<ssir.size(); ++i) {
if (i != 0) ss << ':';
ss << std::hex << std::setw(2) << std::setfill('0') << static_cast<unsigned int>(ssir[i] & 0xff);
}
}
int main() {
for (int i = 0; i < 1000000; ++i)
str_to_hex();
}
I am not sure if this is the best solution but this is how I did it.
#include <vector>
#include <bitset>
#include <string>
//hex->dec->bin8->bin6->dec->base64table
//HexToDec
unsigned int HexToDec(std::string hexInput)
{
//initlize variables
const int HexBaseASCCI = 48;
const int HexBase = 16;
size_t hexCharPlace = hexInput.size() -1;
int result = 0;
//reading the hexInput
for (int i = 0; i < hexInput.size(); i++)
{
char hexChar = hexInput.at(i);
int dec = 0;
//Finde the equvilcey of the char hex u read from the HexNum string
if (hexChar>='0' && hexChar<='9'){dec = (int)hexChar - HexBaseASCCI;}
else
{ switch (hexChar)
{ case ('A') :
case ('a') : {dec = 10; break;}
case ('B') :
case ('b') : {dec = 11; break;}
case ('C') :
case ('c') : {dec = 12; break;}
case ('D') :
case ('d') : {dec = 13; break;}
case ('E') :
case ('e') : {dec = 14; break;}
case ('F') :
case ('f') : {dec = 15; break;}
case ('X') :
case ('x') : {dec = 0; break;}
default : {
std::string msg ("is not in hex format");
throw std::logic_error(msg);};
}
}
//calculating the final dec
result += dec * pow(HexBase,hexCharPlace);
hexCharPlace--;
}
return result;
}
//HexToDec vector version
std::vector<unsigned int> HexToDec(std::vector<std::string> hex)
{
std::vector<unsigned int> dec;
for( auto x : hex){
dec.push_back(HexToDec(x));
}
return dec;
}
//BreakHexStringIntoGroups TODO .. needs to imporve
std::vector<std::string> BreakHexStringIntoGroups(std::string hexInput, unsigned long lengthOfBreaks)
{
std::vector<std::string> hexGroups;
if(!(hexInput.size() % 2)){
for (auto index(0); index < hexInput.size(); index+=lengthOfBreaks )
{
hexGroups.push_back(hexInput.substr(index,lengthOfBreaks));
}
}
else
{
for (auto index(0); index < hexInput.size()-1; index+=lengthOfBreaks )
{
hexGroups.push_back(hexInput.substr(index,lengthOfBreaks));
}
hexGroups.push_back(hexInput.substr(hexInput.size()-1));
}
return hexGroups;
}
//DecTo8BitsBin
std::vector<std::string> DecTo8BitsBin(std::vector<unsigned int> dec)
{
std::vector<std::string> bin;
for (auto x: dec)
{
bin.push_back(std::bitset<8>(x).to_string());
}
return bin;
}
//FuseStringVector
std::string FuseStringVector(std::vector<std::string> vec)
{
std::string res;
for (auto str: vec)
{
res+=str;
}
return res;
}
//BreakBinStringInto6BitsGroups TODO .. needs to imporve
std::vector<std::string> BreakBinStringInto6BitsGroups(std::string longBin){
std::vector<std::string> res;
if (!(longBin.size() % 6))
{
for (unsigned int i(0) ; i < longBin.size(); i+=6){
res.push_back(longBin.substr(i,6));
}
}
else
{
unsigned int max6AlignedIndex = (longBin.size() / 6)*6;
unsigned int paddingZeros = 6 -(longBin.size() % 6);
for (unsigned int i(0) ; i < max6AlignedIndex; i+=6){
res.push_back(longBin.substr(i,6));
}
res.push_back(longBin.substr(max6AlignedIndex) + std::string(paddingZeros, '0'));
}
return res;
}
//Bin6BitsToDec
unsigned int Bin6BitsToDec(std::string bin6Bit){
unsigned int decimalNumber(0), i(0), remainder(0);
unsigned int n (std::stoi(bin6Bit));
while (n!=0)
{
remainder = n%10;
n /= 10;
decimalNumber += remainder*pow(2,i);
++i;
}
return decimalNumber;
}
//Bin6BitsToDec vector
std::vector<unsigned int> Bin6BitsToDec(std::vector<std::string> bin6Bits)
{
std::vector<unsigned int> dec;
for(auto bin: bin6Bits)
{
dec.push_back(Bin6BitsToDec(bin));
}
return dec;
}
//DecToBase64
std::vector<char> DecToBase64(std::vector<unsigned int> dec)
{
const std::string base64Table("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/");
std::vector<char> res;
for(auto x: dec)
{
res.push_back(base64Table.at(x));
}
return res;
}
//FuseCharVector
std::string FuseCharVector(std::vector<char> vec)
{
return std::string(vec.begin(), vec.end());
}
std::string HexToBase64(std::string hex){
std::vector<std::string> brokenHexGroups(BreakHexStringIntoGroups(hex,2));
std::vector<unsigned int> brokenHexGroupsInDec(HexToDec(brokenHexGroups));
std::vector<std::string> bin8bits= DecTo8BitsBin(brokenHexGroupsInDec);
std::string fusedBin8bits = FuseStringVector(bin8bits);
std::vector<std::string> bin6Bits = BreakBinStringInto6BitsGroups(fusedBin8bits);
std::vector<unsigned int> bin6BitsInDec(Bin6BitsToDec(bin6Bits));
std::vector<char> decToBase64Chars = DecToBase64(bin6BitsInDec);
std::string finalString = FuseCharVector(decToBase64Chars);
return finalString;
}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.