Programming

C ++ 문자열 (또는 char *)을 wstring (또는 wchar_t *)으로 변환

procodes 2020. 6. 5. 22:24
반응형

C ++ 문자열 (또는 char *)을 wstring (또는 wchar_t *)으로 변환


string s = "おはよう";
wstring ws = FUNCTION(s, ws);

s의 내용을 ws에 어떻게 할당합니까?

Google을 검색하고 일부 기술을 사용했지만 정확한 콘텐츠를 할당 할 수 없습니다. 내용이 왜곡되었습니다.


예제의 입력 문자열 (お は よ う)이 UTF-8로 인코딩 된 것으로 가정하면 (유형에 따라 다르지 않지만이 설명을 위해 있다고 가정합시다 :-)) 유니 코드 문자열 표준 라이브러리 (C ++ 11 이상)만으로도 문제를 완전히 해결할 수 있습니다.

TL; DR 버전 :

#include <locale>
#include <codecvt>
#include <string>

std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>> converter;
std::string narrow = converter.to_bytes(wide_utf16_source_string);
std::wstring wide = converter.from_bytes(narrow_utf8_source_string);

더 긴 온라인 컴파일 및 실행 가능 예제 :

(모두 동일한 예를 보여줍니다. 중복을위한 많은 것들이 있습니다 ...)

참고 (이전) :

주석에서 지적하고 https://stackoverflow.com/a/17106065/6345에 설명 된 것처럼 표준 라이브러리를 사용하여 UTF-8과 UTF-16 사이를 변환하면 다른 플랫폼의 결과에 예기치 않은 차이가 발생할 수 있습니다 . 더 나은 변환을 위해서는 http://en.cppreference.com/w/cpp/locale/codecvt_utf8에std::codecvt_utf8 설명 된대로 고려 하십시오

참고 (신규) :

codecvtC ++ 17 에서는 헤더가 더 이상 사용되지 않으므로이 답변에 제시된 솔루션에 대한 우려가 제기되었습니다. 그러나, C ++ 표준위원회에서 중요한 문 추가 http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2017/p0618r0.html 말을

이 라이브러리 구성 요소는 적절한 교체가 표준화 될 때까지 옆으로 Annex D로 폐기해야합니다.

따라서 가까운 미래 codecvt에이 답변 솔루션은 안전하고 휴대 가능합니다.


int StringToWString(std::wstring &ws, const std::string &s)
{
    std::wstring wsTmp(s.begin(), s.end());

    ws = wsTmp;

    return 0;
}

귀하의 질문이 잘못 지정되었습니다. 엄밀히 말해 그 예는 구문 오류입니다. 그러나 std::mbstowcs아마도 당신이 찾고있는 것입니다.

C 라이브러리 기능이며 버퍼에서 작동하지만 TBohne (이전 Mooing Duck)이 제공하는 사용하기 쉬운 관용구입니다.

std::wstring ws(s.size(), L' '); // Overestimate number of code points.
ws.resize(std::mbstowcs(&ws[0], s.c_str(), s.size())); // Shrink to fit.

누군가가 필요로 할 경우를 대비하여 C ++ 11 이전의 Windows API 전용 :

#include <stdexcept>
#include <vector>
#include <windows.h>

using std::runtime_error;
using std::string;
using std::vector;
using std::wstring;

wstring utf8toUtf16(const string & str)
{
   if (str.empty())
      return wstring();

   size_t charsNeeded = ::MultiByteToWideChar(CP_UTF8, 0, 
      str.data(), (int)str.size(), NULL, 0);
   if (charsNeeded == 0)
      throw runtime_error("Failed converting UTF-8 string to UTF-16");

   vector<wchar_t> buffer(charsNeeded);
   int charsConverted = ::MultiByteToWideChar(CP_UTF8, 0, 
      str.data(), (int)str.size(), &buffer[0], buffer.size());
   if (charsConverted == 0)
      throw runtime_error("Failed converting UTF-8 string to UTF-16");

   return wstring(&buffer[0], charsConverted);
}

여기에 결합하는 방법 string, wstring그리고에 혼합 문자열 상수 wstring. wstringstream수업을 사용하십시오 .

멀티 바이트 문자 인코딩에는 작동하지 않습니다. 이것은 유형 안전을 버리고 std :: string에서 7 비트 문자를 std : wstring의 각 문자의 하위 7 비트로 확장하는 바보 같은 방법입니다. 이것은 7 비트 ASCII 문자열이 있고 넓은 문자열이 필요한 API를 호출해야하는 경우에만 유용합니다.

#include <sstream>

std::string narrow = "narrow";
std::wstring wide = L"wide";

std::wstringstream cls;
cls << " abc " << narrow.c_str() << L" def " << wide.c_str();
std::wstring total= cls.str();

Windows / Visual Studio를 사용 하고 문자열을 wstring으로 변환 해야하는 경우 다음을 사용할 수 있습니다.

#include <AtlBase.h>
#include <atlconv.h>
...
string s = "some string";
CA2W ca2w(s.c_str());
wstring w = ca2w;
printf("%s = %ls", s.c_str(), w.c_str());

wstring을 문자열로 변환하는 동일한 절차 (때로는 codepage 를 지정해야 함 ) :

#include <AtlBase.h>
#include <atlconv.h>
...
wstring w = L"some wstring";
CW2A cw2a(w.c_str());
string s = cw2a;
printf("%s = %ls", s.c_str(), w.c_str());

