Problem char* zu wchar_t*
-
Hi
Ich weiss, wenn man den Titel dieses Threades bei Google eingibt,
erhält man ziemlich viele Treffer, doch irgendwie gehts bei mir nicht.
Ich versuch nun schon lange char* -> wchar_t* zu konvertieren.Möglichst einfach und sicher.
Jetzt hab ich es fast geschafft:
wchar_t* CharToWide(char* source) { size_t sourcesize = strlen(source) + 1; const size_t newsize = 100; size_t convertedChars = 0; wchar_t wcstring[newsize]; mbstowcs_s(&convertedChars, wcstring, sourcesize, source, _TRUNCATE); return wcstring; } int main() { char* orig = "Lol Lol Lol"; Print(CharToWide(orig)); }Ich erhalte aber immer nur "Lo". Die ersten zwei Zeichen.
Wenn ich aber nicht die Funktion benütze, sondern alles nacheinander
schreibe, dann gehts.
Kann mir das mal einer erklären?
Und was mach ich denn falsch?mfg
vampir26
-
Du gibst einen Pointer auf eine lokale Variable zurück. Das ist undefiniert.
Benutze doch als Rückgabewert std::wstring und als Argument std::string.An einen C- String der std::string bzw. std::wstring Objekte kommst Du mit std::string::c_str() bzw. std::wstring::c_str().
Simon
-
Du gibst einen Zeiger auf ein lokales Objekt zurück -> undefiniertes Verhalten.
Außerdem ist mbstowcs_s Windows-spezifisch, also gehört das ganze ins WinAPI-Forum. Ein C++-Weg, das zu machen, wäre beispielsweise
#include <string> std::wstring widen(std::string const &s) { return std::wstring(s.begin(), s.end()); }einen wchar_t const * kannst du dann mit c_str() nehmen. Wenn du einen variablen wchar_t-Buffer brauchst,
std::wstring ws = widen("foo"); wchar_t buf[LANG_GENUG]; std::copy(ws.begin(), ws.end(), buf);
-
Vielen Dank.
Funktioniert einwandfrei jetzt.
Machs jetzt rein c++, damit es Plattformunabhängig bleibt
.Obwohl ich noch nicht alles 100% begreife ^^
Ist kompliziert mit den ganzen Typen und Zeiger und blabla
-
Alle Container der Standardbibliothek haben einen sog. Range-Konstruktor. Dieser nimmt zwei Iteratoren (Positionsbezeichner) entgegen, die einen Bereich beschreiben. Das funktioniert so lange, wie die Werte innerhalb dieses Bereiches in die Werte des Containers konvertibel sind.
Etwa kann ich so:
char hello[] = "Hello, world!"; std::string s(hello, hello + 13); std::string s2(s.begin(), s.end());Strings erstellen, die "Hello, world!" enthalten. Auch kann ich so:
std::vector<int>(s.begin(), s.end());einen Integer-Vektor erstellen, der die ASCII-Werte der Buchstaben in s enthält, weil char in int umwandelbar ist. Da char ebenfalls in wchar_t (den Werttyp eines std::wstring) umwandelbar ist, kann ich auf die gleiche Weise
std::wstring ws(s.begin(), s.end());schreiben und einen wstring erstellen, dessen Inhalt dem von s entspricht. Das Ergebnis ist das selbe, als hätte ich
std::wstring(s.size()); for(std::size_t i = 0; i < s.size(); ++i) { ws[i] = s[i]; }geschrieben.
Bei komplexen Datentypen gibt es Feinheiten mit Konstruktoren und Zuweisungsoperatoren zu beachten, aber ich hoffe, dass die grundlegende Idee damit klar geworden ist.
-
Thx für die Erläuterung.
Jetzt versuche ich gerade die ganze Zeit alles noch in eine einzige Funktion zu packen.
So, dass ich char* übergebe und wchar_t* erhalte. Ohne Zwischenstation.Ich verwende die Irrlicht Engine mit der RakNet Engine, sende Pakete mache ein
ganzes Login System - alles kein Problem, aber ein paar Variablen zu konvertieren
Ich bekomme dauernd Warnungen, dass die Variable unsicher ist und blabla
Ich werd die Funktion sehr oft nutzen und deshalb ist es wichtig, dass die
wirklich klappt.
-
Das ist der Code:
wchar_t* ConvertCharToWidechar(std::string const &s) { std::wstring temp = std::wstring(s.begin(), s.end()); wchar_t* dest = new wchar_t[strlen(s.c_str())]; std::copy(temp.begin(), temp.end(), dest); return dest; }Muss ich jetzt den Speicher der Variable dest wieder freigeben? Ich bekomm nähmlich die Warnung:
warning C4996: 'std::copy': Function call with parameters that may be unsafe - this call relies on the caller to check that the passed values are correct. To disable this warning, use -D_SCL_SECURE_NO_WARNINGS.Funktionieren tuts im moment gut, aber wird dann später schwierig den Fehler zu finden, wenn plötzlich was nicht mehr funzt.
Thx für hilfe

