NES-Spieler
Mitglied
Benutzerprofil
Anmeldungsdatum: 27.02.2006
Beiträge: 1286
string und wstring ineinander umwandeln
14:36:54 25.12.2006
|
Zitieren
|
Wie das unter Windows geht, weiß ich schon, doch nun würde mich mal interessieren: Wie wandle ich mit Standard-C++ einen std::string in einen std::wstring um und umgekehrt? |
|
|
David_pb
Mitglied
Benutzerprofil
Anmeldungsdatum: 09.10.2005
Beiträge: 1999
17:17:29 25.12.2006
|
Zitieren
|
Hier wurde mal ein wunderbarer Codeschnippsel gepostet:
C++: | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 | /* string2wstring.h */
#pragma once
#include <string>
#include <vector>
#include <locale>
#include <functional>
#include <iostream>
// Put this class in your personal toolbox...
template<class E,
class T = std::char_traits<E>,
class A = std::allocator<E> >
class Widen : public std::unary_function<
const std::string&, std::basic_string<E, T, A> >
{
std::locale loc_;
const std::ctype<E>* pCType_;
// No copy-constructor, no assignment operator...
Widen(const Widen&);
Widen& operator= (const Widen&);
public:
// Constructor...
Widen(const std::locale& loc = std::locale()) : loc_(loc)
{
#if defined(_MSC_VER) && (_MSC_VER < 1300) // VC++ 6.0...
using namespace std;
pCType_ = &_USE(loc, ctype<E> );
#else
pCType_ = &std::use_facet<std::ctype<E> >(loc);
#endif
}
// Conversion...
std::basic_string<E, T, A> operator() (const std::string& str) const
{
typename std::basic_string<E, T, A>::size_type srcLen =
str.length();
const char* pSrcBeg = str.c_str();
std::vector<E> tmp(srcLen);
pCType_->widen(pSrcBeg, pSrcBeg + srcLen, &tmp[0]);
return std::basic_string<E, T, A>(&tmp[0], srcLen);
}
};
// How to use it...
int main()
{
Widen<wchar_t> to_wstring;
std::string s = "my test string";
std::wstring w = to_wstring(s);
std::wcout << w << L"\n";
} | |
grüße |
|
|
NES-Spieler
Mitglied
Benutzerprofil
Anmeldungsdatum: 27.02.2006
Beiträge: 1286
17:36:05 25.12.2006
|
Zitieren
|
Das ist nicht Dein Ernst, oder? Es muß doch eine Möglichkeit geben, das ganze umzuwandeln, ohne dieses ganze Zeug da zu machen und eine komplett neue Klasse zu benutzen. Ist das wirklich derartig kompliziert? |
|
|
David_pb
Mitglied
Benutzerprofil
Anmeldungsdatum: 09.10.2005
Beiträge: 1999
17:49:11 25.12.2006
|
Zitieren
|
Hier und da könnte man das evtl etwas vereinfachen. Aber im Grund bleibt es sich gleich. Unicode ist halt kein einfaches Thema und einfach von char zu wchar_t casten reicht eben nicht aus. |
|
|
rüdiger
Moderator
Benutzerprofil
Anmeldungsdatum: 11.07.2001
Beiträge: 23086
18:24:01 25.12.2006
|
Zitieren
|
steht in der FAQ |
_________________ .
|
|
Artchi
Autor
Benutzerprofil
Anmeldungsdatum: 16.03.2002
Beiträge: 9131
22:16:45 25.12.2006
|
Zitieren
|
Was stört dich denn an der Methode? Nur weil du die Implementierung siehst, findest du sie nicht ernsthaft? Wer sagt dir denn, das andere Konvertierungen, wo du die Implementierungen nicht siehst, besser sind???
Leg die string2wstring.h in dein Library-Verzeichnis, und schon kannst du es wie jede andere Library einfach benutzen. Die Benutzung beschränkt sich nur auf ZWEI Zeilen!!! Und das ist nicht aufwändig. Oder glaubst du, das cout << "Hallo" auch kurz ist? Du kennst nur die Implementierung nicht. SOnst würdest du dich auch ganz schön wundern, was alles im Hintergrund passiert, bis dein Hallo in der Windows- oder Linux-Konsole erscheint. |
_________________ http://www.kharchi.eu
|
|
entfrickelt
Unregistrierter
22:47:08 25.12.2006
|
Zitieren
|
C++: | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | #include <iostream>
#include <string>
#include <vector>
#include <locale>
std::wstring convertStringToWstring(const std::string& str)
{
const std::ctype<wchar_t>& CType = std::use_facet<std::ctype<wchar_t> >(std::locale());
std::vector<wchar_t> wideStringBuffer(str.length());
CType.widen(str.data(), str.data() + str.length(), &wideStringBuffer[0]);
return std::wstring(&wideStringBuffer[0], wideStringBuffer.size());
}
int main()
{
std::wcout << convertStringToWstring("my test string") << L"\n";
} | |
|
|
|
balduin
Unregistrierter
01:48:50 26.12.2006
|
Zitieren
|
C++: | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | #include <string>
using namespace std;
int main()
{
wstring a(L"Hello String!");
wstring c;
string b;
const char* s = (const char*)a.c_str();
// Konvertieren von wstring nach string(a nach b)
for (int i = 0; *(s+i); i+=2)
b += *(s+i);
const char* y = b.c_str();
wchar_t x;
// Konvertieren von string nach wstring(b nach c)
for (int i = 0; *(y+i); i++){
x = (wchar_t)*(y+i);
c += x;
}
return 0;
} | |
:xmas1: |
|
|
rüdiger
Moderator
Benutzerprofil
Anmeldungsdatum: 11.07.2001
Beiträge: 23086
03:04:20 26.12.2006
|
Zitieren
|
balduin schrieb: | C++: | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | #include <string>
using namespace std;
int main()
{
wstring a(L"Hello String!");
wstring c;
string b;
const char* s = (const char*)a.c_str();
// Konvertieren von wstring nach string(a nach b)
for (int i = 0; *(s+i); i+=2)
b += *(s+i);
const char* y = b.c_str();
wchar_t x;
// Konvertieren von string nach wstring(b nach c)
for (int i = 0; *(y+i); i++){
x = (wchar_t)*(y+i);
c += x;
}
return 0;
} | |
:xmas1: |
nö! Das ist unportabler Blödsinn! |
_________________ .
|
|
camper
Moderator
Benutzerprofil
Anmeldungsdatum: 06.08.2004
Beiträge: 7363
05:50:28 26.12.2006
|
Zitieren
|
balduin schrieb: | C++: | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | #include <string>
using namespace std;
int main()
{
wstring a(L"Hello String!");
wstring c;
string b;
const char* s = (const char*)a.c_str();
// Konvertieren von wstring nach string(a nach b)
for (int i = 0; *(s+i); i+=2)
b += *(s+i);
const char* y = b.c_str();
wchar_t x;
// Konvertieren von string nach wstring(b nach c)
for (int i = 0; *(y+i); i++){
x = (wchar_t)*(y+i);
c += x;
}
return 0;
} | |
:xmas1: | das ist schrecklich und unportabel. Immerhin,wenn man tatsächlich weiß, dass der betreffende Wertebereich zwischen 0 und 127 liegt und es um eine Konvertierung ASCII <-> UNICODE geht (in diesem Bereich spielen locales keine Rolle), kann man das ganze vereinfachen:
C++: | 1 2 3 4 5 6 7 8 9 | #include <string>
using namespace std;
int main()
{
wstring a(L"Hello String!");
string b(a.begin(),a.end());
wstring c(b.begin(),b.end());
} | |
Das ist in etwa, was man naiverweise erwartet. In der Praxis ist das allerdings völlig unzureichend. Das unschöne an der gezeigten Lösung von David_pb ff. ist, dass sie in jedem Falle Kopien anlegt, abwohl bei vielen (den meisten?) Implementationen string seine Daten in einem Array speichert und data() und c_str() nur pointer auf diesen Datenbereich zurückgeben. Wenn man dies voraussetzen kann, lassen sich diese Kopien vermeiden. Es dürfte allerdings keinen portablen Weg geben, dieses Verhalten bereits beim Compilieren festzustellen, während der Laufzeit allerdings ist das möglich: da op[] ein echte Referenz zurückgeben muss, brauchen wir nur &s[0] mit data() vergleichen. Sind sie gleich, können wir auf einen eigenen Vektor zum zwischenspeichern verzichten.C++: | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 | template<class E, class T = std::char_traits<E>, class A = std::allocator<E> >
class Widen : public std::unary_function< const std::string&, std::basic_string<E, T, A> >
{
const std::ctype<E>& ctype_;
Widen(Widen&);
public:
typedef std::basic_string<E, T, A> > str_type;
Widen(const std::locale& loc = std::locale())
: ctype_(std::use_facet<std::ctype<E> >(loc))
{}
// Conversion...
str_type operator()(const std::string& str) const
{
// kl. Quizfrage: was machen wir, wenn string::size_type
// und str_type::size_type verschieden sind ? :)
typename str_type::size_type src_len = str.length();
const char* src_data = str.data();
if ( src_data == &str[0] )
{
str_type result( src_len, E() );
const E* p = result.data();
if ( p == &result[0] )
{
ctype_.widen(src_data, src_data + src_len, &result[0]);
return result;
}
}
// hier kann man noch weiter optimieren indem man etwa für
// hinreichend kleine strings ein array auf dem stack benutzt
std::vector<E> tmp(src_len);
ctype_.widen(src_data, src_data + src_len, &tmp[0]);
return str_type(&tmp[0], srcLen);
}
}; | |
|
Zuletzt bearbeitet von camper am 06:03:29 26.12.2006, insgesamt 2-mal bearbeitet
|
|
Alle Rechte vorbehalten.