Nasıl wstring dizeye dönüştürmek için?


204

Soru wstring'in dizeye nasıl dönüştürüleceğidir?

Sonraki örneğim var:

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

yorum satırı olmayan çıktı:

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

ama olmadan sadece:

std::wstring =    Hello

Örnekte yanlış olan bir şey var mı? Yukarıdaki gibi bir dönüştürme yapabilir miyim?

DÜZENLE

Yeni bir örnek (bazı cevapları dikkate alarak)

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

Çıktı:

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

bu nedenle dize akışı wstring'i dizeye dönüştürmek için kullanılamaz.


4
Kodlamaları da belirtmeden bu soruyu nasıl sorabilirsiniz?
David Heffernan

5
@tenfour: Neden std::wstringhiç kullanıyorsunuz ? stackoverflow.com/questions/1049947/…
dalle

11
@dalle UTF-16 ile önceden kodlanmış verileriniz varsa, UTF-16'nın zararlı olup olmadığı biraz tartışmalıdır. Değeri ne olursa olsun, herhangi bir dönüşüm formunun zararlı olduğunu düşünmüyorum; Zararlı olan şey, gerçekte anlamadıklarında Unicode'u anladıklarını düşünen insanlardır.
David Heffernan

2
Platformlar arası bir çözüm olması gerekiyor mu?
ali_bahoo

2
@dalle c ++ standardı utf'tan hiçbir şekilde bahsetmez (utf-8 veya utf-16). Utf-16'nın neden wstring ile kodlanamayacağını söyleyen bir bağlantı var mı?
BЈовић

Yanıtlar:


31

İşte diğer önerilere dayanan bir çözüm:

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

Bu genellikle Linux için çalışır, ancak Windows'ta sorun yaratır.


@Phillip: Kodun hangi kısmı c-yerel ayarına bağlıdır? olduğunu std::setlocale(LC_ALL, "");gerçekten gerekli?
smerlin

2
Kullanmak std::wcout.imbue(locale)da işi yapmalı ve herhangi bir küresel durumu değiştirmemesinin faydası var.
smerlin

32
std::wstring_convertC ++ bu gürültü bir sürü kadar 11 sarar.
Cubbi

7
@Philipp, "Windows'da sorun yaratacak" ne demek? Ne tür problemler?
Gili

1
Yukarıdaki kod verir (kopyalandığı gibi) bana bir *** glibc detected *** test: malloc(): smallbin double linked list corrupted: 0x000000000180ea30 ***linux 64-bit (gcc 4.7.3) verir. Bunu yaşayan başka biri var mı?
hogliux

313

Cubbi yorumların birinde belirttiği gibi, std::wstring_convert(C ++ 11) düzgün basit bir çözüm (Gerekirse sağlar #include <locale>ve <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 );

Ben wcstombsbu rastlamadan önce bir arada ve bellek sıkıcı tahsis / deallocation kullanıyordum.

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

Güncelleştirme (2013/11/28)

Bir gömlek şu şekilde ifade edilebilir (Yorumunuz için teşekkür ederim Guss):

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

Sarmalayıcı işlevleri şu şekilde ifade edilebilir: (Yorumunuz için teşekkürler 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);
}

Not: olmadığına bazı tartışmalara var string/ wstringreferans olarak ya da (nedeniyle 11 ve derleyici güncellemeleri ++ C) hazır bilgi olarak işlevlerine geçirilmelidir. Kararı uygulayan kişiye bırakacağım, ama bilmeye değer.

Not: std::codecvt_utf8Yukarıdaki kodda kullanıyorum, ancak UTF-8 kullanmıyorsanız, bunu kullandığınız uygun kodlamaya değiştirmeniz gerekir:

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


26
Lütfen +1 : Bu, dize dönüşümü yapmanın resmi C ++ standart yoludur. Diğer yolu dönüştürmek için from_bytes komutunu da kullanabilirsiniz. Şahsen tek gömlekleri sevdiğim için, işte benim versiyonum:std::wstring str = std::wstring_convert<std::codecvt_utf<wchar_t>>().from_bytes("some string");
Guss

7
Görünüşe göre en.cppreference.com/w/cpp/header/codecvt , g ++ 4.8.2 itibariyle mevcut değildir. İki s2ws ve ws2s yöntemi şu anda linux altında çalışmıyor
Begui