-
Der Compiler sagt dir lediglich, das die Funktion copy unsicher ist. D.h. es kann zu Buffer-Überläufen kommen. Sicherlich hast du davon schon in diversen Security-Meldungen auf heise.de und anderen Seiten gelesen, wenn mal wieder Windows, Linux, Firefox u.a. gepatcht werden müssen... wegen Buffer-Overflows.
MS hat sich aber damals verpflichtet, gegen solche unsicheren Funktionen vorzugehen. Auch für ihre eigenen Inhouse-Entwickler! Genau deshalb kommen solche Meldungen von MS-Compiler, weil man unsichere C-Funktionen verwendet! Andere Compiler melden so was nicht.
Entweder du benutzt eine sichere Funktion, oder du schaltest die Warnung ab, weil du der Meinung bist, das du es besser weißt. Und wie das geht, steht sogar am Ende der Warning-Meldung. Machen mußt du es aber selber.

Übrigens hilft die MSDN bei Warning und Error Meldungen immer weiter, in dem man Fehlercode (in disem Fall C4996) eingibt:
http://msdn.microsoft.com/en-us/library/ttcz0bys.aspx
-
Du musst alles wieder freigeben, was du mit new anforderst. Faustregel: Zu jedem new ein delete, zu jedem new[] ein delete[]. Wenn es überhaupt möglich ist, nimm am besten std::string und std::wstring, die übernehmen die Speicherverwaltung für dich.
Was die Warnung angeht, die kannst du getrost ignorieren (bzw. das angegebene Makro in die Projekteigenschaften aufnehmen). Microsoft hat seit MSVC 2005 eine Reihe von nicht standardisierten Funktionen, die im Grunde das gleiche wie Standardfunktionen machen, aber anderes Fehlerbehandlungsverhalten haben. In einigen Fällen ist das sinnvoll, beispielsweise gets und strcpy, allerdings gibt es dafür in nahezu allen Fällen standardisierte Funktionen, die deren Probleme behandeln (gets -> fgets, strcpy -> strncpy).
Das Problem damit ist, dass MSVC mit ziemlich bei den Haaren herbeigezogenen Begründungen über nicht weiter gefährliche Funktionen warnt. Es ist ohne die *_SECURE_NO_WARNINGS-Makros nahezu unmöglich, standardkonformen C++-Code (oder auch C-Code) zu schreiben, über den MSVC sich nicht beschwert. Im Falle von std::copy kannst etwa du Probleme kriegen, wenn du dich sehr dämlich anstellst, beispielsweise
std::string s = "foo", s2 = "bar", s3; // Iteratoren von zwei verschiedenen Containern als Bereichsbegrenzungen, // d.h. KAWUMM! std::copy(s.begin(), s2.end(), std::back_inserter(s3));Natürlich kann man die _s-Funktionen auf ähnliche Weisen auch zu Blödsinn überreden, ein Gewinn ist damit also an dieser Stelle nicht wirklich zu haben.
Ich habe den Verdacht, dass dahinter vor allem das Bestreben steht, Programmierer dazu zu erziehen, nur unter Windows lauffähigen Code zu schreiben.