wstring을 문자열로 변환하는 방법은 무엇입니까?


204

문제는 wstring을 문자열로 변환하는 방법입니다.

다음 예가 있습니다.

#include <string>
#include <iostream>

int main()
{
    std::wstring ws = L"Hello";
    std::string s( ws.begin(), ws.end() );

  //std::cout <<"std::string =     "<<s<<std::endl;
    std::wcout<<"std::wstring =    "<<ws<<std::endl;
    std::cout <<"std::string =     "<<s<<std::endl;
}

주석 처리 된 출력은 다음과 같습니다.

std::string =     Hello
std::wstring =    Hello
std::string =     Hello

그러나 없이는 :

std::wstring =    Hello

예제에 문제가 있습니까? 위와 같이 변환 할 수 있습니까?

편집하다

새로운 예 (일부 답변 고려)는

#include <string>
#include <iostream>
#include <sstream>
#include <locale>

int main()
{
    setlocale(LC_CTYPE, "");

    const std::wstring ws = L"Hello";
    const std::string s( ws.begin(), ws.end() );

    std::cout<<"std::string =     "<<s<<std::endl;
    std::wcout<<"std::wstring =    "<<ws<<std::endl;

    std::stringstream ss;
    ss << ws.c_str();
    std::cout<<"std::stringstream =     "<<ss.str()<<std::endl;
}

출력은 다음과 같습니다

std::string =     Hello
std::wstring =    Hello
std::stringstream =     0x860283c

따라서 stringstream을 사용하여 wstring을 문자열로 변환 할 수 없습니다.


4
인코딩도 지정하지 않고 어떻게이 질문을 할 수 있습니까?
David Heffernan 2012 년

5
@tenfour : 왜 std::wstring전혀 사용하지 않습니까? stackoverflow.com/questions/1049947/…
dalle

11
@dalle UTF-16으로 이미 인코딩 된 데이터가있는 경우 UTF-16이 유해한 것으로 간주되는지 여부는 다소 무의미합니다. 그리고 가치있는 것에 대해, 나는 어떤 변환 형태도 해롭다 고 생각하지 않습니다. 해로운 것은 실제로는 그렇지 않을 때 유니 코드를 이해한다고 생각하는 사람들입니다.
David Heffernan

2
크로스 플랫폼 솔루션이어야합니까?
ali_bahoo

2
@dalle c ++ 표준은 utf를 언급하지 않습니다 (utf-8 또는 utf-16). utf-16이 wstring으로 인코딩 할 수없는 이유가있는 링크가 있습니까?
BЈовић

답변:


31

다른 제안을 바탕으로 해결 된 솔루션은 다음과 같습니다.

#include <string>
#include <iostream>
#include <clocale>
#include <locale>
#include <vector>

int main() {
  std::setlocale(LC_ALL, "");
  const std::wstring ws = L"ħëłlö";
  const std::locale locale("");
  typedef std::codecvt<wchar_t, char, std::mbstate_t> converter_type;
  const converter_type& converter = std::use_facet<converter_type>(locale);
  std::vector<char> to(ws.length() * converter.max_length());
  std::mbstate_t state;
  const wchar_t* from_next;
  char* to_next;
  const converter_type::result result = converter.out(state, ws.data(), ws.data() + ws.length(), from_next, &to[0], &to[0] + to.size(), to_next);
  if (result == converter_type::ok or result == converter_type::noconv) {
    const std::string s(&to[0], to_next);
    std::cout <<"std::string =     "<<s<<std::endl;
  }
}

일반적으로 Linux에서는 작동하지만 Windows에서는 문제가 발생합니다.


@ 필립 : 코드의 어느 부분이 c 로케일에 의존합니까? 는 IS std::setlocale(LC_ALL, "");정말 필요?
smerlin

2
를 사용 std::wcout.imbue(locale)하면 작업을 수행 할 수 있으며 전역 상태를 변경하지 않는 이점이 있습니다.
smerlin

32
std::wstring_convert에서 C ++이 많은 소음까지 11 랩.
Cubbi

7
@Philipp, "Windows에서 문제를 일으킬 것"이란 무엇입니까? 어떤 종류의 문제?
길리

1
위의 코드는 (복사 된) *** glibc detected *** test: malloc(): smallbin double linked list corrupted: 0x000000000180ea30 ***Linux 64 비트 (gcc 4.7.3)를 제공합니다. 다른 사람이 이것을 경험?
hogliux

