Как мне преобразовать строку base64 в шестнадцатеричную строку в C ++? - PullRequest
2 голосов
/ 14 января 2011

У меня есть строка, которая представляет значение в base64. Я хочу преобразовать эту строку из base64 в шестнадцатеричное. Я работаю в C ++ на Ubuntu 10.10. У меня есть следующий код:

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;

Результат:

0c: ffffffd4: 30: 4a: 29: ffffffdf: 39: 44: ffffff92: 59: ffffffdf: ffffff94: ffffffd3: ffffff8a: fffffff6: ffffffdc

Это правильно, кроме этих ffffffff. Что я могу сделать, чтобы это исправить? Если я хочу, чтобы мой шестнадцатеричный результат был записан в std::vector<unsigned char> x, что мне нужно делать?

Ответы [ 4 ]

2 голосов
/ 14 января 2011

@ Пост cdhowie почти правильный. Однако, если вы приведете к char (со знаком или без знака), стандартные операторы потока попытаются записать значение ASCII этого символа. Вам также понадобится другой состав:

static_cast<int>(static_cast<unsigned char>(dec[i]))

или для явного усечения значения:

(static_cast<int>(dec[i]) & 0xFF)

(В обоих случаях ваш внешний int не обязательно должен быть unsigned; в первом случае signed int достаточно широк, чтобы вместить все значения unsigned char, а во втором вы явно делаете значение положительное.)

2 голосов
/ 14 января 2011

Вы можете попробовать другой метод преобразования строки в гекс. Я написал две функции. Str_to_hex - это мой метод. str_to_hex2 - это ваш. Я опускаю кодировку base64. И тогда я вызвал 1M раз мою функцию и вашу. Время выполнения для str_to_hex составляет

time ./a.out 

real    0m0.365s
user    0m0.360s
sys 0m0.010s

И время выполнения для str_to_hex2:

time ./a.out 

real    0m3.253s
user    0m3.220s
sys 0m0.000s

Ubuntu 10.04, 64-битная версия, g ++ 4.4.3, опция -O3.

Код программы тестирования ниже.

#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();

}
2 голосов
/ 14 января 2011

Попробуйте использовать вместо этого приведение:

static_cast<unsigned char>(dec[i])

int имеет ширину 32 бита, и вы хотите вывести только 8 бит, то есть ширину char.Предположительно std::hex учитывает тип ввода при форматировании числа.(Хотя я не совсем уверен, откуда исходит расширение знака, так как вы приводите тип без знака ...)

0 голосов
/ 04 сентября 2017

Я не уверен, что это лучшее решение, но я так и сделал.

#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;
}
...