WINAPI und LPWCH, LPCH, LPCWSTR, LPCSTR.... ?!



  • CStoll schrieb:

    Es gibt drei verschiedene Zeichensätze - ANSI (1 Byte Zeichen), MULTIBYTE (variable Zeichengröße) und UNICODE (2 Byte). Allerdings werden die ersten beiden Varianten beide durch char's abgebildet und von vielen Funktionen identisch behandelt.

    Wie kommst Du darauf, dass Unicode 2 Byte sind...

    Unicode als solches definiert nur Codepoints. Diese gehen bis U+10FFFF
    Brauchen also min. 3 Bytes...
    Siehe:
    http://www.fileformat.info/info/unicode/block/index.htm

    I.d.R. wird aber Unicode in einer bestimmten Codierung verwendet. Windows verwendet UTF-16 (ursprünglich UCS2). Viele Unix-Varianten verwenden UTF-8. Beides sind Multibyte-Character-Sets.

    Der einzige nicht Multi-Byte-Character-Set ist UTF-32. Hier kann der Unicode-Zeichensatz (bzw. die Codepoints) direkt abgebildet werden.

    Das ganze heisst aber nicht, dass z.B. ein "ä" aus nur einem Codepoint bestehen muss... ein "ä" kann auch aus mehreren Codepoints bestehen... somit ist auch ein nicht-MBCS keine Garantie dafür, dass man Zeichen direkt findet, die man sucht... aber das war ja nicht das Thema 😉



  • Jochen Kalmbach schrieb:

    CStoll schrieb:

    Es gibt drei verschiedene Zeichensätze - ANSI (1 Byte Zeichen), MULTIBYTE (variable Zeichengröße) und UNICODE (2 Byte). Allerdings werden die ersten beiden Varianten beide durch char's abgebildet und von vielen Funktionen identisch behandelt.

    Wie kommst Du darauf, dass Unicode 2 Byte sind...

    Schlecht geraten und ungenau formuliert (außerdem hat meine Erinnerung für diese Details etwas nachgelassen, seitdem ich micht nicht mehr so oft damit beschäftigen muß).



  • Warum braucht man eigentlich überhaupt so viele Datentypen, wenn es zu fast jedem ein Äquivalent gibt? 😕 Ich meine irgendwo gelesen zu haben, dass DWORD, LPSTR, LPCSTR, etc. von den C-Programmierern übernommen wurden, aber das kann doch unmöglich die Erklärung dafür sein... Wenn man sich die Definitionen der Datentypen anschaut... das ist doch alles doppelt (und manchmal dreifach) gemoppelt..
    Ich meine wozu braucht man PINT wenn's int * bereits gibt?;



  • [Rewind] schrieb:

    Warum braucht man eigentlich überhaupt so viele Datentypen, wenn es zu fast jedem ein Äquivalent gibt? 😕 Ich meine irgendwo gelesen zu haben, dass DWORD, LPSTR, LPCSTR, etc. von den C-Programmierern übernommen wurden, aber das kann doch unmöglich die Erklärung dafür sein... Wenn man sich die Definitionen der Datentypen anschaut... das ist doch alles doppelt (und manchmal dreifach) gemoppelt..
    Ich meine wozu braucht man PINT wenn's int * bereits gibt?;

    Die Frage habe ich mir auch gestellt. Es ist aber nun mal so, dass das meiste noch Überreste aus der 16-Bit-Ära sind, die, um abwärtskompatibilität zu garantieren, drinne sind.



  • Hallo nochmal,

    also auch wenn das jetzt ein bisschen off-topic ist, ich bin seit 2 Jahren als C# Entwickler für Windows-Applikationen tätig und hab auch schon einige Sachen in Java geschrieben. Aber C++ autodidaktisch zu lernen ist echt der absolute Horror.
    Ich komm mir vor als hätte ich noch nie was programmiert. Und die msdn-library ist absolut nicht mein Freund. Ich mein die Doku da ist echt ein bisschen für den .... Es gibt so viele Libraries, für viele gleich mehrere, ein paar noch in C geschrieben... was benutz ich wann. (Bspl. <string> und "String.h").
    Wie 2 Beiträge über mir schon erwähnt, kommt noch erschwerend hinzu, dass es für jeden Datentyp 2 oder mehr "Bezeichungen" gibt.
    Mittlerweile bin ich soweit, dass ich mir wohl ein Buch kaufen werde... Die Grundlagen der Sprache zu lernen war ja kein Problem, aber mit der WINAPI komm ich echt nur schwer voran. Zumindest alles was über WinMain und die Nachrichtenschleife hinausgeht. Im Netz gibts da ja auch nicht wirklich was dazu. 😡

    Ach ja, und nochmal zum Thema:
    Ich hab jetzt in meinem "Lern"-Projekt versucht, meine strings die ich mit WINAPI-Funktionen austauschen muss, als TCHAR zu definieren.
    Wobei ich bei den einfachsten Sachen wieder auf Probleme stoße.
    Bspl. Ich definiere eine variable TCHAR* path und lass mir diese über GetModuleFileName(..) füllen. Funktioniert auch wunderbar. Jetzt würd ich path aber noch gerne abändern mit ein paar Funktionen aus der "String.h" strcpy und so... Jetzt erwarten diese aber wieder eine variable vom Typ char*...

    So, Noobfrage: Ich denke hier muss ich wohl casten, oder?
    Wenn ja, wie? 😕

    Danke an alle die sich meinen kleinen Erguss hier durchlesen und
    vll noch Ihren Senf dazugeben!



  • evilplayground schrieb:

    Hallo nochmal,
    Mittlerweile bin ich soweit, dass ich mir wohl ein Buch kaufen werde... Die Grundlagen der Sprache zu lernen war ja kein Problem, aber mit der WINAPI komm ich echt nur schwer voran. Zumindest alles was über WinMain und die Nachrichtenschleife hinausgeht. Im Netz gibts da ja auch nicht wirklich was dazu. 😡

    Ach ja, und nochmal zum Thema:
    Ich hab jetzt in meinem "Lern"-Projekt versucht, meine strings die ich mit WINAPI-Funktionen austauschen muss, als TCHAR zu definieren.
    Wobei ich bei den einfachsten Sachen wieder auf Probleme stoße.

    Da sag ich nur: geht mir genau so!
    Nun zu deinem kleinen Problem. Von String zu char* kannst du auch so casten (dürfte aber nicht allzu schwer zu finden sein...):

    string sMyStr;
    char* cCharArray= new char[sMyStr.size() + 1];
    
    //dann Inhalt mit strcpy() übergeben
    strcpy(m_cCharArray, sMyStr.c_str(), sMyStr.size());
    

    Rewind



  • Ich habe vor längerem mal Hilfsklassen gemacht, welche das Konvertieren von Unicode nach Multibyte und umgekehrt übernehmen:

    Oberster Post von mir (StringUtil.h und cpp):
    http://www.c-plusplus.net/forum/260205-10

    Hier noch einige Hinweise:
    Erster Post von mir:
    http://www.c-plusplus.net/forum/276277

    Falls die Benutzung unklar ist, bitte hier nachfragen.



  • Danke Rewind,

    Sehr schön! Mittlerweile seh ich den Wald vor lauter Bäumen nicht mehr.
    Ich glaub ich sollte mal ne Pause machen 😉

    @theta:
    Ich werd mir das bei Gelegenheit zu Gemüte führen,
    aber danke schon mal dafür! Ich denk die werden mir sicher gute Dienste leisten.

    evilplayground



  • evilplayground schrieb:

    So, Noobfrage: Ich denke hier muss ich wohl casten, oder?
    Wenn ja, wie? 😕

    Casten? Ist keine Noob-Frage.

    Von Multibyte in Wide-Char umwandeln ist nicht so einfach. Da brauchst du gar nicht an:

    wchar_t*MyWideString=L"Jupidu";
    char*MyMultiString=(char*)MyWideString;
    

    zu denken (für den Fall, dass du noch von C# verwöhnt bist, was die Strings angeht). Auch strcpy kannst du vergessen, nimm lieber WideCharToMultiByte und MultiByteToWideChar .



  • evilplayground schrieb:

    Ach ja, und nochmal zum Thema:
    Ich hab jetzt in meinem "Lern"-Projekt versucht, meine strings die ich mit WINAPI-Funktionen austauschen muss, als TCHAR zu definieren.
    Wobei ich bei den einfachsten Sachen wieder auf Probleme stoße.
    Bspl. Ich definiere eine variable TCHAR* path und lass mir diese über GetModuleFileName(..) füllen. Funktioniert auch wunderbar. Jetzt würd ich path aber noch gerne abändern mit ein paar Funktionen aus der "String.h" strcpy und so... Jetzt erwarten diese aber wieder eine variable vom Typ char*...

    So, Noobfrage: Ich denke hier muss ich wohl casten, oder?
    Wenn ja, wie? 😕

    Afair gab es für die string.h-Funktionen auch Hilfsmakros (z.B. _tcslen()), die je nach Setting entweder auf die char- oder wchar_t-Version umgeleitet werden.



  • Glühbirne schrieb:

    evilplayground schrieb:

    So, Noobfrage: Ich denke hier muss ich wohl casten, oder?
    Wenn ja, wie? 😕

    Casten? Ist keine Noob-Frage.

    Von Multibyte in Wide-Char umwandeln ist nicht so einfach. Da brauchst du gar nicht an:

    wchar_t*MyWideString=L"Jupidu";
    char*MyMultiString=(char*)MyWideString;
    

    zu denken (für den Fall, dass du noch von C# verwöhnt bist, was die Strings angeht). Auch strcpy kannst du vergessen, nimm lieber WideCharToMultiByte und MultiByteToWideChar .

    Das war in der Tat das Erste, was ich versucht habe 😉
    Hab mir jetzt mal die beiden Funktionen aus deinem Vorschlag angesehen und
    es funktioniert tadellos. Für mich sieht die ganze Casterei zwar immer nach ein bisschen overhead aus, da ich nur strings und chars gewöhnt bin, und damit auch nur Methoden und Klassen die solche als Parameter erwarten. Aber damit muss ich wohl leben.

    Trotzdem, wie oben schon gesagt, die beiden Funktionen waren genau das was ich gesucht und gebraucht hab. Danke!

    evilplayground



  • CStoll schrieb:

    evilplayground schrieb:

    Ach ja, und nochmal zum Thema:
    Ich hab jetzt in meinem "Lern"-Projekt versucht, meine strings die ich mit WINAPI-Funktionen austauschen muss, als TCHAR zu definieren.
    Wobei ich bei den einfachsten Sachen wieder auf Probleme stoße.
    Bspl. Ich definiere eine variable TCHAR* path und lass mir diese über GetModuleFileName(..) füllen. Funktioniert auch wunderbar. Jetzt würd ich path aber noch gerne abändern mit ein paar Funktionen aus der "String.h" strcpy und so... Jetzt erwarten diese aber wieder eine variable vom Typ char*...

    So, Noobfrage: Ich denke hier muss ich wohl casten, oder?
    Wenn ja, wie? 😕

    Afair gab es für die string.h-Funktionen auch Hilfsmakros (z.B. _tcslen()), die je nach Setting entweder auf die char- oder wchar_t-Version umgeleitet werden.

    Ok, hab mir jetzt kurz mal die TCHAR.h angesehen und du hast Recht!
    Was soll ich jetzt am besten benutzen? Ich tendier zu den Funktionen aus TCHAR.h
    weils schöner aussieht und ich nicht jedesmal rumcasten muss, bzw das casten auf ein minimum reduzieren kann.

    evilplayground



  • CStoll schrieb:

    Afair gab es für die string.h-Funktionen auch Hilfsmakros (z.B. _tcslen()), die je nach Setting entweder auf die char- oder wchar_t-Version umgeleitet werden.

    Nur eine kleine ergänzende Bemerkung: aus demselben Grund (einstellungsunabhängige Verwendung) sollte man den Datentyp TCHAR den anderen zwei (char und wchar_t) vorziehen.



  • evilplayground schrieb:

    Für mich sieht die ganze Casterei zwar immer nach ein bisschen overhead aus, da ich nur strings und chars gewöhnt bin, und damit auch nur Methoden und Klassen die solche als Parameter erwarten. Aber damit muss ich wohl leben

    Das hat nun mal seinen Grund. C ist eine schnelle, systemnahe Sprache (meine sogar, mich erinnern zu können, dass man mit dem Befehl asm Assemblercode in C-Code einfügen kann), und deshalb muss man sich auch stark mit dem jeweiligen System beschäftigen. Der Vorteil einer solchen Sprache kommt vor allem bei großen Projekten (wie zum Beispiel Grafik-Engines) hervor, denn diese sind sehr viel schneller als z.B. eine Engine in C# oder Visual Basic (:D stellt euch das mal vor).

    Wenn man speicherschonend programmieren will, sollte man bei Multibytes bleiben, denn dort kann man sicher sein, dass JEDES Byte gebraucht wird - im Gegensatz zu Wide-Char, wo oft nur ein Byte gebraucht wird und der Rest hinten dranhängt. Für die Lokalisierung kannst du dann einfach die Codepage wechseln und eine neue Stringtable anlegen, die die Zeichen arbeitet ... glaube ich zumindest. Ich beherrsche zwar ein bisschen japanisch, aber eine Lokalisierung musste ich noch nicht schreiben - ich stelle mir aber vor, dass es die reine Folter ist, denn ich meine gelesen zu haben, dass Codepage 932 nur japanische Kanji, aber Katakana und Hiragana nicht kennt. Und japanisch NUR in Kanji ... 😮

    Da ist Wide-Char besser. Dort hat jedes Zeichen einen Wert (manchmal sogar zwei), und auch die elbischen Zeichen von J.R.R.Tolkien sind dort definiert. Nix mit verrückten Codepagewechsel, einfach den Mischmasch aus japanischem Brei da rein und fertig. Allerdings wird dies für die meisten Alphabete bis zu 50% Speicher verschwenden (bei 2 Byte, es gibt aber noch UTF-32 ... rechne es dir selbst aus, ich meine gelesen zu haben, dass nur 27% des Speichers so gebraucht wird). Bei einem großen Projekt mit einer riesigen Stringtable ... nochmal 😮.

    Du musst also selbst entscheiden, was du verwenden willst. Das ist ja das Mächtige an C - du kannst auch Sachen machen, die unter normalen Umständen Unsinn, aber in einer gewissen Situation essenziell für ein Programm sind.


Anmelden zum Antworten