5
Bunun kullanımdan kaldırıldığı anlaşılıyor ( stackoverflow.com/a/42946556/211176 ). Bu kodu çalıştırmaya çalıştığımda derleyicim hata
veriyor


5
C ++ 17 ve daha fazla uyumluluktan endişe duyan herkes için (kullanımdan kaldırılma nedeniyle) bkz: stackoverflow.com/a/18597384/6205379
Timo

130

Çözüm: 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;

Dikkat olduğu hiçbir hiç burada devam karakter kümesi dönüştürme. Bunun yaptığı her bir yinelenenwchar_t bir karşı charbir kesiliyor dönüşüm -. Std :: string c'tor kullanır :

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

Yorumlarda belirtildiği gibi:

0-127 değerleri hemen hemen her kodlamada aynıdır, bu nedenle 127'den küçük olan kesme değerleri aynı metinde sonuçlanır. Çince bir karakter girin ve başarısızlığı göreceksiniz.

-

Windows kod sayfası 1252'nin 128-255 değerleri (Windows İngilizce varsayılanı) ve unicode'un 128-255 değerleri çoğunlukla aynıdır, bu nedenle kod sayfası kullanıyorsanız, bu karakterlerin çoğunun doğru değerlere kısaltılması gerekir. (Ben tamamen á ve õ çalışmasını bekledim, işteki kodumuzun yakında düzelteceğim é için buna bağlı olduğunu biliyorum)

Ve not aralığında kod noktaları olduğunu 0x80 - 0x9Fyılında Win1252 olacak değil çalışır. Bunlar arasında , œ, ž, Ÿ, ...


2
Tuhaf, bu Visual Studio 10 üzerinde çalışıyor. Neler oluyor? Bu, orijinal dizenin tüm öğeleri için wchar_t'tan char'a kısaltılmış bir atamaya neden olmalıdır.
Pedro Lamarão

6
... latin olmayan karakterlere gittiğinde.
JavaRunner

8
@ PedroLamarão: 0-127 değerleri hemen hemen her kodlamada aynıdır, bu nedenle 127'den küçük olan kesme değerleri aynı metinde sonuçlanır. Çince bir karakter girin ve başarısızlığı göreceksiniz.
Mooing Ördek

3
@ PedroLamarão: pencerelerin 128-255 1252 (Windows İngilizce varsayılan) Codepage değerler ve değerler unicode 128-255 olan çoğunlukla o kullandığınız teh kod sayfası var eğer öyleyse, aynı çoğu bu karakterlerin doğru şekilde kısaltılır edilmelidir değerler. (Ben tamamen á ve õ çalışmasını beklediğim, işte
kodumun

2
Harika çalışıyor. MSVS 2015 ve MSVS 2017 ve MINGW / g ++ ve clang ++. Yasal ++ 1.
Nikos

11

Yerel ayarları ve tüm bu fantezi şeyleri eklemek yerine, FACT için biliyorsanız, dizeniz dönüştürülebilir.

#include <iostream>
#include <string>

using namespace std;

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

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

Burada canlı örnek


2
+1 çünkü bazı senaryolar için çalışan basit bir çözümdür ("işlerin" gevşek bir tanımı için ekleyebilirim).
kuzgun

2
Namar0x0309'un çözümü ile neredeyse aynı şey, ki bu çok daha zarif bir IMHO. Ama bu sadece benim.
onitake

Aslında minimal değişiklik ;-)
rubenvb

9
-1 Bir wstring'iniz varsa, büyük olasılıkla çok baytlı karakterlerle uğraşıyorsunuz. Dizenin önemsiz bir şekilde dönüştürülebilir olduğunu bilseydiniz, ilk etapta bir wstring kullanamazsınız. Büyük olasılıkla, wstring'i düzgün bir şekilde ele almanızı bekleyen başka bir kütüphane ile uğraşıyorsunuz. Wchars'ı kesmek daha sonra izlemesi zor bir hata için yalvarıyor. Ayrıca, "string results (w.begin (), w.end ());" yapacaksanız, birçok yeniden tahsisi tetikleyebilecek bir döngüden kaçınmak için.
Kian

7

