gpt4 book ai didi

c++ - 插入窄字符串到 std::basic_ostream

转载 作者:太空宇宙 更新时间:2023-11-04 13:27:22 25 4
gpt4 key购买 nike

根据 cppref , 有一个 operator << std::basic_ostream<wchar_t> 过载接受 const char* .似乎转换操作只是加宽了每个 char进入 wchar_t .也就是说,转换(插入)的宽字符数等于窄字符数。那么问题来了。窄字符串可能正在编码国际字符,比如使用 GB2312 的汉字.进一步假设sizeof(wchar_t)2并使用 UTF16 编码。那么这种天真的字符转换方法应该如何工作?

最佳答案

我刚刚检查了 Visual Studio 2015,你是对的。 char 仅扩展为 wchar_t,没有任何转换。在我看来,您必须自己将窄字符串转换为宽字符串。有几种方法可以做到这一点,其中一些已经被建议。

在这里,我建议您可以使用纯 C++ 工具来完成它,假设您的 C++ 编译器标准库足够完整(Visual Studio 或 Linux 上的 GCC(并且只有那里)):

void clear_mbstate (std::mbstate_t & mbs);

void
towstring_internal (std::wstring & outstr, const char * src, std::size_t size,
std::locale const & loc)
{
if (size == 0)
{
outstr.clear ();
return;
}

typedef std::codecvt<wchar_t, char, std::mbstate_t> CodeCvt;
const CodeCvt & cdcvt = std::use_facet<CodeCvt>(loc);
std::mbstate_t state;
clear_mbstate (state);

char const * from_first = src;
std::size_t const from_size = size;
char const * const from_last = from_first + from_size;
char const * from_next = from_first;

std::vector<wchar_t> dest (from_size);

wchar_t * to_first = &dest.front ();
std::size_t to_size = dest.size ();
wchar_t * to_last = to_first + to_size;
wchar_t * to_next = to_first;

CodeCvt::result result;
std::size_t converted = 0;
while (true)
{
result = cdcvt.in (
state, from_first, from_last,
from_next, to_first, to_last,
to_next);
// XXX: Even if only half of the input has been converted the
// in() method returns CodeCvt::ok. I think it should return
// CodeCvt::partial.
if ((result == CodeCvt::partial || result == CodeCvt::ok)
&& from_next != from_last)
{
to_size = dest.size () * 2;
dest.resize (to_size);
converted = to_next - to_first;
to_first = &dest.front ();
to_last = to_first + to_size;
to_next = to_first + converted;
continue;
}
else if (result == CodeCvt::ok && from_next == from_last)
break;
else if (result == CodeCvt::error
&& to_next != to_last && from_next != from_last)
{
clear_mbstate (state);
++from_next;
from_first = from_next;
*to_next = L'?';
++to_next;
to_first = to_next;
}
else
break;
}
converted = to_next - &dest[0];

outstr.assign (dest.begin (), dest.begin () + converted);
}

void
clear_mbstate (std::mbstate_t & mbs)
{
// Initialize/clear mbstate_t type.
// XXX: This is just a hack that works. The shape of mbstate_t varies
// from single unsigned to char[128]. Without some sort of initialization
// the codecvt::in/out methods randomly fail because the initial state is
// random/invalid.
std::memset (&mbs, 0, sizeof (std::mbstate_t));
}

这个函数是 log4cplus 库的一部分,它可以工作。它使用 codecvt facet 来进行转换。你必须给它适本地设置 locale

Visual Studio 可能无法为您正确设置 GB2312 的语言环境。您可能必须使用 _setmbcp() 才能使其正常工作。有关详细信息,请参阅“double byte character sequence conversion issue in Visual Studio 2015”。

关于c++ - 插入窄字符串到 std::basic_ostream<wchar_t>,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32907986/

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