2011-10-17 23 views
2

我有一段代碼將整數轉換爲c中的字符串。代碼必須在32位和64位平臺上工作。snprintf,用於整數到字符串轉換C

我解析在一個循環論證,所以我需要的malloc創建緩衝區

int tmp_integer = /*read as integer*/ 
char* tmp_string = malloc(20* sizeof(char)); /*enough room for the biggest integer*/ 
snprintf(tmp_string, 20,"%d",tmp_integer); /*can I avoid using 20 here*/ 
a[i - 1] = tmp_string; /*save the parsed argument for final usage*/ 

我的問題是: 有沒有什麼辦法讓它很好用的snprintf,或者我應該回落到的sprintf 。

我覺得使用snprintf並不是正確的做法,因爲最初我想避免緩衝區溢出,但由於整數的大小已知,所以我認爲它沒用。不過,我想知道這裏的最佳做法是什麼。

回答

2

在這種情況下你是對的。你知道你的號碼不會超過64位,並且你知道這意味着它不會超過20位數。因此,你並不需要使用snprintf

錯誤:最大的無符號的64位數字,你可以爲18,446,744,073,709,551,615這是20位。但是,每個字符串最後都有一個'\0'NUL)字符(因此是nul結尾的字符串術語)。因此,你應該分配字節爲您的陣列,而不是20

+0

其實我決定回去,因爲到的sprintf,snprintf的在我的情況是沒有必要的。當然,我並沒有在代碼中加入21。這是爲了緩解閱讀。 – user763556

+0

太好了。事實上,'snprintf'就派上用場了,當你處理字符串。如果不是這樣,總是有一個容易預測的緩衝區大小的上限,可以計算和足夠的空間分配,所以'sprintf'可以安全地使用。你可能會遇到一些固執地說「永遠不會使用'sprintf'的人,總是使用'snprintf'」。你通常可以忽略它們 – Shahbaz

+0

是的,我真的得出這個結論嘿嘿。 – user763556

2

如果動態分配內存,你可以使用日誌10來計算你的字串需要的地方數:

int tmp_integer = /*read as integer*/ 
int signpadding = 0; 
if tmpinteger < 0 then signpadding = 1; 
int digitcount = (integer)floor(log10(abs(value)))+ 1 + signpadding; 
char* tmp_string = malloc(digitcount * sizeof(char)); 
snprintf(tmp_string, digitcount,"%d",tmp_integer); 
+0

作品負值? –

+0

@Benoît:現在確實如此。 – sum1stolemyname

+0

它不適用於值= 0. 另外,它甚至不是C或我錯了嗎? :) –

0

您可以在臨時緩衝區sprintf和隨後的Alloc良好的尺寸(與回報sprintf),然後將temp複製到緩衝區中。

int tmp_integer = /*read as integer*/ 
static char tmp_string[20]; 
int size = sprintf(tmp_string,"%d",tmp_integer); 
char *myValueString = malloc((size+1)*sizeof(char)); 
a[i - 1] = strcpy(myValueString,tmp_string); 
+0

如果你需要的是結果的大小,可以'snprintf'與0大小NULL,看看它的返回值。參見[這裏](http://stackoverflow.com/questions/10533556/how-do-i-use-strlen-on-a-formatted-string/10533616#10533616)。 – Shahbaz

1

問題變成了神奇的「20」來自哪裏。由於它是神奇的,它應該被表示爲一個符號常量,而不是代碼中重複的整數文字。使用符號常量還具有編譯器的好處做錯誤檢查你:(還要注意如何我放棄了sizeof (char)的事情,因爲這是完全多餘的,(IMO)非常雜亂)

#define MAX_INTEGER_DIGITS (20) 

int value = /* ... */ 
char* tmp_string = malloc(MAX_INTEGER_DIGITS); 
snprintf(tmp_string, MAX_INTEGER_DIGITS, "%d", value); 

從性能角度來看,您可能會取消字符串格式化程序的受保護變體,但由於您無論如何都要調用malloc()(不便宜),因此刪除它可能不是一個好的選擇。

0

這又是一個(也許不是那麼漂亮)轉換成它的基礎上sum1stolemyname代碼片段的方式:

char *convert_int_to_string(int value) 
{ 
    int digitcount; 
    char * tmp_string; 
    int increment = 2; // one for rounding, one for '\0' terminator 
    if(value <0){ 
      increment += 1; // make room for sign 
    } 
    if(0 == value){ 
      tmp_string = malloc(2* sizeof(char)); 
      sprintf(tmp_string, "%u", 0); 
    } 
    else{ 
      digitcount = (int)floor(log10((double)abs(value)))+ increment; 
      tmp_string = malloc(digitcount * sizeof(char)); 
      sprintf(tmp_string, "%d", value); 
    } 
    return tmp_string; 
}