2

我已经看到了几个将数字从十进制转换为十六进制(或以 10 为底为 16)的示例,但我对我正在尝试做的事情有一些限制。我需要能够将带有十进制数字的字符串转换为另一个字符串作为十六进制数字。该数字可能太大而无法容纳在任何原始数据类型中 - 即:不能使用整数、无符号整数、双精度数等...

这应该能够执行与此页面上列出的相同的计算。http://www.kaagaard.dk/service/convert.htm

我试过这个,但它对我没有用。

对函数的调用:

const int maxLen = 256;
char destination[maxLen];
int retVal = convertBase(destination, maxLen, "123487032174829820348320429437483266812812");

函数定义:

int convertBase(char* dest, int maxDestLength, const char* inputInBase10)
{
    const char lookUpTable[] = { "0123456789abcdef" };
    const std::string input = inputInBase10;
    const unsigned int inputSize = input.length();

    std::string output;
    output.reserve(2 * inputSize);

    for(unsigned int i = 0; i < inputSize; ++i)
    {
        const unsigned char c = input[i];
        output.push_back(lookUpTable[c >> 4]);  
        output.push_back(lookUpTable[c & 15]);
    }

    if(output.length() < maxDestLength)
        strcpy_s(dest, output.length(), output.c_str());
    else
        strcpy_s(dest, maxDestLength, output.c_str());

    cout << dest << endl;

    return strlen(dest);
}

预期的十六进制数:“16ae5514d07e120126dfbcb3073fddb2b8c”

生成的实际十六进制数:“313233343837303332313734383239383230333438333230343239343337343833323636383132383132”

另外,当传递回 char* 时,我不断收到一个错误,即缓冲区太小(在下面重复)

    if(output.length() < maxDestLength)
        strcpy_s(dest, output.length(), output.c_str());
    else
        strcpy_s(dest, maxDestLength, output.c_str());
4

2 回答 2

3

所以如果你急于得到任何东西,并且不太关心效率,试试这个。我已经修改了我为以下 SO 问题编写的函数:c++ string (int) + string (int)

首先,我修改了Add函数以适用于 2 到 36 之间的任何基数:

const int MIN_BASE = 2;
const int MAX_BASE = 36;

static bool tablesInitialised = false;
static char tblIntToChar[MAX_BASE] = {0};
static int tblCharToInt[256] = {0};

void InitTables()
{
    if( tablesInitialised ) return;

    for( int i = 0; i < 10; i++ ) {
        tblIntToChar[i] = '0' + i;
        tblCharToInt[tblIntToChar[i]] = i;
    }

    for( int i = 0; i < 26; i++ ) {
        tblIntToChar[i+10] = 'a' + i;
        tblCharToInt['a' + i] = i + 10;
        tblCharToInt['A' + i] = i + 10;
    }

    tablesInitialised = true;
}


// Adds two numbers using long addition.
string Add( const string& a, const string& b, int base=10 )
{
    InitTables();
    if( base > MAX_BASE || base < MIN_BASE ) return "";

    // Reserve storage for the result.
    string result;
    result.reserve( 1 + std::max(a.size(), b.size()) );

    // Column positions and carry flag.
    int apos = a.size();
    int bpos = b.size();
    int carry = 0;

    // Do long arithmetic.
    while( carry > 0 || apos > 0 || bpos > 0 )
    {
        if( apos > 0 ) carry += tblCharToInt[(unsigned char)a[--apos]];
        if( bpos > 0 ) carry += tblCharToInt[(unsigned char)b[--bpos]];
        result.push_back(tblIntToChar[carry%base]);
        carry /= base;
    }

    // The result string is backwards.  Reverse and return it.
    reverse( result.begin(), result.end() );
    return result;
}


// Converts a single value to some base, intended for single-digit conversions.
string AsBase( int number, int base )
{
    InitTables();
    if( number <= 0 ) return "0";
    string result;
    while( number > 0 ) {
        result += tblIntToChar[number%base];
        number /= base;
    }
    reverse( result.begin(), result.end() );
    return result;
}

并且,使用上述所有内容,这是一个从一个任意基数转换为另一个基数的函数:

// Converts a number from one base to another.
string ConvertBase( const string & number, int oldBase, int newBase )
{
    InitTables();
    string result;

    for( unsigned digit = 0; digit < number.size(); digit++ )
    {
        int value = tblCharToInt[(unsigned char)number[digit]];
        if( result.empty() )
        {
            result = AsBase( value, newBase );
        }
        else 
        {
            string temp = result;
            for( int i = 1; i < oldBase; i++ ) {
                temp = Add( result, temp, newBase );
            }
            result = Add( temp, AsBase(value, newBase), newBase );
        }
    }

    return result;
}

这只是我使用我的 StackOverflow 'for fun' 沙箱中的代码破解的东西。它执行oldBase加法而不是仅执行一次乘法的方式非常笨拙。Multiply如果你创建一个函数来做长乘法,这会好很多。

于 2013-03-25T04:22:09.743 回答
1

您无法通过单独检查每个字符来解决问题。原因是在决定需要使用哪个十六进制数字时需要考虑两个字符。

例如,“12”将正确表示为“C”,而您的算法不会考虑到这一点。

你也应该从右到左而不是从左到右阅读

于 2013-03-25T03:16:23.737 回答