312

Cubbi가 의견 중 하나에서 지적했듯이 std::wstring_convert(C ++ 11)은 깔끔하고 간단한 솔루션을 제공합니다 ( #include <locale>및 필요 <codecvt>).

std::wstring string_to_convert;

//setup converter
using convert_type = std::codecvt_utf8<wchar_t>;
std::wstring_convert<convert_type, wchar_t> converter;

//use converter (.to_bytes: wstr->str, .from_bytes: str->wstr)
std::string converted_str = converter.to_bytes( string_to_convert );

나는 wcstombs이것을 발견하기 전에 메모리의 지루한 할당 / 할당 해제를 조합하여 사용하고있었습니다 .

http://en.cppreference.com/w/cpp/locale/wstring_convert

업데이트 (2013.11.28)

하나의 라이너는 다음과 같이 말할 수 있습니다 (댓글을 보내 주셔서 감사합니다).

std::wstring str = std::wstring_convert<std::codecvt_utf8<wchar_t>>().from_bytes("some string");

래퍼 함수는 다음과 같이 설명 할 수 있습니다. (주석에 대한 ArmanSchwarz 감사합니다)

std::wstring s2ws(const std::string& str)
{
    using convert_typeX = std::codecvt_utf8<wchar_t>;
    std::wstring_convert<convert_typeX, wchar_t> converterX;

    return converterX.from_bytes(str);
}

std::string ws2s(const std::wstring& wstr)
{
    using convert_typeX = std::codecvt_utf8<wchar_t>;
    std::wstring_convert<convert_typeX, wchar_t> converterX;

    return converterX.to_bytes(wstr);
}

참고 : string/ 여부에 대한 논란이 있습니다.wstring 참조 또는 (로 인해 11 및 컴파일러 업데이트 ++ C까지) 리터럴로 함수에 전달해야한다가. 나는 그 결정을 이행하는 사람에게 맡길 것이다. 그러나 그것은 가치가있다.

참고 : std::codecvt_utf8위 코드에서 사용 하고 있지만 UTF-8을 사용하지 않는 경우 사용중인 적절한 인코딩으로 변경해야합니다.

http://en.cppreference.com/w/cpp/header/codecvt


25
+1 : 문자열 변환을 수행하는 공식 C ++ 표준 방법입니다. from_bytes를 사용하여 다른 방법으로 변환 할 수도 있습니다. 개인적으로 원 라이너를 좋아하기 때문에 여기 내 버전이 있습니다.std::wstring str = std::wstring_convert<std::codecvt_utf<wchar_t>>().from_bytes("some string");
Guss

7
g ++ 4.8.2 부터 en.cppreference.com/w/cpp/header/codecvt 를 사용할 수없는 것 같습니다 . 두 개의 s2ws 및 ws2s 메소드는 현재 리눅스에서 작동하지 않습니다
Begui

5
이것은 더 이상 사용되지 않는 것 같습니다 ( stackoverflow.com/a/42946556/211176 ). 이 코드를 실행하려고하면 컴파일러에서 오류가 발생합니다
adam_0


5
C ++ 17 및 추가 호환성 (더 이상 사용되지 않음)에 대해 걱정하는 사람은 다음을 참조하십시오. stackoverflow.com/a/18597384/6205379
Timo

128

솔루션 : http://forums.devshed.com/c-programming-42/wstring-to-string-444006.html

std::wstring wide( L"Wide" ); 
std::string str( wide.begin(), wide.end() );

// Will print no problemo!
std::cout << str << std::endl;

주의 가 없다는 것을 전혀 전혀 여기에 무슨 문자 집합 변환. 이것이하는 일은 단순히 각 반복 wchar_tchar잘라내는 변환 에 할당 하는 것입니다. std :: string c'tor를 사용합니다 .

template< class InputIt >
basic_string( InputIt first, InputIt last,
              const Allocator& alloc = Allocator() );

의견에 명시된 바와 같이 :

값 0-127은 거의 모든 인코딩에서 동일하므로 127보다 작은 값을 자르면 동일한 텍스트가 생성됩니다. 한자를 입력하면 실패를 볼 수 있습니다.

-

Windows 코드 페이지 1252의 값 128-255 (Windows 영어 기본값)와 유니 코드의 128-255 값은 대부분 동일하므로 코드 페이지 인 경우 대부분의 문자를 사용하면 올바른 값으로 잘립니다. (나는 완전히 작동 할 것으로 예상했다. 나는 직장에서 우리의 코드가 이것에 의존한다는 것을 알고있다. 나는 곧 고칠 것이다)

그리고 참고 범위의 코드 포인트 것을 0x80 - 0x9F에서 Win1252는 것입니다 하지 작동합니다. 여기에는 , œ, ž, Ÿ, ...


2
이상하게도 Visual Studio 10에서 작동합니다. 무슨 일입니까? 이로 인해 원래 문자열의 모든 요소에 대해 wchar_t에서 char로 절단이 잘립니다.
Pedro Lamarão

6
... 비 라틴 문자가 아닌 경우.
JavaRunner 2013 년

8
@ PedroLamarão : 값 0-127은 거의 모든 인코딩에서 동일하므로 127보다 작은 값을 자르면 동일한 텍스트가됩니다. 한자를 입력하면 실패를 볼 수 있습니다.
Mooing Duck

3
@ PedroLamarão : Windows 코드 페이지 1252 (Windows 영어 기본값)의 128-255 값과 유니 코드의 128-255 값은 대부분 동일하므로 코드 페이지 인 경우 대부분 의 문자를 사용하면 올바른 문자로 잘립니다 가치. (나는 완전히 작동 할 것으로 예상했다. 나는 직장에서 우리 코드가 é에 의존한다는 것을 알고있다. 곧 수정 될 것이다.)
Mooing Duck

2
이것은 잘 작동합니다. MSVS 2015 및 MSVS 2017 및 MINGW / g ++ 및 clang ++. 합법적 인 ++ 1.
Nikos

11

로케일과 모든 멋진 것들을 포함시키는 대신 FACT를 알고 있다면 문자열을 변환 할 수 있습니다.

#include <iostream>
#include <string>

using namespace std;

int main()
{
  wstring w(L"bla");
  string result;
  for(char x : w)
    result += x;

  cout << result << '\n';
}

여기에 실례


2
일부 시나리오에서 작동하는 간단한 솔루션이기 때문에 +1입니다 ( "works"의 느슨한 정의의 경우 추가 할 수 있음).
raven

2
훨씬 더 우아한 IMHO 인 namar0x0309의 솔루션과 거의 동일합니다. 그러나 그것은 단지 나입니다.
onitake

나는 ;-) 최소한의 수정으로 실제로 작업에 코드를 spiffied
rubenvb

