Mac OS X/Linux上的_vscwprintf

dop*_*ime 1 c c++ linux macos

我正在为Mac OS X上移植一个为Windows编写的应用程序.

在此应用程序中,有许多_vscwprintf和_vscprintf实例.

这个问题帮助我在Mac OS X上实现_vsprintf.但是_vswprintf的相同技术无效.

任何人都可以在Mac OS X上提供_vscwprintf的替代方案吗?或者有任何等效的方法吗?

Jon*_*ler 5

Microsoft将函数描述为返回格式化字符串时将使用的字符数 - 请注意它们被记录为不包括空终止符.

int _vscprintf(
   const char *format,
   va_list argptr 
);
int _vscwprintf(
   const wchar_t *format,
   va_list argptr 
);
Run Code Online (Sandbox Code Playgroud)

初步答复

这些功能可以,因此,可以用模拟vsprintf()vswprintf():

int _vscprintf(const char *format, va_list argptr)
{
    return(vsnprintf(0, 0, format, argptr));
}
Run Code Online (Sandbox Code Playgroud)

int _vscwprintf(const wchar_t *format, va_list argptr)
{
    return(vswprintf(0, 0, format, argptr));
}
Run Code Online (Sandbox Code Playgroud)

是否删除了前导下划线取决于您; 我会.

注意_vscwprintf()上面的实现是有缺陷的; 请参阅下面的代码.


vscprintf()scprintf()

道歉:我写vsprintf()了我需要写的地方vsnprintf()(现在修复了上面的代码); 但是,vswprintf()已经有了更缓慢的缓冲区长度接口,所以没有vsnwprintf().我之所以喜欢在发布之前(或之后不久)测试编译代码是有原因的 - 几天之内没有足够的资金来做这件事.

这是vscprintf()(和scprintf())的SSCCE :

#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;
}
Run Code Online (Sandbox Code Playgroud)

输出:

18 = 18: abc           123
Run Code Online (Sandbox Code Playgroud)

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;
}
Run Code Online (Sandbox Code Playgroud)

运行时,会产生输出

18 = 18: abc           123
Run Code Online (Sandbox Code Playgroud)

(和以前一样).

使用GCC 4.7.3(基于Mac OS X 10.7.5构建,但不应导致任何问题)在Mac OS X 10.8.3上进行测试.