簡體   English   中英

如何在OSX上通過vswprintf格式化寬字符串(想要返回std :: wstring)

[英]How to format wide char string via vswprintf on OSX (want to return std::wstring)

我需要實現一個函數來格式化寬字符串並返回std :: wstring。 我的實施是:

std::wstring format(const wchar_t* fmt, ...)
{
    std::wstring ret;

    va_list va;
    va_start(va, fmt);

    int size = vswprintf(nullptr, 0, fmt, va);
    if (size > 0)
    {
        ret.resize(size + 1);
        vswprintf(&ret[0], size + 1, fmt, va);
    }

    va_end(va);
    return ret;
}

它在Windows上運行良好,但不幸的是它在osx上不起作用,因為vswprintf(nullptr,0,fmt,va)將返回-1。

只能使用std,我不能假設字符串長度在一定范圍內。

我認為應該有一些方法可以做到這一點,但我找不到,你能幫忙嗎? 謝謝

似乎Darwin版本實際上是根據vfwprintf的規范vfwprintf 不幸的是,似乎沒有方便的方法來計算格式字符串的長度,就像使用常規單字節字符串一樣(通過傳遞NULL目標字符串)。

經過大量研究后,我發現似乎有兩種可行的解決方案,這兩種解決方案都在這個答案中提到:

我不喜歡迭代分配方法,因為在分配足夠多的情況下盲目地嘗試相同的操作似乎是低效的。

我首選的解決方案是首先將字符串(一次!)格式化為/dev/null以計算長度,然后使用它來調整緩沖區的大小。 有必要復制變量args列表來執行此操作,因為它由vs *函數使用。 這最接近你如何做它,只是使用空流而不是空字符串。

我建議的解決方案是:

std::wstring format(const wchar_t* fmt, ...)
{
    std::wstring ret;

    va_list va;
    va_start(va, fmt);

    va_list vc;
    va_copy(vc, va);

    FILE* fp = fopen("/dev/null", "w");
    int size = vfwprintf(fp, fmt, vc);
    fclose(fp);

    if (size > 0)
    {
        ret.resize(size + 1);
        vswprintf(&ret[0], size + 1, fmt, va);
    }

    va_end(va);
    va_end(vc);

    return ret;
}

我在Mac OS X上用以下代碼測試了這個,並觀察了預期的輸出:

int main(int argc, char* argv[])
{
    auto outstr = format(L"Hello %ls, you are %u years old.\n", L"Fred", 65);

    std::wcout << outstr << std::endl;

    return 0;
}

偽代碼:

buffer.resize(1)
loop:
    res = vswprintf(buffer, args)
    if res indicates success:
        break
    buffer.resize(buffer.size() * 2)
buffer.truncate()

換句話說,您只需嘗試增加緩沖區大小,直到成功為止。 我會從大於1個字符的東西開始,基本上這樣大多數電話都不必重復,但這只是性能微調。

一種可能的解決方案可能是使用C11標准函數vswprintf_s函數。 這不是完全可移植的,因為C11使得它可以實現這個功能,但我提到它以防你的實現實現它。

C ++ 14僅指定C99標准庫,此函數在C11中。 但是,如果您的C ++編譯器的相關C編譯器支持C11,那么它可能會使該函數直接從C ++中獲得。 即使它沒有,你可以將該代碼包裝在C函數中並從C ++調用該C函數。

vswprintf_s函數使用不同的參數來vswprintf所以仔細檢查其文檔。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

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