9
-1 wstring이 있으면 멀티 바이트 문자를 다루는 것 같습니다. 문자열이 간단하게 변환 가능하다는 것을 알 수 있다면 처음에는 wstring을 처리하지 않을 것입니다. 아마도 wstring을 올바르게 처리 할 것으로 기대하는 다른 라이브러리를 다루고있을 것입니다. wchars를 잘라내는 것은 나중에 버그를 추적하기가 어렵다는 것을 간청합니다. 또한 "string result (w.begin (), w.end ());"를 사용해야합니다. 많은 재 할당을 트리거 할 수있는 루프를 피하려면 그렇게해야합니다.
키안

7

나는 공식적인 방법이 여전히 멍청한 codecvt면 으로 갈 것이라고 믿는다.

resultCode = use_facet<codecvt<char, wchar_t, ConversionState> >(locale).
  in(stateVar, scratchbuffer, scratchbufferEnd, from, to, toLimit, curPtr);

또는 그와 비슷한 것, 작업 코드가 없습니다. 그러나 요즘 얼마나 ​​많은 사람들이 그 기계를 사용하는지 그리고 얼마나 많은 사람들이 단순히 메모리에 대한 포인터를 요구하고 ICU 또는 다른 도서관이 처참한 세부 사항을 처리하게하는지 확실하지 않습니다.


7

