C++ 将窄字符串插入std::basic_ostream<;wchar_t>;

C++ 将窄字符串插入std::basic_ostream<;wchar_t>;,c++,internationalization,locale,c++-standard-library,C++,Internationalization,Locale,C++ Standard Library,根据,有一个操作员我刚刚在Visual Studio 2015中进行了检查,您是对的。chars仅扩展到wchar\ts,而不进行任何转换。在我看来,您必须自己将窄字符串转换为宽字符串。有几种方法可以做到这一点,其中一些已经被提出 P>这里,我建议您可以使用纯C++设备来完成它,假设C++编译器和标准库已经足够(VisualStudio,或者GCC在Linux上(仅在那里)): void clear_mbstate(标准::mbstate_t&mbs); 无效的 拖缆串\u内部(标准::wst

根据,有一个
操作员我刚刚在Visual Studio 2015中进行了检查,您是对的。
char
s仅扩展到
wchar\t
s,而不进行任何转换。在我看来,您必须自己将窄字符串转换为宽字符串。有几种方法可以做到这一点,其中一些已经被提出

<> P>这里,我建议您可以使用纯C++设备来完成它,假设C++编译器和标准库已经足够(VisualStudio,或者GCC在Linux上(仅在那里)):

void clear_mbstate(标准::mbstate_t&mbs);
无效的
拖缆串\u内部(标准::wstring&outtr,常量字符*src,标准::大小\u t大小,
std::locale const&loc)
{
如果(大小==0)
{
outsr.clear();
返回;
}
typedef std::codevt codevt;
const CodeCvt&cdcvt=std::use_facet(loc);
std::mbstate\u t state;
清除状态(状态);
char const*from_first=src;
std::size\t const from\u size=size;
char const*const from_last=from_first+from_size;
char const*from_next=from_first;
std::向量dest(从_大小);
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::结果;
std::size\u t转换为0;
while(true)
{
结果=cdcvt.in(
州,从第一,从最后,
从下一个到第一个到最后一个,
下一步);
//XXX:即使只有一半的输入被转换为
//in()方法返回CodeCvt::ok。我认为它应该返回
//编解码器VT::部分。
if((结果==CodeCvt::partial | |结果==CodeCvt::ok)
&&来自下一个!=来自上一个)
{
to_size=dest.size()*2;
dest.resize(调整大小);
转换=到下一个\u-到第一个\u;
to_first=&dest.front();
to_last=to_first+to_size;
to_next=to_first+已转换;
继续;
}
else if(result==CodeCvt::ok&&from\u next==from\u last)
打破
else if(结果==CodeCvt::error
&&to_next!=to_last&&from_next!=from_last)
{
清除状态(状态);
++从下一步;
from_first=from_next;
*to_next=L'?';
++下一步;
先到_=后到_;
}
其他的
打破
}
转换为_next-&dest[0];
outsr.assign(dest.begin(),dest.begin()+已转换);
}
无效的
清除状态(标准::状态和状态)
{
//初始化/清除mbstate类型。
//XXX:这只是一个可行的方法。mbstate的形状各不相同
//从单无符号到字符[128]。无需某种初始化
//codecvt::in/out方法随机失败,因为初始状态为
//随机/无效。
std::memset(&mbs,0,sizeof(std::mbstate_t));
}
此函数是log4cplus库的一部分,可以正常工作。它使用
codevt
facet进行转换。您必须对其进行适当的设置
locale


Visual studio可能在为GB2312提供适当的语言环境设置时遇到问题。您可能必须使用
\u setmbcp()
才能使其工作。有关详细信息,请参见“”。

我刚刚签入Visual Studio 2015,您说得对。
char
s仅扩展到
wchar\t
s,而不进行任何转换。在我看来,您必须自己将窄字符串转换为宽字符串。有几种方法可以做到这一点,其中一些已经被提出

<> P>这里,我建议您可以使用纯C++设备来完成它,假设C++编译器和标准库已经足够(VisualStudio,或者GCC在Linux上(仅在那里)):

void clear_mbstate(标准::mbstate_t&mbs);
无效的
拖缆串\u内部(标准::wstring&outtr,常量字符*src,标准::大小\u t大小,
std::locale const&loc)
{
如果(大小==0)
{
outsr.clear();
返回;
}
typedef std::codevt codevt;
const CodeCvt&cdcvt=std::use_facet(loc);
std::mbstate\u t state;
清除状态(状态);
char const*from_first=src;
std::size\t const from\u size=size;
char const*const from_last=from_first+from_size;
char const*from_next=from_first;
std::向量dest(从_大小);
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::结果;
std::size\u t转换为0;
while(true)
{
结果=cdcvt.in(
州,从第一,从最后,
从下一个到第一个到最后一个,
下一步);
//XXX:即使只有一半的输入被转换为
//in()方法返回CodeCvt::ok。我认为它应该返回
//编解码器VT::部分。
if((结果==CodeCvt::partial | |结果==CodeCvt::ok)
&&来自下一个!=来自上一个)
{
to_size=dest.size()*2;
dest.resize(调整大小);
转换=到下一个\u-到第一个\u;
to_first=&dest.front();
to_last=to_first+to_size;
to_next=to_first+已转换;
继续;
}
else if(result==CodeCvt::ok&&from\u next==from\u last)
打破
else if(结果==CodeCvt::error
&&to_next!=to_last&&from_next!=from_last)
{
清除状态(状态);
++从下一步;
from_first=from_next;
*to_next=L'?';
++下一步;
先到_=后到_;
}
其他的
打破
}
转换为_next-&dest[0];
outsr.assign(dest.begin(),dest.beg
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));
}