2013-03-25 77 views
2

我已經看到幾個將數字從十進制轉換爲十六進制(或基數10轉換爲十六進制)的示例,但我對於所嘗試的有幾個限制去做。我需要能夠將十進制數字的字符串轉換爲另一個字符串作爲十六進制數字。該數字可能太大而不適合在任何原始數據類型中 - 即:不能使用整數,無符號整數,雙精度等...在C++中將任意長度的數字從十進制轉換爲十六進制

這應該能夠執行與本頁上列出的相同的計算。 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[] = { "abcdef" }; 
    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()); 
+1

您正在將輸入字符串中數字的ASCII值轉換爲十六進制,而不是輸入字符串表示的實際數字。 – 2013-03-25 03:06:25

+2

這裏有一個提示:你得到的輸出(「313233343837」)看起來像你的輸入號碼字符的ASCII值(在字符串中編碼爲十六進制字節) 0x38 =='8' – 2013-03-25 03:06:29

+1

一般來說,你需要爲這種事情做長時間的劃分,但是當你沒有長時間的劃分時,你可以用一系列的補充來構建它。這是否必須是最佳的?我有一個非最優但簡單的解決方案。 – paddy 2013-03-25 03:35:40

回答

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上踢圍繞「爲了好玩」沙盒。它執行oldBase添加的方式非常笨重,而不是僅執行一次乘法。如果你使用Multiply函數來進行長乘法,這將會好很多。

+0

謝謝,這太棒了! – rkeller 2013-03-25 16:54:49

1

您無法通過將每個角色單獨去解決問題。原因是在決定使用哪個十六進制數字時需要考慮兩個字符。

例如「12」將被正確地表示爲「C」,其中您的算法將不會考慮這一點。

你也應該從右到左,而不是從左到右

相關問題