[英]_vscwprintf on Mac OS X/Linux
我正在 Mac OS X 上移植一個為 Windows 編寫的應用程序。
在這個應用程序中,有很多 _vscwprintf 和 _vscprintf 的實例。
這個問題幫助我在 Mac OS X 上實現 _vsprintf。但是 _vswprintf 的相同技術不起作用。
任何人都可以在 Mac OS X 上提供 _vscwprintf 的替代方案嗎? 或者有任何等效的方法嗎?
Microsoft將這些函數描述為返回格式化字符串時將使用的字符數 - 請注意,它們被記錄為不包括空終止符。
int _vscprintf(
const char *format,
va_list argptr
);
int _vscwprintf(
const wchar_t *format,
va_list argptr
);
因此,可以使用vsprintf()
和vswprintf()
模擬這些函數:
int _vscprintf(const char *format, va_list argptr)
{
return(vsnprintf(0, 0, format, argptr));
}
int _vscwprintf(const wchar_t *format, va_list argptr) { return(vswprintf(0, 0, format, argptr)); }
是否刪除前導下划線取決於您; 我會。
請注意,上面的_vscwprintf()
實現是有缺陷的; 請參閱下面的代碼。
vscprintf()
和scprintf()
道歉:我在需要寫vsnprintf()
vsprintf()
地方寫了vsprintf()
(現在在上面的代碼中修復了); 但是, vswprintf()
已經具有緩沖區長度的更安全接口,因此沒有vsnwprintf()
。 我更喜歡在發布之前(或之后不久)測試編譯代碼是有原因的——幾天來沒有足夠的資金這樣做很令人厭煩。
這是vscprintf()
(和scprintf()
)的scprintf()
:
#include <stdio.h>
#include <stdarg.h>
extern int vscprintf(const char *format, va_list argptr);
extern int scprintf(const char *format, ...);
int vscprintf(const char *format, va_list argptr)
{
return(vsnprintf(0, 0, format, argptr));
}
int scprintf(const char *format, ...)
{
va_list args;
va_start(args, format);
int rc = vscprintf(format, args);
va_end(args);
return rc;
}
int main(void)
{
int l = scprintf("%-8s %8d\n", "abc", 123);
if (l > 0)
{
char buffer[l+1];
int n = snprintf(buffer, sizeof(buffer), "%-8s %8d\n", "abc", 123);
printf("%d = %d: %s", l, n, buffer);
}
return 0;
}
輸出:
18 = 18: abc 123
vscwprintf()
和scwprintf()
事實證明,模擬_vscwprintf()
更難,因為vswprintf()
函數不如vsnprintf()
函數有用。 具體來說,如果格式化字符串不適合格式化空間, vswprintf()
報告錯誤,而vsnprintf()
報告緩沖區中需要的字符數(如果它適合)。 因此,您必須通過反復試驗來工作:
#include <stdio.h>
#include <stdarg.h>
#include <wchar.h>
extern int vscwprintf(const wchar_t *format, va_list argptr);
extern int scwprintf(const wchar_t *format, ...);
int vscwprintf(const wchar_t *format, va_list argptr)
{
// Unlike vsnprintf(), vswprintf() does not tell you how many
// characters would have been written if there was space enough in
// the buffer - it just reports an error when there is not enough
// space. Assume a moderately large machine so kilobytes of wchar_t
// on the stack is not a problem.
int buf_size = 1024;
while (buf_size < 1024 * 1024)
{
va_list args;
va_copy(args, argptr);
wchar_t buffer[buf_size];
int fmt_size = vswprintf(buffer, sizeof(buffer)/sizeof(buffer[0]), format, args);
if (fmt_size >= 0)
return fmt_size;
buf_size *= 2;
}
return -1;
}
int scwprintf(const wchar_t *format, ...)
{
va_list args;
va_start(args, format);
int rc = vscwprintf(format, args);
va_end(args);
return rc;
}
int main(void)
{
int l = scwprintf(L"%-8ls %8d\n", L"abc", 123);
if (l > 0)
{
wchar_t buffer[l+1];
int n = swprintf(buffer, sizeof(buffer)/sizeof(buffer[0]), L"%-8ls %8d\n", L"abc", 123);
wprintf(L"%d = %d: %ls", l, n, buffer);
}
return 0;
}
運行時,這會產生輸出
18 = 18: abc 123
(和以前一樣)。
在 Mac OS X 10.8.3 上使用 GCC 4.7.3 進行測試(它是在 Mac OS X 10.7.5 上構建的,但這不會導致任何問題)。
我建議改用open_wmemstream
。 類似的東西:
#include <stdio.h>
#include <string>
#include <stdarg.h>
using namespace std;
wstring wstring_format(const wchar_t* format, ...)
{
wchar_t* buf;
size_t size;
FILE* stream = open_wmemstream(&buf, &size);
va_list args;
va_start(args, format);
vfwprintf(stream, format, args);
va_end(args);
fclose(stream);
wstring result(buf, buf + size);
free(buf);
return result;
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.