You could specify a codepage and even UTF8 (that's pretty nice when working with JNI/Java). A standard way of converting a std::wstring to utf8 std::string is showed in this answer.

// 
// using ATL
CA2W ca2w(str, CP_UTF8);

// 
// or the standard way taken from the answer above
#include <codecvt>
#include <string>

// convert UTF-8 string to wstring
std::wstring utf8_to_wstring (const std::string& str) {
    std::wstring_convert<std::codecvt_utf8<wchar_t>> myconv;
    return myconv.from_bytes(str);
}

// convert wstring to UTF-8 string
std::string wstring_to_utf8 (const std::wstring& str) {
    std::wstring_convert<std::codecvt_utf8<wchar_t>> myconv;
    return myconv.to_bytes(str);
}

If you want to know more about codepages there is an interesting article on Joel on Software: The Absolute Minimum Every Software Developer Absolutely, Positively Must Know About Unicode and Character Sets.

These CA2W (Convert Ansi to Wide=unicode) macros are part of ATL and MFC String Conversion Macros, samples included.

Sometimes you will need to disable the security warning #4995', I don't know of other workaround (to me it happen when I compiled for WindowsXp in VS2012).

#pragma warning(push)
#pragma warning(disable: 4995)
#include <AtlBase.h>
#include <atlconv.h>
#pragma warning(pop)

Edit: Well, according to this article the article by Joel appears to be: "while entertaining, it is pretty light on actual technical details". Article: What Every Programmer Absolutely, Positively Needs To Know About Encoding And Character Sets To Work With Text.


From char* to wstring:

char* str = "hello worlddd";
wstring wstr (str, str+strlen(str));

From string to wstring:

string str = "hello worlddd";
wstring wstr (str.begin(), str.end());

Note this only works well if the string being converted contains only ASCII characters.


using Boost.Locale:

ws = boost::locale::conv::utf_to_utf<wchar_t>(s);

This variant of it is my favourite in real life. It converts the input, if it is valid UTF-8, to the respective wstring. If the input is corrupted, the wstring is constructed out of the single bytes. This is extremely helpful if you cannot really be sure about the quality of your input data.

std::wstring convert(const std::string& input)
{
    try
    {
        std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>> converter;
        return converter.from_bytes(input);
    }
    catch(std::range_error& e)
    {
        size_t length = input.length();
        std::wstring result;
        result.reserve(length);
        for(size_t i = 0; i < length; i++)
        {
            result.push_back(input[i] & 0xFF);
        }
        return result;
    }
}

Based upon my own testing (On windows 8, vs2010) mbstowcs can actually damage original string, it works only with ANSI code page. If MultiByteToWideChar/WideCharToMultiByte can also cause string corruption - but they tends to replace characters which they don't know with '?' question marks, but mbstowcs tends to stop when it encounters unknown character and cut string at that very point. (I have tested Vietnamese characters on finnish windows).

So prefer Multi*-windows api function over analogue ansi C functions.

Also what I've noticed shortest way to encode string from one codepage to another is not use MultiByteToWideChar/WideCharToMultiByte api function calls but their analogue ATL macros: W2A / A2W.

So analogue function as mentioned above would sounds like:

wstring utf8toUtf16(const string & str)
{
   USES_CONVERSION;
   _acp = CP_UTF8;
   return A2W( str.c_str() );
}

_acp is declared in USES_CONVERSION macro.

Or also function which I often miss when performing old data conversion to new one:

string ansi2utf8( const string& s )
{
   USES_CONVERSION;
   _acp = CP_ACP;
   wchar_t* pw = A2W( s.c_str() );

   _acp = CP_UTF8;
   return W2A( pw );
}

But please notice that those macro's use heavily stack - don't use for loops or recursive loops for same function - after using W2A or A2W macro - better to return ASAP, so stack will be freed from temporary conversion.


String to wstring

std::wstring Str2Wstr(const std::string& str)
{
    int size_needed = MultiByteToWideChar(CP_UTF8, 0, &str[0], (int)str.size(), NULL, 0);
    std::wstring wstrTo(size_needed, 0);
    MultiByteToWideChar(CP_UTF8, 0, &str[0], (int)str.size(), &wstrTo[0], size_needed);
    return wstrTo;
}

wstring to String

std::string Wstr2Str(const std::wstring& wstr)
{
    typedef std::codecvt_utf8<wchar_t> convert_typeX;
    std::wstring_convert<convert_typeX, wchar_t> converterX;
    return converterX.to_bytes(wstr);
}

method s2ws works well. Hope helps.

std::wstring s2ws(const std::string& s) {
    std::string curLocale = setlocale(LC_ALL, ""); 
    const char* _Source = s.c_str();
    size_t _Dsize = mbstowcs(NULL, _Source, 0) + 1;
    wchar_t *_Dest = new wchar_t[_Dsize];
    wmemset(_Dest, 0, _Dsize);
    mbstowcs(_Dest,_Source,_Dsize);
    std::wstring result = _Dest;
    delete []_Dest;
    setlocale(LC_ALL, curLocale.c_str());
    return result;
}

If you have QT and if you are lazy to implement a function and stuff you can use

std::string str; QString(str).toStdWString()


string s = "おはよう"; is an error.

You should use wstring directly:

wstring ws = L"おはよう";

use this code to convert your string to wstring

std::wstring string2wString(const std::string& s){
    int len;
    int slength = (int)s.length() + 1;
    len = MultiByteToWideChar(CP_ACP, 0, s.c_str(), slength, 0, 0); 
    wchar_t* buf = new wchar_t[len];
    MultiByteToWideChar(CP_ACP, 0, s.c_str(), slength, buf, len);
    std::wstring r(buf);
    delete[] buf;
    return r;
}

int main(){
    std::wstring str="your string";
    std::wstring wStr=string2wString(str);
    return 0;
}

참고URL : https://stackoverflow.com/questions/2573834/c-convert-string-or-char-to-wstring-or-wchar-t

반응형