gpt4 book ai didi

c++ - 如何在 OSX 上通过 vswprintf 格式化宽字符字符串(想要返回 std::wstring)

转载 作者:可可西里 更新时间:2023-11-01 09:33:07 55 4
gpt4 key购买 nike

我需要实现一个函数来格式化宽字符字符串并返回 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 版本实际上表现良好 according to the specification for vfwprintf .不幸的是,似乎也没有方便的方法来计算 wide 格式字符串的长度,就像计算常规单字节字符串一样(通过传递 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;
}

关于c++ - 如何在 OSX 上通过 vswprintf 格式化宽字符字符串(想要返回 std::wstring),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36280521/

55 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com