코드에는 두 가지 문제가 있습니다.

  1. const std::string s( ws.begin(), ws.end() );넓은 문자를 좁은 문자에 올바르게 매핑하기 위해 변환 할 필요는 없습니다. 대부분의 넓은 문자는로 형식 변환됩니다 char.
    이 문제에 대한 해결책 은 이미 kem의 답변에 나와 있으며 narrow로케일 ctype패싯 의 기능 과 관련이 있습니다 .

  2. 동일한 프로그램에서 둘 모두에 출력을 작성 std::cout하고 std::wcout있습니다. 양쪽 cout과는 wcout동일한 스트림 (과 연관된 stdout)과 동일한 스트림 모두 바이트 스트림 지향 (만큼 사용한 결과 cout않음) 및 넓은 지향 스트림 (AS wcout않음)를 정의하지.
    가장 좋은 옵션은 좁은 (너무) 출력을 동일한 (기본) 스트림에 혼합하지 않는 것입니다. 대한 stdout/ cout/ wcout당신의 방향 전환 시도 할 수 있습니다 stdout폭이 좁은 출력 (또는 반대의 반대)를 전환 할 때를 :

    #include <iostream>
    #include <stdio.h>
    #include <wchar.h>
    
    int main() {
        std::cout << "narrow" << std::endl;
        fwide(stdout, 1); // switch to wide
        std::wcout << L"wide" << std::endl;
        fwide(stdout, -1); // switch to narrow
        std::cout << "narrow" << std::endl;
        fwide(stdout, 1); // switch to wide
        std::wcout << L"wide" << std::endl;
    }

예, cout 및 wcout 사용 관련 문제를 해결합니다.
BЈовић

7

기본 인코딩 :

  • Windows UTF-16.
  • 리눅스 UTF-8.
  • MacOS UTF-8.

이 코드에는 std :: string을 std :: wstring으로, std :: wstring을 std :: string으로 변환하는 두 가지 형식이 있습니다. WIN32가 정의 된 경우 #을 부정하면 동일한 결과가 나타납니다.

std :: string to std :: wstring

MultiByteToWideChar WinAPI

_mbstowcs_s_l

#if defined WIN32
#include <windows.h>
#endif

std::wstring StringToWideString(std::string str)
{
    if (str.empty())
    {
        return std::wstring();
    }
    size_t len = str.length() + 1;
    std::wstring ret = std::wstring(len, 0);
#if defined WIN32
    int size = MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, &str[0], str.size(), &ret[0], len);
    ret.resize(size);
#else
    size_t size = 0;
    _locale_t lc = _create_locale(LC_ALL, "en_US.UTF-8");
    errno_t retval = _mbstowcs_s_l(&size, &ret[0], len, &str[0], _TRUNCATE, lc);
    _free_locale(lc);
    ret.resize(size - 1);
#endif
    return ret;
}

2. std :: wstring을 std :: string으로

WideCharToMultiByte WinAPI를

_wcstombs_s_l

std::string WidestringToString(std::wstring wstr)
{
    if (wstr.empty())
    {
        return std::string();
    }
#if defined WIN32
    int size = WideCharToMultiByte(CP_UTF8, WC_ERR_INVALID_CHARS, &wstr[0], wstr.size(), NULL, 0, NULL, NULL);
    std::string ret = std::string(size, 0);
    WideCharToMultiByte(CP_UTF8, WC_ERR_INVALID_CHARS, &wstr[0], wstr.size(), &ret[0], size, NULL, NULL);
#else
    size_t size = 0;
    _locale_t lc = _create_locale(LC_ALL, "en_US.UTF-8");
    errno_t err = _wcstombs_s_l(&size, NULL, 0, &wstr[0], _TRUNCATE, lc);
    std::string ret = std::string(size, 0);
    err = _wcstombs_s_l(&size, &ret[0], size, &wstr[0], _TRUNCATE, lc);
    _free_locale(lc);
    ret.resize(size - 1);
#endif
    return ret;
}

3. Windows에서는 WinAPI를 사용하여 유니 코드를 인쇄해야합니다.

WriteConsole

#if defined _WIN32
    void WriteLineUnicode(std::string s)
    {
        std::wstring unicode = StringToWideString(s);
        WriteConsole(GetStdHandle(STD_OUTPUT_HANDLE), unicode.c_str(), unicode.length(), NULL, NULL);
        std::cout << std::endl;
    }

    void WriteUnicode(std::string s)
    {
        std::wstring unicode = StringToWideString(s);
        WriteConsole(GetStdHandle(STD_OUTPUT_HANDLE), unicode.c_str(), unicode.length(), NULL, NULL);
    }

    void WriteLineUnicode(std::wstring ws)
    {
        WriteConsole(GetStdHandle(STD_OUTPUT_HANDLE), ws.c_str(), ws.length(), NULL, NULL);
        std::cout << std::endl;
    }

    void WriteUnicode(std::wstring ws)
    {
        WriteConsole(GetStdHandle(STD_OUTPUT_HANDLE), ws.c_str(), ws.length(), NULL, NULL);
    }

