2

有人知道任何常用的 C++ 库,它提供了从基数 10 到基数 32 编码和解码数字的方法,反之亦然?

谢谢,斯特凡诺

4

5 回答 5

4

[更新]显然,C++ std::setbase() IO 操纵器和普通<<>>IO 操作符只处理基数 8、10 和 16,因此对于处理基数 32 是无用的。

所以要解决你的转换问题

  • 以 10/32 为基数表示从某些输入读取到程序中的整数的数字的字符串
  • 将程序中的整数转换为以 10/32 为基数的字符串以输出

您将需要求助于其他功能。

要将包含基本 2..36 表示形式的 C 样式字符串转换为整数,您可以使用#include <cstdlib>& strtol(3)Co. 函数集。

至于将整数转换为具有任意基数的字符串......我找不到一个简单的答案。printf(3)样式格式字符串仅处理基数 8、10、16 AFAICS,就像std::setbase. 任何人?

于 2009-12-16T17:26:14.227 回答
3

您的意思是“base 10 to base 32”,而不是整数到 base32吗?后者似乎更有可能和更有用;默认情况下,标准格式的 I/O 函数在处理整数时会生成以 10 为基数的字符串格式。

对于基数 32 到整数的转换,标准库 strtol() 函数将执行此操作。对于互惠,您不需要库来轻松实现自己的东西(并非所有东西都是乐高积木)。

这是一个例子,不一定是最有效的,但很简单;

#include <cstring>
#include <string>

long b32tol( std::string b32 )
{
    return strtol( b32.c_str(), 0, 32 ) ;
}

std::string itob32( long i )
{
    unsigned long u = *(reinterpret_cast<unsigned long*>)( &i ) ;
    std::string b32 ;

    do
    {
        int d = u % 32 ;
        if( d < 10 )
        {
            b32.insert( 0, 1, '0' + d ) ;
        }
        else
        {
            b32.insert( 0, 1, 'a' + d - 10 ) ;
        }

        u /= 32 ;

    } while( u > 0 );

    return b32 ;
}


#include <iostream>

int main() 
{ 
    long i = 32*32*11 + 32*20 + 5 ; // BK5 in base 32
    std::string b32 = itob32( i ) ;
    long ii = b32tol( b32 ) ;

    std::cout << i << std::endl ;    // Original
    std::cout << b32 << std::endl ;  // Converted to b32
    std::cout << ii << std::endl ;   // Converted back

    return 0 ;
}
于 2009-12-16T18:58:53.700 回答
2

在对原始(现在是旧的)问题的直接回答中,我不知道任何用于在 base32 中编码字节数组或之后再次解码它们的通用库。但是,上周有人向我提出了将 base32 中表示的 SHA1 哈希值解码为其原始字节数组的需求。这是我为此编写的一些 C++ 代码(带有一些值得注意的 Windows/little endian 工件),并用于验证结果。

请注意,与上面 Clifford 的代码相比,如果我没记错的话,它假定 RFC 4648 中提到的“base32hex”字母表,我的代码假定“base32”字母表(“AZ”和“2-7”)。

// This program illustrates how SHA1 hash values in base32 encoded form can be decoded
// and then re-encoded in base16.

#include "stdafx.h"
#include <string>
#include <vector>
#include <iostream>
#include <cassert>

using namespace std;

unsigned char Base16EncodeNibble( unsigned char value )
{
    if( value >= 0 && value <= 9 )
        return value + 48;
    else if( value >= 10 && value <= 15 )
        return (value-10) + 65;
    else //assert(false);
    {
        cout << "Error: trying to convert value: " << value << endl;
    }

    return 42; // sentinal for error condition
}

