【问题标题】:How do I convert a base64 string to hexadecimal string in C++?如何在 C++ 中将 base64 字符串转换为十六进制字符串?
【发布时间】:2011-06-09 00:20:23
【问题描述】:

我有一个表示 base64 值的字符串。我想将此字符串从 base64 转换为十六进制。我在 Ubuntu 10.10 上使用 C++ 工作。我有以下代码:

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:ffffff6:ffffffdc

这是正确的,除了那些ffffffff。我能做些什么来解决这个问题?如果我想将我的十六进制结果写入std::vector&lt;unsigned char&gt; x,我该怎么办?

【问题讨论】:

  • 请注意,您所说的“六进制结果”是一个字符串,因此将其存储在 std::string 中会更有意义。
  • 重复(同一用户,昨天):base 64 string to hexa string

标签: c++ base64 hex


【解决方案1】:

尝试改用这个演员表:

static_cast<unsigned char>(dec[i])

int 是 32 位宽,而您只想输出 8 位,这就是 char 的宽度。大概std::hex在格式化数字时正在考虑输入类型。 (虽然我不太确定符号扩展的来源,因为您正在转换为无符号类型......)

【讨论】:

  • 如果实现将char 定义为signed,将char 转换为int 将导致符号扩展。
  • @Daniel:即使转换为无符号类型?我不知道从有符号类型转换为无符号类型会导致符号扩展。
  • 是的。当 from 转换为无符号类型时,不会发生符号扩展。
  • @Daniel:啊,源类型决定是否出现符号扩展。我假设仅在将签名转换为签名时才执行符号扩展。
【解决方案2】:

@cdhowie 的帖子几乎是正确的。但是,如果您转换为 char(有符号或无符号),标准流运算符将尝试写出该字符的 ASCII 值。你要么需要另一个演员表:

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

或显式截断值:

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

(在这两种情况下,您的外部int 不需要是unsigned;在第一种情况下,signed int 的宽度足以容纳所有unsigned char 值,而在第二种情况下,您明确地使正值。)

【讨论】:

    【解决方案3】:

    您可以尝试另一种字符串到十六进制的转换方法。我写了两个函数。 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, 64bit, 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();
    
    }
    

    【讨论】:

      【解决方案4】:

      我不确定这是否是最好的解决方案,但我就是这样做的。

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

      【讨论】:

        猜你喜欢
        • 2018-03-01
        • 1970-01-01
        • 2011-11-29
        • 2018-01-31
        • 2022-07-22
        • 1970-01-01
        • 2013-02-07
        • 1970-01-01
        • 2021-04-28
        相关资源
        最近更新 更多