4. 메인 프로그램에서.

#if defined _WIN32
int wmain(int argc, WCHAR ** args)
#else
int main(int argc, CHAR ** args)
#endif
{
    std::string source = u8"ÜüΩωЙ你月曜日\na🐕èéøÞǽлљΣæča🐕🐕";
    std::wstring wsource = L"ÜüΩωЙ你月曜日\na🐕èéøÞǽлљΣæča🐕🐕";

    WriteLineUnicode(L"@" + StringToWideString(source) + L"@");
    WriteLineUnicode("@" + WidestringToString(wsource) + "@");
    return EXIT_SUCCESS;
}

5. 마지막으로 콘솔에서 유니 코드 문자를 강력하고 완벽하게 지원해야합니다. ConEmu를 권장 하고 Windows에서 기본 터미널로 설정합니다 . Visual Studio를 ConEmu에 연결해야합니다. Visual Studio의 exe 파일은 devenv.exe입니다.

VC ++로 Visual Studio 2017에서 테스트했습니다. std = c ++ 17.

결과

결과 1


6

ctype facet의 좁은 방법을 직접 사용할 수도 있습니다.

#include <clocale>
#include <로케일>
#include <문자열>
#include <벡터>

인라인 std :: string narrow (std :: wstring const & text)
{
    std :: locale const loc ( "");
    wchar_t const * from = text.c_str ();
    std :: size_t const len ​​= text.size ();
    std :: vector <char> 버퍼 (len + 1);
    std :: use_facet <std :: ctype <wchar_t>> (loc) .narrow (from, from + len, '_', & buffer [0]);
    std :: string (& buffer [0], & buffer [len])을 리턴합니다.
}

6

이 답변을 작성할 때 Google이 "문자열 wstring 변환"을 검색하면이 페이지로 연결됩니다. 내 대답은 문자열을 wstring으로 변환하는 방법을 보여줍니다. 실제 질문은 아니지만이 대답을 삭제해야하지만 나쁜 형식으로 간주됩니다. 이 페이지보다 순위가 높은 이 StackOverflow 답변으로 건너 뛸 수 있습니다 .


다음은 문자열, wstring 및 혼합 문자열 상수를 wstring에 결합하는 방법입니다. wstringstream 클래스를 사용하십시오.

#include <sstream>

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

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

13
이것은 wstring에서 문자열로의 변환이 아닙니다
poitroae

1
@Michael 설명해 주시겠습니까? 이건 어때? 귀하의 의견은 자세한 내용이 없으면 도움이되지 않습니다.
Nate

1
이것은 문자열을 wstring으로 변환하는 것입니다. 즉 질문의 반대입니다.
Jeff McClintock의

4

유형을 변환하는 것 외에도 문자열의 실제 형식에 대해서도 알고 있어야합니다.

멀티 바이트 문자 집합을 컴파일 할 때 Visual Studio 및 Win API는 UTF8 (실제로 Windows 인코딩 인 Windows-28591 )을 가정합니다. 유니 코드 문자 집합을
컴파일 할 때 Visual Studio 및 Win API는 UTF16을 가정합니다.

따라서 문자열을 UTF16에서 UTF8 형식으로 변환해야하며 std :: string으로 변환하지 않아야합니다.
이것은 비 라틴 언어와 같은 다중 문자 형식으로 작업 할 때 필요합니다.

아이디어는 std::wstring 항상 UTF16을 나타내는 지를 결정하는 것입니다 .
그리고 std::string 항상 UTF8을 나타냅니다 .

이것은 컴파일러에 의해 시행되지 않으며, 더 좋은 정책입니다. UTF16 ( L ) 및 UTF8 ( u8 ) 을 정의하는 데 사용하는 문자열 접두사에 유의하십시오 .

두 유형을 변환하려면 std :: codecvt_utf8_utf16 <wchar_t> 를 사용해야합니다.

#include <string>

#include <codecvt>

