2

数値を10進数から16進数(または基数10から基数16)に変換する例をいくつか見てきましたが、実行しようとしていることにはいくつかの制限があります。10進数の文字列を16進数の別の文字列に変換できる必要があります。数値が大きすぎてプリミティブデータ型に収まらない可能性があります。つまり、int、unsigned ints、doubleなどを使用できません。

これにより、このページにリストされているのと同じ計算を実行できるはずです。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);
}

予想される16進数:「16ae5514d07e120126dfbcb3073fddb2b8c」

生成された実際の16進数:「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)

まず、Add2から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;
}

そして、上記のすべてを使用して、1つの任意のベースから別のベースに変換する関数を次に示します。

// 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で「楽しみのために」サンドボックスでほとんどキックしていたコードを使用してハックしたものです。oldBase1回の乗算ではなく、加算を実行する方法はかなり不格好です。Multiply長い乗算を行う関数を作成した場合、これははるかに優れています。

于 2013-03-25T04:22:09.743 に答える
1

各キャラクターを個別に調べても問題を解決することはできません。その理由は、使用する必要のある16進数を決定するときに2文字を考慮する必要があるためです。

たとえば、「12」は「C」として正しく表され、アルゴリズムではそれが考慮されません。

また、左から右ではなく、右から左に読む必要があります

于 2013-03-25T03:16:23.737 に答える