我希望能夠將格式化的字串傳遞給其他函式,比如我的錯誤處理程式:
error_handler(str_format("error code %d in graphics function: %s", code, error));
我的第一個想法是使用 sprintf,但它不回傳結果,所以你必須添加額外的行:
char msg = [100];
sprintf(msg, "error code %d in graphics function: %s", code, error)
error_handler(msg);
如果錯誤訊息大于 msg 的大小,則可能存在問題。
所以我想我可以做一個這樣的包裝函式:
char* str_format (char* format, ...) {
char* output = malloc(100);
va_list args;
va_start(args, format);
vsnprintf(output, 100, format, args);
va_end(args);
return output;
}
但是我仍然有不知道輸出所需大小的問題。所以我想我可以使用 sizeof 來獲取格式的大小和所有 args,但是除非您每次手動傳遞一些 args,否則無法檢測到有多少個 args。我可以讀取格式字串并查找'%'符號并檢測每個占位符和型別,但這似乎太復雜了,只是為了獲取 sprintf 的回傳值。
我知道有一個名為 snprintf 的函式將是安全的并限制字符數,但 c 中沒有 vsnprintf
編輯:#1 將輸出更改為 malloc #2 畢竟有一個 vsnprintf 函式,所以我改成了那個。那么問題就在于是否有比這種包裝函式更簡單的方法。謝謝
有沒有一種簡單的方法可以讓 sprintf 回傳格式化的字串?
uj5u.com熱心網友回復:
通常,您為此使用兩次呼叫vsnprintf——第一次呼叫沒有緩沖區來獲取所需的大小,第二次呼叫來填充緩沖區
char* str_format (char* format, ...) {
va_list args;
va_start(args, format);
int len = vsnprintf(0, 0, format, args);
va_end(args);
char *output = malloc(len 1);
va_start(args, format);
vsnprintf(output, len 1, format, args);
va_end(args);
return output;
}
請注意,呼叫者需要釋放分配的指標(否則會泄漏)
uj5u.com熱心網友回復:
所以我想我可以做一個這樣的包裝函式:
/* !!! DON'T DO THIS !!! */ char* str_format (char* format, ...) { char output[100]; va_list args; va_start(args, format); vsprintf(output, format, args); va_end(args); return output; }
由于多種原因,這很糟糕:首先,正如您所說,您不知道輸出的大小。然而,最重要的是,您不可能回傳本地定義的變數(如output)。
vsnprintf要知道輸出的大小,您可以首先對大小進行“虛擬”呼叫0,根據手冊,它應該簡單地計算并回傳輸出緩沖區所需的大小。
根據回傳有效指標,您可以通過兩種不同的方式進行此作業:
用 分配一個緩沖區
malloc,然后回傳一個指向已分配緩沖區的指標。這可能很煩人,因為您總是需要free()分配的緩沖區,并且由于您想使用函式,就像error_handler(str_format(...))丟失對回傳的緩沖區的參考一樣,所以您要么使用free()它error_handler()并始終假設error_handler()它將采用malloc'd 個物件,要么您需要一個臨時變數。使用
static緩沖區。然而,這存在需要在編譯時以恒定大小預分配的問題。您可以選擇此選項并限制錯誤訊息的大小。這種方法的另一個限制是一次只能格式化一個錯誤(即這不是執行緒安全的),因為您static每次都將覆寫相同的緩沖區。這在 C 庫中很常見,因為它輕松且易于實作,但只有在您有合理大小的錯誤訊息時才真正適用。
選項 1(省略錯誤檢查):
char* str_format(char* format, ...) {
char *buf;
int size;
va_list args;
va_start(args, format);
size = vsnprintf(NULL, 0, format, args) 1;
va_end(args);
buf = malloc(size);
va_start(args, format);
vsnprintf(NULL, size, format, args);
va_end(args);
return buf;
}
選項 2:
char* str_format(char* format, ...) {
static char buf[1024]; // fixed at compile time
va_list args;
va_start(args, format);
vsnprintf(NULL, 1024, format, args);
va_end(args);
return buf;
}
請注意,vsnprintf您需要至少定義以下功能測驗宏之一,如手冊中所述:
#define _XOPEN_SOURCE 500
// or
#define _ISOC99_SOURCE
// or
#define _BSD_SOURCE // old glibc <= 2.19
轉載請註明出處,本文鏈接:https://www.uj5u.com/net/417889.html
標籤:
下一篇:同心方陣