Resmi yol hala hala codecvtfacet facet gitmek için olduğuna inanıyorum (bir tür yerel ayar çeviri gerekir),

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

ya da bunun gibi bir şey varsa, etrafta çalışma kodum yok. Ama bu günlerde kaç kişinin bu makineleri kullandığından ve kaçının basitçe işaretçilerin hafızaya alınmasını ve ICU'nun veya başka bir kütüphanenin kanlı ayrıntılarla baş etmesine izin verdiğinden emin değilim.


7

Kodla ilgili iki sorun vardır:

  1. const std::string s( ws.begin(), ws.end() );Geniş karakterleri dar karşılıklarıyla doğru eşleştirmek için içeri dönüştürme gerekmez. Büyük olasılıkla, her geniş karakter sadece yazılır char.
    Bu sorunun çözümü, zaten verilmiştir kem tarafından cevap ve kapsar narrowyerelin işlevini ctypefaset.

  2. Her iki çıktı yazıyoruz std::coutve std::wcoutaynı programda. Hem coutve hem wcoutde aynı akışla ( stdout) ilişkilidir ve aynı akışı hem bayt yönelimli akış (olduğu coutgibi) hem de geniş yönlendirilmiş bir akış (olduğu wcoutgibi) olarak tanımlamanın sonuçları tanımlanmamıştır.
    En iyi seçenek, dar ve geniş çıktıyı aynı (altta yatan) akıma karıştırmaktan kaçınmaktır. İçin stdout/ cout/ wcout, sen yönünü değiştirme deneyin stdoutgeniş ve dar çıkış (veya tam tersi) arasında geçiş yapıldığında:

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

Evet, cout ve wcout kullanımı ile ilgili sorunu çözer.
21:21

7

Varsayılan kodlama açık:

  • Windows UTF-16.
  • Linux UTF-8.
  • MacOS UTF-8.

Bu kod std :: string'i std :: wstring ve std :: wstring'i std :: string'e dönüştürmek için iki biçime sahiptir. # WIN32 tanımlıysa, aynı sonucu alırsanız aynı sonucu alırsınız.

1. std :: dize 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'den std'ye :: 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'da WinAPI kullanarak unicode yazdırmanız gerekir.

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. Ana programda.

#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. Son olarak konsoldaki unicode karakterler için güçlü ve eksiksiz bir desteğe ihtiyacınız var. ConEmu öneriyorum ve Windows'ta varsayılan terminal olarak ayarlıyorum . Visual Studio'yu ConEmu'ya bağlamanız gerekir. Visual Studio'nun exe dosyasının devenv.exe olduğunu unutmayın

VC ++ ile Visual Studio 2017'de test edilmiştir; Std = C ++ 17.

Sonuç

Result1


6

Sadece ctype faset'in dar yöntemini doğrudan kullanabilirsiniz:

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

satır içi std :: string dar (std :: wstring const & text)
{
    std :: yerel ayar const loc ("");
    wchar_t const * from = text.c_str ();
    std :: size_t const len ​​= text.size ();
    std :: vektör <tampon> tampon (len + 1);
    std :: use_facet <std :: ctype <wchar_t>> (loc) .karrow (+ len, '_' ve tampondan [0] itibaren);
    return std :: string (& buffer [0] ve & buffer [len]);
}

6

Bu yanıtı yazarken, "string wstring dönüştürmek" için bir numaralı google araması sizi bu sayfaya yönlendirir. Cevabım bu gerçek soru DEĞİL olmasına rağmen, wstring dize dönüştürmek nasıl gösterir ve muhtemelen bu cevabı silmeliyim ama bu kötü form olarak kabul edilir. Şimdi bu sayfadan daha üst sıralarda yer alan bu StackOverflow yanıtına atlamak isteyebilirsiniz .


İşte dize, wstring ve karışık dize sabitlerini wstring ile birleştirmenin bir yolu. Wstringstream sınıfını kullanın.

#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
Bu dize dönüştürme için bir wstring değil
poitroae

1
@Michael Açıklayabilir misiniz? Peki ya yanlış? Yorumunuz daha fazla ayrıntı olmadan yararlı değildir.
Nate

1
bu bir wstring dönüşümü dizesidir. yani sorunun tam tersi.
Jeff McClintock