int main()
{

    std::string original8 = u8"הלו";

    std::wstring original16 = L"הלו";

    //C++11 format converter
    std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>> convert;

    //convert to UTF8 and std::string
    std::string utf8NativeString = convert.to_bytes(original16);

    std::wstring utf16NativeString = convert.from_bytes(original8);

    assert(utf8NativeString == original8);
    assert(utf16NativeString == original16);

    return 0;
}

3

필자의 경우 멀티 바이트 문자 (MBCS)를 사용해야하며 std :: string 및 std :: wstring을 사용하고 싶습니다. 그리고 c ++ 11을 사용할 수 없습니다. 그래서 mbstowcs와 wcstombs를 사용합니다.

new, delete []를 사용하여 동일한 기능을 수행하지만 속도가 느립니다.

이 도움이 될 수 있습니다 방법 : 다양한 문자열 형식 사이의 변환

편집하다

그러나 wstring으로 변환하고 소스 문자열이 알파벳과 멀티 바이트 문자열이 아닌 경우 작동하지 않습니다. 그래서 wcstombs를 WideCharToMultiByte로 변경합니다.

#include <string>

std::wstring get_wstr_from_sz(const char* psz)
{
    //I think it's enough to my case
    wchar_t buf[0x400];
    wchar_t *pbuf = buf;
    size_t len = strlen(psz) + 1;

    if (len >= sizeof(buf) / sizeof(wchar_t))
    {
        pbuf = L"error";
    }
    else
    {
        size_t converted;
        mbstowcs_s(&converted, buf, psz, _TRUNCATE);
    }

    return std::wstring(pbuf);
}

std::string get_string_from_wsz(const wchar_t* pwsz)
{
    char buf[0x400];
    char *pbuf = buf;
    size_t len = wcslen(pwsz)*2 + 1;

    if (len >= sizeof(buf))
    {
        pbuf = "error";
    }
    else
    {
        size_t converted;
        wcstombs_s(&converted, buf, pwsz, _TRUNCATE);
    }

    return std::string(pbuf);
}

'wcstombs'대신 'MultiByteToWideChar'를 사용하도록 편집

#include <Windows.h>
#include <boost/shared_ptr.hpp>
#include "string_util.h"

std::wstring get_wstring_from_sz(const char* psz)
{
    int res;
    wchar_t buf[0x400];
    wchar_t *pbuf = buf;
    boost::shared_ptr<wchar_t[]> shared_pbuf;

    res = MultiByteToWideChar(CP_ACP, 0, psz, -1, buf, sizeof(buf)/sizeof(wchar_t));

    if (0 == res && GetLastError() == ERROR_INSUFFICIENT_BUFFER)
    {
        res = MultiByteToWideChar(CP_ACP, 0, psz, -1, NULL, 0);

        shared_pbuf = boost::shared_ptr<wchar_t[]>(new wchar_t[res]);

        pbuf = shared_pbuf.get();

        res = MultiByteToWideChar(CP_ACP, 0, psz, -1, pbuf, res);
    }
    else if (0 == res)
    {
        pbuf = L"error";
    }

    return std::wstring(pbuf);
}

std::string get_string_from_wcs(const wchar_t* pcs)
{
    int res;
    char buf[0x400];
    char* pbuf = buf;
    boost::shared_ptr<char[]> shared_pbuf;

    res = WideCharToMultiByte(CP_ACP, 0, pcs, -1, buf, sizeof(buf), NULL, NULL);

    if (0 == res && GetLastError() == ERROR_INSUFFICIENT_BUFFER)
    {
        res = WideCharToMultiByte(CP_ACP, 0, pcs, -1, NULL, 0, NULL, NULL);

        shared_pbuf = boost::shared_ptr<char[]>(new char[res]);

        pbuf = shared_pbuf.get();

        res = WideCharToMultiByte(CP_ACP, 0, pcs, -1, pbuf, res, NULL, NULL);
    }
    else if (0 == res)
    {
        pbuf = "error";
    }

    return std::string(pbuf);
}

gcc 4.8에서 "wcstombs_s"를 어떻게 사용합니까? 그것이 C ++ 11 기능이라는 것을 알기 때문입니다.
크리스티안

@cristian이 기능의 "안전하지 않은"버전을 사용할 수 있습니다 wcstombs().
Vizor

3

이 솔루션은 dk123의 솔루션 에서 영감을 얻었 지만 로케일 종속 codecvt 패싯을 사용합니다. 결과는 UTF-8 대신 로케일로 인코딩 된 문자열에 있습니다 (로케일로 설정되지 않은 경우).

std::string w2s(const std::wstring &var)
{
   static std::locale loc("");
   auto &facet = std::use_facet<std::codecvt<wchar_t, char, std::mbstate_t>>(loc);
   return std::wstring_convert<std::remove_reference<decltype(facet)>::type, wchar_t>(&facet).to_bytes(var);
}

std::wstring s2w(const std::string &var)
{
   static std::locale loc("");
   auto &facet = std::use_facet<std::codecvt<wchar_t, char, std::mbstate_t>>(loc);
   return std::wstring_convert<std::remove_reference<decltype(facet)>::type, wchar_t>(&facet).from_bytes(var);
}

검색했지만 찾을 수 없습니다. 마지막으로 올바른 typename으로 함수 를 std::locale사용하여 올바른 패싯을 얻을 수 있음을 알았습니다 std::use_facet(). 도움이 되었기를 바랍니다.


Vizor, 로케일 종속 패싯으로 변환하면 어떤 이점이 있습니까?
Marc.2377

예를 들어 콘솔 입력에서 시스템의 문자열로 작업하는 경우.
Vizor

1

다른 사람이 관심이있는 경우 : string또는 wstring예상 한 위치에서 상호 교환 가능하게 사용할 수있는 클래스가 필요했습니다 . 다음 클래스 convertible_string를 기반으로, dk123의 솔루션은 , 중 하나로 초기화 할 수있다 string, char const*, wstring또는 wchar_t const*과 중 하나에 의해 지정 또는 암시 적으로 변환 할 수 있습니다 string또는 wstring(중 걸릴 함수로 그렇게 전달 될 수 있습니다).

class convertible_string
{
public:
    // default ctor
    convertible_string()
    {}

    /* conversion ctors */
    convertible_string(std::string const& value) : value_(value)
    {}
    convertible_string(char const* val_array) : value_(val_array)
    {}
    convertible_string(std::wstring const& wvalue) : value_(ws2s(wvalue))
    {}
    convertible_string(wchar_t const* wval_array) : value_(ws2s(std::wstring(wval_array)))
    {}

    /* assignment operators */
    convertible_string& operator=(std::string const& value)
    {
        value_ = value;
        return *this;
    }
    convertible_string& operator=(std::wstring const& wvalue)
    {
        value_ = ws2s(wvalue);
        return *this;
    }

    /* implicit conversion operators */
    operator std::string() const { return value_; }
    operator std::wstring() const { return s2ws(value_); }
private:
    std::string value_;
};

1
std::wstring클래스를 저장하는 것이 아니라 필요할 때 저장 std::string하고 변환하는 것보다 클래스에 저장하고 싶습니다 . 때문에 보다 빠른 다소입니다 그것은 더 나은 호환. 심지어 그것보다 더 많은 메모리를 소비합니다 . std::wstringstd::wstringstd::wstringstd::stringstd::string
0xAA55

0
#include <boost/locale.hpp>
namespace lcv = boost::locale::conv;

inline std::wstring fromUTF8(const std::string& s)
{ return lcv::utf_to_utf<wchar_t>(s); }

inline std::string toUTF8(const std::wstring& ws)
{ return lcv::utf_to_utf<char>(ws); }

-1

wstring을 문자열로 변환하기 위해 아래를 사용하고 있습니다.

std::string strTo;
char *szTo = new char[someParam.length() + 1];
szTo[someParam.size()] = '\0';
WideCharToMultiByte(CP_ACP, 0, someParam.c_str(), -1, szTo, (int)someParam.length(), NULL, NULL);
strTo = szTo;
delete szTo;

당신은 표준 헤더 (없는 것 같다 <string>)과 정의는 WideCharToMultiByte()-입니다 주위에 어떤 래퍼가 std::wctomb()?
Toby Speight

-3
// Embarcadero C++ Builder 

// convertion string to wstring
string str1 = "hello";
String str2 = str1;         // typedef UnicodeString String;   -> str2 contains now u"hello";

// convertion wstring to string
String str2 = u"hello";
string str1 = UTF8string(str2).c_str();   // -> str1 contains now "hello"

3
답이 무엇인지 설명해주십시오. 그렇지 않으면 삭제 될 수 있습니다.
CodeFanatic

1
UTF8string 함수는 어디에서 왔습니까?
Jean-Christophe Blanchard
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.