2013-10-02 60 views
6

我有一個包含字符串長度的結構:printf的變量字符串長度說明

typedef struct string { 
    char* data; 
    size_t len; 
} string_t; 

這是所有罰款和花花公子。但是,我希望能夠使用類似於printf的函數來輸出此結構的內容。 data可能沒有nul結束符(或者它在錯誤的地方),所以我不能只使用%s。但%.*s說明符需要一個int,而我有一個size_t

所以現在的問題是,我怎樣才能使用printf輸出字符串?

+7

如果長度不適合'int',那將是一個有趣的'printf',那麼你可以*將一個'size_t'轉換爲'int',只要該值符合... –

+3

@KerrekSB調用:-))應該檢查,因爲它可能會溢出。 – cnicutar

+6

如果'data'可能包含不可打印的字符(如空字符),則根本不需要'%s'。寫一個循環。 –

回答

3

簡單的解決辦法只是使用格式化輸出:

fwrite(x.data, 1, x.len, stdout); 

這實際上是不好的形式,因爲fwrite可能不會寫的一切,所以應該在一個循環中使用;

for (size_t i, remaining = x.len; 
    remaining > 0 && (i = fwrite(x.data, 1, remaining, stdout)) > 0; 
    remaining -= i) { 
} 

確保x.len不超過SIZE_T_MAX大。

+0

+1正準備放棄這個。很難變得更簡單。 – WhozCraig

+0

但是,如果我想使用像snprintf這樣的東西,這不會起作用。在這種情況下,我可以複製數據,我寧願能夠使用其他格式說明符(如'%i')。 –

+0

@drderp:我不明白。你將如何使用'snprintf'?你可以使用'memcpy'來寫入內存位置而不是文件... –

1

如何使用printf輸出字符串?

在單個調用中?你不能以任何有意義的方式,因爲你說你可能在陌生的地方有空終止符。一般來說,如果緩衝區可能包含不可打印的字符,則需要確定在輸出字符串時如何打印(或不打印)這些字符。寫一個循環,測試每個字符,並按照您的邏輯規定打印(或不打印)。

11

假設您的字符串不具有任何內嵌的NULL字符,可以在鑄造後使用%.*s符的size_tint

string_t *s = ...; 
printf("The string is: %.*s\n", (int)s->len, s->data); 

這也是假設您的字符串長度小於INT_MAX。如果您的字符串長度大於INT_MAX,那麼您還有其他問題(首先需要打印20億個字符才需要相當長的時間)。

+0

不太可能,但OP *可能*針對嵌入式或歷史性的16位設備int# – user4815162342

+0

這真的是最好的方式去做這件事嗎?當我第一次注意到這種行爲時,我的第一個問題是「爲什麼它不是'size_t'?」 –

+0

@JeremyRodi:不確定,但我的猜測是它使用'int'而不是'size_t',因爲它是爲了向後兼容在C語言標準化之前編寫的代碼,甚至在'size_t'類型存在之前。 –