作者热门文章
- android - RelativeLayout 背景可绘制重叠内容
- android - 如何链接 cpufeatures lib 以获取 native android 库?
- java - OnItemClickListener 不起作用,但 OnLongItemClickListener 在自定义 ListView 中起作用
- java - Android 文件转字符串
我需要实现一个函数来格式化宽字符字符串并返回 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/
我是一名优秀的程序员,十分优秀!