void Base32DecodeBase16Encode(const string & input, string & output)
{
    // Here's the base32 decoding:

        // The "Base 32 Encoding" section of http://tools.ietf.org/html/rfc4648#page-8
        // shows that every 8 bytes of base32 encoded data must be translated back into 5 bytes
        // of original data during a decoding process. The following code does this.

    int input_len = input.length();
    assert( input_len == 32 );
    const char * input_str = input.c_str();
    int output_len = (input_len*5)/8;
    assert( output_len == 20 );
        // Because input strings are assumed to be SHA1 hash values in base32, it is also assumed
        // that they will be 32 characters (and bytes in this case) in length, and so the output
        // string should be 20 bytes in length.
    unsigned char *output_str = new unsigned char[output_len];

    char curr_char, temp_char;
    long long temp_buffer = 0; //formerly: __int64 temp_buffer = 0;
    for( int i=0; i<input_len; i++ )
    {
        curr_char = input_str[i];
        if( curr_char >= 'A' && curr_char <= 'Z' )
            temp_char = curr_char - 'A';
        if( curr_char >= '2' && curr_char <= '7' )
            temp_char = curr_char - '2' + 26;

        if( temp_buffer )
            temp_buffer <<= 5; //temp_buffer = (temp_buffer << 5);
        temp_buffer |= temp_char;

        // if 8 encoded characters have been decoded into the temp location,
            // then copy them to the appropriate section of the final decoded location
        if( (i>0) && !((i+1) % 8) )
        {
            unsigned char * source = reinterpret_cast<unsigned char*>(&temp_buffer);
            //strncpy(output_str+(5*(((i+1)/8)-1)), source, 5);
            int start_index = 5*(((i+1)/8)-1);
            int copy_index = 4;
            for( int x=start_index; x<(start_index+5); x++, copy_index-- )
                output_str[x] = source[copy_index];
            temp_buffer = 0;

            // I could be mistaken, but I'm guessing that the necessity of copying
            // in "reverse" order results from temp_buffer's little endian byte order.
        }
    }

    // Here's the base16 encoding (for human-readable output and the chosen validation tests):

        // The "Base 16 Encoding" section of http://tools.ietf.org/html/rfc4648#page-10
        // shows that every byte original data must be encoded as two characters from the
        // base16 alphabet - one charactor for the original byte's high nibble, and one for
        // its low nibble.

    unsigned char out_temp, chr_temp;
    for( int y=0; y<output_len; y++ )
    {
        out_temp = Base16EncodeNibble( output_str[y] >> 4 ); //encode the high nibble
        output.append( 1, static_cast<char>(out_temp) );
        out_temp = Base16EncodeNibble( output_str[y] & 0xF ); //encode the low nibble
        output.append( 1, static_cast<char>(out_temp) );
    }

    delete [] output_str;
}

int _tmain(int argc, _TCHAR* argv[])
{
    //string input = "J3WEDSJDRMJHE2FUHERUR6YWLGE3USRH";
    vector<string> input_b32_strings, output_b16_strings, expected_b16_strings;

    input_b32_strings.push_back("J3WEDSJDRMJHE2FUHERUR6YWLGE3USRH");
    expected_b16_strings.push_back("4EEC41C9238B127268B4392348FB165989BA4A27");
    input_b32_strings.push_back("2HPUCIVW2EVBANIWCXOIQZX6N5NDIUSX");
    expected_b16_strings.push_back("D1DF4122B6D12A10351615DC8866FE6F5A345257");
    input_b32_strings.push_back("U4BDNCBAQFCPVDBL4FBG3AANGWVESI5J");
    expected_b16_strings.push_back("A7023688208144FA8C2BE1426D800D35AA4923A9");

    // Use the base conversion tool at http://darkfader.net/toolbox/convert/
    // to verify that the above base32/base16 pairs are equivalent.

    int num_input_strs = input_b32_strings.size();
    for(int i=0; i<num_input_strs; i++)
    {
        string temp;
        Base32DecodeBase16Encode(input_b32_strings[i], temp);
        output_b16_strings.push_back(temp);
    }

    for(int j=0; j<num_input_strs; j++)
    {
        cout << input_b32_strings[j] << endl;
        cout << output_b16_strings[j] << endl;
        cout << expected_b16_strings[j] << endl;

        if( output_b16_strings[j] != expected_b16_strings[j] )
        {
            cout << "Error in conversion for string " << j << endl;
        }
    }

    return 0;
}
于 2010-09-21T20:59:05.650 回答
1

我不知道有任何专门用于 base32 编码的常用库,但 Crypto++ 包含一个公共域 base32 编码器和解码器

于 2009-12-16T17:14:30.493 回答
0

我不使用cpp,如果我错了,请纠正我。我编写这段代码是为了从 C# 中翻译它,以免我的熟人遇到麻烦。我用来创建这些方法的原始来源在另一个帖子上,这里是 stackoverflow: https ://stackoverflow.com/a/10981113/13766753

话虽如此,这是我的解决方案:

#include <iostream>
#include <math.h>

class Base32 {
    public:
        static std::string dict;
        static std::string encode(int number) {
            std::string result = "";
            bool negative = false;
            if (number < 0) {
                negative = true;
            }

            number = abs(number);
            do {
                result = Base32::dict[fmod(floor(number), 32)] + result;
                number /= 32;
            } while(number > 0);

            if (negative) {
                result = "-" + result;
            }
    
            return result;
        }

        static int decode(std::string str) {
            int result = 0;
            int negative = 1;
            if (str.rfind("-", 0) == 0) {
                negative = -1;
                str = str.substr(1);
            }

            for(char& letter : str) {
                result += Base32::dict.find(letter);
                result *= 32;
            }

            return result / 32 * negative;
        }
};

std::string Base32::dict = "0123456789abcdefghijklmnopqrstuvwxyz";

int main() {
    std::cout << Base32::encode(0) + "\n" << Base32::decode(Base32::encode(0)) << "\n";

    return 0;
}
于 2022-01-20T16:14:16.737 回答