简体   繁体   中英

How do I convert a base64 string to hexadecimal string in C++?

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM