programing

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

javajsp 2023. 8. 2. 08:46

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

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

제가 어떻게 스토브의 내용물을 할당할 수 있습니까?

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

예제의 입력 문자열이 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 사이를 변환하는 경우 다른 플랫폼에서 결과에 예상치 못한 차이가 발생할 수 있습니다.더 나은 변환을 위해 고려합니다.std::codecvt_utf8http://en.cppreference.com/w/cpp/locale/codecvt_utf8 에 설명된 바와 같이

참고(새로 만들기):

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

이 라이브러리 구성요소는 적절한 교체가 표준화될 때까지 부속문서 D에 따라 폐기되어야 합니다.

그래서 가까운 미래에,codecvt이 답변의 솔루션은 안전하고 휴대할 수 있습니다.

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

    ws = wsTmp;

    return 0;
}

질문이 제대로 지정되지 않았습니다.엄밀히 말하면, 그 예는 구문 오류입니다.하지만, 그것은 아마도 당신이 찾고 있는 것일 것입니다.

C 라이브러리 기능이며 버퍼에서 작동하지만, 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.

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을 string으로 변환하는 동일한 절차(때로는 코드 페이지를 지정해야 할 수도 있음):

#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());

코드 페이지와 UTF8도 지정할 수 있습니다(JNI/Java로 작업할 때 매우 유용함).std::wstring을 utf8 std::string으로 변환하는 표준 방법이 이 답변에 나와 있습니다.

// 
// 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);
}

코드 페이지에 대해 자세히 알고 싶다면 Joel on Software에 대한 흥미로운 기사가 있습니다.절대 최소 모든 소프트웨어 개발자는 유니코드문자 집합에 대해 절대적, 긍정적으로 알아야 합니다.

이러한 CA2W(Convert Ansi to Wide=module) 매크로는 ATL MFC String Conversion 매크로의 일부이며 샘플이 포함되어 있습니다.

때때로 보안 경고 #4995'를 사용하지 않도록 설정해야 합니다. 다른 해결 방법은 모르겠습니다(VS2012에서 Windows XP용으로 컴파일할 때 발생합니다).

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

편집: 자, 기사에 따르면 조엘의 기사는 "흥미를 주는 동안 실제 기술적 세부 사항에 대해 매우 가볍습니다."라고 합니다.기사:모든 프로그래머가 텍스트 작업을 위해 인코딩 문자 집합에 대해 절대적으로 알아야사항.

Windows API 전용, C++11 이전 구현(다른 사용자가 필요할 경우):

#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();

char*wstring:

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

stringwstring:

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

변환 중인 문자열에 ASCII 문자만 포함된 경우에만 이 기능이 제대로 작동합니다.

이것의 변형은 내가 실생활에서 가장 좋아하는 것입니다.유효한 UTF-8인 경우 입력을 각 입력으로 변환합니다.wstring, 입이손경우된상력,wstring단일 바이트로 구성됩니다.이것은 입력 데이터의 품질을 확신할 수 없는 경우에 매우 유용합니다.

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;
    }
}

Boost를 사용합니다.로케일:

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

부스트 경로 또는 표준 경로를 사용할 수 있으며, 이는 훨씬 더 쉽습니다.크로스 플랫폼 애플리케이션의 경우 향상 경로가 더 쉽습니다.

#include <boost/filesystem/path.hpp>

namespace fs = boost::filesystem;

//s to w
std::string s = "xxx";
auto w = fs::path(s).wstring();

//w to s
std::wstring w = L"xxx";
auto s = fs::path(w).string();

std를 사용하려는 경우:

#include <filesystem>
namespace fs = std::filesystem;

//The same

c++ 이전 버전

#include <experimental/filesystem>
namespace fs = std::experimental::filesystem;

//The same

내부의 코드는 세부 사항을 풀 필요가 없는 변환기를 여전히 구현합니다.

큰 오버헤드가 없는 가장 단순한 옵션은 다음과 같습니다.

포함:

#include <atlbase.h>
#include <atlconv.h>

변환:

char* whatever = "test1234";
std::wstring lwhatever = std::wstring(CA2W(std::string(whatever).c_str()));

필요한 경우:

lwhatever.c_str();

문자열 towstring

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);
}

당신이 QT를 가지고 있고 당신이 사용할 수 있는 기능과 것들을 구현하기가 귀찮다면.

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

여기 모든 사람에게 효과가 없을 수도 있는 저의 가장 기본적인 해결책이 있습니다.하지만 많은 사람들에게 효과가 있을 것입니다.

가이드라인 지원 라이브러리를 사용해야 합니다.많은 C++ 위원회 저자들이 설계한 꽤 공식적인 C++ 라이브러리입니다.

    std::string to_string(std::wstring const & wStr)
    {
        std::string temp = {};

        for (wchar_t const & wCh : wStr)
        {
            // If the string can't be converted gsl::narrow will throw
            temp.push_back(gsl::narrow<char>(wCh));
        }

        return temp;
    }

제 기능은 가능하면 변환을 허용하는 것뿐입니다.그렇지 않으면 예외를 설정합니다.

gsl::sl을 사용하여 (https://github.com/isocpp/CppCoreGuidelines/blob/master/CppCoreGuidelines.md#es49-if-you-must-use-a-cast-use-a-named-cast) .

방법 s2ws는 잘 작동합니다.희망이 도움이 됩니다.

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;
}

자체 테스트(윈도우즈 8, vs 2010)에 따르면 mbstowcs는 실제로 원래 문자열을 손상시킬 수 있으며 ANSI 코드 페이지에서만 작동합니다.MultiByteToWideChar/WideCharToMultiByte도 문자열 손상을 일으킬 수 있지만, 모르는 문자는 '?' 물음표로 대체하는 경향이 있지만, mbstowcs는 알 수 없는 문자와 마주치면 중지되고 바로 그 지점에서 문자열을 자릅니다.(핀란드 창에서 베트남 문자를 테스트했습니다.)

따라서 아날로그 ansi C 기능보다 Multi*windows api 기능을 선호합니다.

또한 한 코드 페이지에서 다른 코드 페이지로 문자열을 인코딩하는 가장 짧은 방법은 MultiByteToWideChar/WideCharToMultiByte API 함수 호출이 아니라 아날로그 ATL 매크로를 사용하는 것입니다.W2A / A2W.

따라서 위에서 언급한 아날로그 기능은 다음과 같이 들립니다.

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

_acp는 USES_CONVERSION 매크로에서 선언됩니다.

또는 이전 데이터를 새 데이터로 변환할 때 자주 놓치는 기능:

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

   _acp = CP_UTF8;
   return W2A( pw );
}

그러나 이러한 매크로는 W2A 또는 A2W 매크로를 사용한 후 동일한 기능에 대한 루프 또는 재귀 루프에 사용하지 마십시오. 따라서 스택은 일시적인 변환으로부터 자유로워집니다.

std::string -> wchar_t[]안전하게mbstowcs_s함수:

auto ws = std::make_unique<wchar_t[]>(s.size() + 1);
mbstowcs_s(nullptr, ws.get(), s.size() + 1, s.c_str(), s.size());

이것은 나의 샘플 코드입니다.

이 코드를 사용하여 문자열을 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;
}

string s = "おはよう";오류입니다.

wstring을 직접 사용해야 합니다.

wstring ws = L"おはよう";

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