我正在为 Windows 编写的 Mac OS X 上移植一个应用程序。
在这个应用程序中,有很多 _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()
道歉:我写vsprintf()
了我需要写的地方vsnprintf()
(现在在上面的代码中修复了);但是,vswprintf()
已经有了缓冲区长度更安全的接口,所以没有vsnwprintf()
. 我更喜欢在发布代码之前(或之后不久)测试编译代码是有原因的——这几天没有足够的资金来做这件事令人厌烦。
vscprintf()
这是(和)的SSCCE 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;
}