4

Sadece türleri dönüştürmenin yanı sıra, dizenin gerçek biçimi hakkında da bilinçli olmalısınız.

Çok baytlı karakter için derleme yaparken Visual Studio ve Win API UTF8 (aslında Windows-28591 olan Windows kodlaması) varsayar . Unicode Karakter
için derleme yaparken Visual studio ve Win API UTF16 varsayar.

Bu nedenle, dizeyi UTF16'dan UTF8 biçimine de dönüştürmelisiniz ve sadece std :: string'e dönüştürmemelisiniz.
Latin olmayan diller gibi çok karakterli biçimlerle çalışırken bu gerekli olacaktır.

Fikir, std::wstring her zaman UTF16'yı temsil ettiğine karar vermektir .
Ve std::string her zaman UTF8'i temsil eder .

Bu derleyici tarafından uygulanmıyor, sahip olmak daha iyi bir politika. UTF16 ( L ) ve UTF8 ( u8 ) tanımlamak için kullandığım dize öneklerine dikkat edin .

2 tür arasında dönüştürme yapmak için şunu kullanmalısınız: 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

Benim durumumda, çokbaytlı karakter (MBCS) kullanmak zorundayım ve std :: string ve std :: wstring kullanmak istiyorum. Ve c ++ 11 kullanamazsınız. Bu yüzden mbstowcs ve wcstombs kullanıyorum.

Ben new, delete [] kullanarak aynı işlevi yapmak, ama o zaman bu daha yavaş.

Bu nasıl yardımcı olabilir : Çeşitli Dize Türleri Arasında Dönüştürme

DÜZENLE

Ancak, wstring ve kaynak dizgiye dönüştürülmesi durumunda alfabe ve çoklu bayt dizesi yoksa, çalışmaz. Bu yüzden wcstombs'u WideCharToMultiByte olarak değiştiriyorum.

#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' yerine 'MultiByteToWideChar' kullanmak için DÜZENLE

#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 ile "wcstombs_s" i nasıl kullanabilirim? Çünkü bunun C ++ 11 özelliği olduğunu görüyorum.
cristian

@cristian Bu işlevin "güvensiz" sürümünü kullanabilirsiniz wcstombs().
Vizor

3

Bu çözüm dk123'ün çözümünden esinlenmiştir , ancak yerel ayara bağlı codecvt faseti kullanır. Sonuç, UTF-8 yerine yerel ayar kodlamalı dizede bulunur (yerel ayar olarak ayarlanmamışsa):

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

Onu arıyordum, ama bulamıyorum. Sonunda , doğru yazım işlevini std::localekullanarak doğru yönü alabileceğimi buldum std::use_facet(). Bu yardımcı olur umarım.


Vizor, yerel ayara bağlı yön ile dönüştürmenin avantajları (varsa) nelerdir?
Marc.2377

Sistemden dizelerle çalışıyorsanız, örneğin konsol girişinden.
Vizor

1

Başka birinin ilgilenmesi durumunda: her iki durumda da birbirinin yerine kullanılabilecek bir sınıfa ihtiyacım vardı. string veya wstringbeklenen . Aşağıdaki sınıf convertible_stringdayalı dk123 solüsyonu , ya bir ilklendirilebilirler string, char const*, wstringveya wchar_t const*ve ya bir karşı tarafından atanan veya örtülü olarak dönüştürülebilir stringveya wstring(ya aldığımız bir fonksiyonlarına böylece geçirilebilir).

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
Daha doğrusu bir depolamak istiyorum std::wstringmağazaya daha sınıfta std::stringve bir dönüşüm yapmak std::wstringbir almak gerektiğinde std::wstring. Çünkü std::wstringbiraz daha hızlı std::stringve daha uyumlu. Hatta daha fazla bellek tüketir std::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

Dize wstring dönüştürmek için aşağıdaki kullanıyorum.

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;

Standart bir başlık ( <string>) ve bir tanım eksik gibi görünüyor WideCharToMultiByte()- bu biraz sarıcı std::wctomb()mı?
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
lütfen cevabınızda ne yaptığınızı açıklayın, aksi takdirde silinebilir
CodeFanatic

1
UTF8string işlevi nereden geliyor?
Jean-Christophe Blanchard
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.