2009-05-26 98 views
8

是否有一種安全的方式在整數的末尾添加數字而不將其轉換爲字符串並且不使用字符串流?將數字追加到int而不轉換爲字符串?

我試圖谷歌答案爲這個和大多數解決方案建議將其轉換爲一個字符串和使用stringstreams,但我想保留它作爲一個整數,以確保數據的完整性,並避免轉換類型。
我也讀了一個解決方案,建議將int乘以10然後加上數字,但是這可能會導致整數溢出。
這是安全嗎?還是有更好的方法來做到這一點?如果我這樣做乘以10並添加數字解決方案,我應該採取什麼預防措施?

回答

25

最好的辦法是乘以10並增加值。你可以做a naive check像這樣:

assert(digit >= 0 && digit < 10); 
newValue = (oldValue * 10) + digit; 
if (newValue < oldValue) 
{ 
    // overflow 
} 
+0

優秀!非常感謝你! – nmuntz 2009-05-26 19:42:25

3

爲了防止溢出:

if ((0 <= value) && (value <= ((MAX_INT - 9)/10))) { 
    return (value * 10) + digit; 
} 

代替MAX_INT的,你可以使用std::numeric_limits<typeof(value)>::max()或相似,支持比INT等類型。

2
 
    assert(digit >= 0 && digit < 10); 
    newvalue = 10 * oldvalue; 
    if (oldvalue < 0) { 
    newvalue -= digit; 
    } else { 
    newvalue += digit; 
    } 

    // check for overflow SGN(oldvalue) == 0 || SGN(newvalue) == SGN(oldvalue) 
2

這裏是一個比被接受作爲一個答案,這也是快一個更好,更防彈實現:

#include <climits> 
#include <cassert> 

unsigned int add_digit(unsigned int val, unsigned int digit) 
{ 
    // These should be computed at compile time and never even be given a memory location 
    static const unsigned int max_no_overflow = (UINT_MAX - 9)/10U; 
    static const unsigned int max_maybe_overflow = UINT_MAX/10U; 
    static const unsigned int last_digit = UINT_MAX % 10; 

    assert(digit >= 0 && digit < 10); 
    if ((val > max_no_overflow) && ((val > max_maybe_overflow) || (digit > last_digit))) { 
     // handle overflow 
    } else { 
     return val * 10 + digit; 
    } 
    assert(false); 
} 

你也應該能夠使成一個內聯函數這一點。第一次比較後,溢出檢查幾乎總是會短路。 &&之後的子句簡直就是這樣(在32位的情況下,二進制補碼整數)在429496729的末尾添加5,但不是6.