C++ Converteer string (of char*) naar wstring (of wchar_t*)

Hoe zou ik de inhoud van s aan ws toewijzen?

Google gezocht en enkele technieken gebruikt, maar ze kunnen de exacte inhoud niet toewijzen. De inhoud is vervormd.


Antwoord 1, autoriteit 100%

Ervan uitgaande dat de invoerreeks in uw voorbeeld (おはよう) een UTF-8-gecodeerd is (wat het niet is, zo te zien, maar laten we aannemen dat dit het geval is omwille van deze uitleg :-)) representatie van een Unicode-string van uw interesse, dan kan uw probleem volledig worden opgelost met alleen de standaardbibliotheek (C++11 en nieuwer).

De TL;DR-versie:

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

Langer online compileerbaar en uitvoerbaar voorbeeld:

(Ze laten allemaal hetzelfde voorbeeld zien. Er zijn er gewoon veel voor redundantie…)

Opmerking (oud):

Zoals aangegeven in de opmerkingen en uitgelegd in https://stackoverflow.com/a/17106065/6345daar zijn gevallen waarin het gebruik van de standaardbibliotheek om te converteren tussen UTF-8 en UTF-16 onverwachte verschillen in de resultaten op verschillende platforms kan opleveren. Overweeg voor een betere conversie std::codecvt_utf8zoals beschreven op http ://en.cppreference.com/w/cpp/locale/codecvt_utf8

Opmerking (nieuw):

Aangezien de codecvt-header is verouderd in C++17, zijn er enige zorgen geuit over de oplossing die in dit antwoord wordt gepresenteerd. De commissie voor C++-normen heeft echter een belangrijke verklaring toegevoegd in http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2017/p0618r0.htmlgezegde

deze bibliotheekcomponent moet worden teruggetrokken in bijlage D, naast , totdat een geschikte vervanging is gestandaardiseerd.

Dus in de nabije toekomst is de codecvt-oplossing in dit antwoord veilig en draagbaar.


Antwoord 2, autoriteit 22%

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

Antwoord 3, autoriteit 14%

Uw vraag is onvoldoende gespecificeerd. Strikt genomen is dat voorbeeld een syntaxisfout. Echter, mbstowcsis waarschijnlijk wat je zoekt.

Het is een C-bibliotheekfunctie en werkt op buffers, maar hier is een gebruiksvriendelijk idioom, met dank aan Mooing Duck:

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

4, Autoriteit 5%

Van char*naar wstring:

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

Van stringnaar wstring:

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

Let op: dit werkt alleen goed als de string die wordt geconverteerd alleen ASCII-tekens bevat.


Antwoord 5, autoriteit 3%

met behulp van Boost.Locale:

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

Antwoord 6, autoriteit 3%

Deze variant ervan is mijn favoriet in het echte leven. Het converteert de invoer, indien geldigUTF-8, naar de respectievelijke wstring. Als de invoer beschadigd is, wordt de wstringopgebouwd uit de enkele bytes. Dit is erg handig als u niet echt zeker kunt zijn van de kwaliteit van uw invoergegevens.

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

Antwoord 7

U kunt het boostpad of het standaardpad gebruiken; wat een stuk makkelijker is.
boost-pad is gemakkelijker voor platformonafhankelijke toepassingen

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

als je std wilt gebruiken:

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

c++ oudere versie

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

De code erin implementeert nog steeds een converter waarvan u de details niet hoeft te ontrafelen.


Antwoord 8

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

Antwoord 9

Als je QT hebt en als je lui bent om een ​​functie en zo te implementeren die je kunt gebruiken

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

Antwoord 10

std::string -> wchar_t[]met veilige mbstowcs_sfunctie:

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

Dit is van mijn voorbeeld code


Antwoord 11

methode s2ws werkt goed. Hoop helpt.

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

Antwoord 12

Op basis van mijn eigen testen (op Windows 8, vs2010) kunnen mbstowcs de originele string beschadigen, het werkt alleen met de ANSI-codepagina. Als MultiByteToWideChar/WideCharToMultiByte ook stringcorruptie kan veroorzaken – maar ze hebben de neiging om tekens die ze niet kennen te vervangen door ‘?’ vraagtekens, maar mbstowcs heeft de neiging om te stoppen wanneer het een onbekend teken tegenkomt en op dat moment de string doorknipt. (Ik heb Vietnamese karakters getest op Finse vensters).

Geef dus de voorkeur aan Multi*-windows api-functie boven analoge ansi C-functies.

Wat me ook is opgevallen, de kortste manier om een ​​string van de ene codepagina naar de andere te coderen, is niet het gebruik van MultiByteToWideChar/WideCharToMultiByte api-functieaanroepen, maar hun analoge ATL-macro’s: W2A / A2W.

Dus analoge functie zoals hierboven vermeld zou klinken als:

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

_acp is gedeclareerd in de macro USES_CONVERSION.

Of ook functie die ik vaak mis bij het uitvoeren van oude gegevensconversie naar nieuwe:

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

Maar merk op dat die macro’s zwaar stapelen – gebruik geen for-lussen of recursieve lussen voor dezelfde functie – na gebruik van W2A- of A2W-macro – het is beter om zo snel mogelijk terug te keren, zodat de stapel wordt bevrijd van tijdelijke conversie.

>


Antwoord 13

Voor mij is de meest ongecompliceerde optie zonder grote overhead:

Opnemen:

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

Converteren:

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

Indien nodig:

lwhatever.c_str();

Antwoord 14

Hier is mijn supereenvoudige oplossing die misschien niet voor iedereen werkt. Maar zou voor veel mensen werken.

Het vereist het gebruik van de Guideline Support Library.
Dat is een vrij officiële C++-bibliotheek die is ontworpen door veel auteurs van de C++-commissie:

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

Alles wat mijn functie doet, is de conversie toestaan, indien mogelijk. Gooi anders een uitzondering.

Via het gebruik van gsl::narrow (https://github.com/isocpp/CppCoreGuidelines/blob/master/CppCoreGuidelines.md#es49-if-you-must-use-a-cast- use-a-named-cast)


Antwoord 15

gebruik deze code om je string naar wstring te converteren

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

Antwoord 16

string s = "おはよう";is een fout.

Je moet wstring direct gebruiken:

wstring ws = L"おはよう";

Other episodes