簡體   English   中英

_vscwprintf 在 Mac OS X/Linux 上

[英]_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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM