strings und sonderzeichen



  • hi,
    wie funktioniert denn das mit den sonderzeichen in einzelnen elementen von strings? folgendes beispiel:

    string Test = "ä";
    int Temp = Test[0];
    
    cout << Test << endl;				// gibt das ä ordentlich aus
    cout << Test[0] << ", " << Temp;	// gibt ein falsches zeichen und -61 aus
    

    wieso steht in Temp der wert -61? ein ä wäre doch laut der erweiterten ascii tabelle 132. und das faszinierendste: wenn ich das ä in ein ü, ö, ß oder anderes sonderzeichen ändere kommt immer -61 raus.
    das die ausgabe von Test[0] falsch ist, ist mir eigentlich nicht so schlimm da sie für mich keine relevanz hat . das einzige was ich brauche ist der richte ascii code aus Test[0].

    wie kriege ich den am besten raus?

    schonmal danke im vorraus



  • So richtig kann ich dir auch nicht weiterhelfen, aber ich bekomme für ä,ö,ü unterschiedliche Werte:
    ä = -28, ö = -10, ü=-4
    Und bei mir schaut generell einiges anders aus:

    cout << Test << endl;               // gibt ein Summenzeichen aus
    cout << Test[0] << ", " << Temp;    // gibt ein Summenzeichen und -28 aus
    

    Es ist sicherlich sinnvoll

    unsigned char Temp = Test[0];
    

    zu schreiben, denn dann bekommt man wenigstens die 228 zu sehen die dem Summenzeichen entspricht. Das Problem liegt übrigens nicht bei der Ausgabe (die ist bei mir ja auch wenigstens konsistent falsch) sondern wohl schon an den Compilereinstellungen. Denn wenn ich mir das Array im Debugger ansehe bereits nach dem Zuweisen der falsche Wert -28 an erster Stelle.
    Sieht man sich den AssemblerCode an für einen Code:

    string Test = "abcäöüää";
    -> ??_C@_08GIJGJEOK@abc?d?v?$PM?d?d?$AA@ DB 'abc', 0e4H, 0f6H, 0fcH, 0e4H, 0e4H
    

    Sieht man das bereits hier 228 = 0e4H für das ä geschrieben wird.
    Tja, weiter bin ich leider auch nicht gekommen, bin aber auch stark daran interessiert das mal hinzubekommen.



  • Normalerweise wird ein Programm mit der traditionellen C-Locale gestartet, dies entspricht einem Aufruf von:

    setlocale( LC_ALL, "C" );
    

    In diesem Set entspricht ein "ä" auch der 228 (0xE4) wie man sich in der M$ CharacterMap für 'Modern' ansehen kann. Dummerweise wird wohl für die Ausgabe eine CodePage verwendet, nämlich die 1252 -> die kann man auch setzen über:

    setlocale( LC_ALL, "" );         // setzt die Standardpage
    setlocale( LC_ALL, "Germany" );  // setzt German_Germany.1252
    

    Damit stimmt dann wenigstens die Ausgabe wieder.

    m.



  • sehr komisch.
    ich benutze als compiler g++ und bekomme immer -61 raus. welchen compiler benutzt du denn?
    die ergebnisse der andern forenbenutzer hier wären auch interessant, vielleicht kommt ja bei irgendwem was noch ganz anderes raus.

    den gedanken mit dem unsigned char hatt ich auch schon, die sache bringt aber mehr verwirrung als licht in die ganze sache.

    string Test = "ä";
    unsigned char Temp = Test[0];		
    cout << Test << endl;			// gibt das ä ordentlich aus	
    cout << Test[0] << ", " << Temp << endl;	// gibt ein falsches zeichen und für Temp NICHTS aus. nichtmahl ein fehler!!!!
    
    if(Temp == 'ä') //Compilermeldung: "Warnung: Vergleich ist durch beschränkten Wertebereich des Datentyps stets »unwahr«"
    {
    	cout << "wird nie passieren" << endl;
    }
    

    hinzuzufügen ist das wenn man ind der if-schleife statt 'ä' die 132(also den ascii-code des ä) schreibt die warnung vom compler nicht kommt.



  • Ich habe dem VC8 vom Visual Studio 2005.
    Wenn du den Debugger startest und dann auf das erste Zeichenelement schaust, falls das beim g++-Debugger geht - siehst du dann für ä, ö, ü überall die -61?

    m.



  • mugglemaster schrieb:

    Ich habe dem VC8 vom Visual Studio 2005.
    Wenn du den Debugger startest und dann auf das erste Zeichenelement schaust, falls das beim g++-Debugger geht - siehst du dann für ä, ö, ü überall die -61?

    m.

    Ich tippe mal blindlings auf UTF-8 als locale. Dann hat man auch IMO mehrere Chars im string als Zeichen 😉



  • Also jetzt habe ich es zumindestens für mein System:
    Zum Kodieren in einen std::string verwendet der Compiler wohl die CodePage 1252 bzw. ISO8591-1, sind nahezu indentisch:
    http://www.microsoft.com/globaldev/reference/sbcs/1252.mspx
    http://www.microsoft.com/globaldev/reference/iso/28591.mspx
    => ein ä wird zu einem 0xe4=228 im char-array des strings (dort ein -28 wegen signed)

    Bei der Ausgabe verwendet die run-time die sogenannte "C"-locale die sich von der system-default ANSI-CodePage unterscheidet. Auf meinem XP-System hatte ich als 'language for non-unicode software' in Regional Settings - Advanced ein US-Encoding -> dies führt zu einer Ausgabe mit der (DOS) OEM-Codepage 437 -> aus einem 0xe4 wird ∑.
    http://www.microsoft.com/globaldev/reference/oem/437.mspx

    Wenn ich diese Einstellung auf Germany umsetze wird von Windows die (DOS) OEM-Codepage 850 verwendet -> aus einem 0xe4 wird hier nun ein o mit Schlange drauf.
    http://www.microsoft.com/globaldev/reference/oem/850.mspx

    Damit die Ausgabe korrekt ist muss ich nun per

    setlocale( LC_ALL, "" );
    

    das Programm nun noch anweisen für die Ausgabe die richtige system-default CodePage zu verwenden und schon ist es OK.

    => Kein Unicode etc. Die strings sind alle 1 Zeichen groß, keine UTF-8-Kodierung.

    Warum beim g++ hier eine 61 steht, keine Ahnung was der für CodePages verwendet.

    Sehr interessant zu diesem Thema finde ich übrigens
    http://www.joelonsoftware.com/articles/Unicode.html
    http://www.i18nguy.com/unicode/codepages.html#msftiso

    m.



  • C++ hat auch locales ... es gibt std::wstring hmm usw. ...



  • (D)Evil schrieb:

    C++ hat auch locales ... es gibt std::wstring hmm usw. ...

    Das Problem bleibt auch bei Verwendung von wstring und wcout identisch, man bekommt lediglich keine negativen Werte mehr für die ausgegebenen Zahlen, weil ein wchar_t ein unsigned short ist.
    Ein C++-string kann übrignes auch kein UTF-8, denn entweder der String ist 8Bit oder 16Bit lang. UTF-8 kannst du nur beim Speichern/Lesen mit Dateien verwenden.
    UTF-16 kann er direkt auch nicht, dass was ein wstring ist könnte man noch als ucs2 bezeichnen.

    m.



  • GCC 4.2.1 auf Debian Gnu/Linux Produziert aus Umlauten in Quelltexten in std::basic_string<char> s UTF-8.

    Macht halt ein

    char string[] = "äüö";

    ein Array von 7 char.

    Umlaute im Quellcode ist sowieso schwachsinn (außer vll in den Kommentaren ... )



  • darthdespotism schrieb:

    GCC 4.2.1 auf Debian Gnu/Linux Produziert aus Umlauten in Quelltexten in std::basic_string<char> s UTF-8.
    Macht halt ein
    char string[] = "äüö";
    ein Array von 7 char.
    )

    Nö, bei mir nicht:

    char str[] = "äüö";
      int cnt = sizeof( str ); // liefert 4
    

    m.



  • ist ja auch korrekt:

    str = {'ä', 'ü', 'ö', 0 }
    


  • Man kann doch auch die hier einsetzen für Umlaute:

    Ä = \x8e
    ä = \x84
    Ö = \x99
    ö = \x94
    Ü = \x9a
    ü = \x81
    ß = \xe1

    MfG
    Stromberg



  • darthdespotism schrieb:

    GCC 4.2.1 auf Debian Gnu/Linux Produziert aus Umlauten in Quelltexten in std::basic_string<char> s UTF-8.

    Sicher, dass das nicht daran liegt, dass dein Editor das als UTF-8 abspeichert? Ich meine der Compiler darf das nicht einfach so machen.



  • Bashar schrieb:

    darthdespotism schrieb:

    GCC 4.2.1 auf Debian Gnu/Linux Produziert aus Umlauten in Quelltexten in std::basic_string<char> s UTF-8.

    Sicher, dass das nicht daran liegt, dass dein Editor das als UTF-8 abspeichert? Ich meine der Compiler darf das nicht einfach so machen.

    Wäre eine möglichkeit probier ich nachher mal aus.



  • stringer schrieb:

    wieso steht in Temp der wert -61?

    Deine Plattform hat für den Datentyp char den Wertebereich -128 .. 127 andere 0..255. Die Norm garantiert, daß man char sowohl in "unsigend char" wie auch "signed char" konvertieren kann.

    Wenn Du nun Werte im Beriech 0..255 haben willst, mußt Du als Datentyp "unsigned char" verwenden.



  • Bashar schrieb:

    Sicher, dass das nicht daran liegt, dass dein Editor das als UTF-8 abspeichert? Ich meine der Compiler darf das nicht einfach so machen.

    Der Compiler darf den String Byte für Byte aus der Quelldatei holen, das ist mit Sicherheit der Editor gewesen.



  • hi,
    sorry das ich jetzt erst wieder antworte, aber ich war die letzte woche nicht zuhause.
    richtig durchsteigen tue ich immer noch nicht. ich benutze ubuntu 7.10 als os, anjuta 2.2.0 als ide und g++ 4.1.3 als compiler. was muss ich machen damit ich das nun endlich hinbekomme? ich hab bei anjuta mit den verschiedenen kodierungen rumgespielt, aber nix hat bis jetzt funktioniert.

    für noch ein bisschen hilfe wäre ich sehr dankbar



  • stringer schrieb:

    was muss ich machen damit ich das nun endlich hinbekomme?

    Das macht es noch nicht ganz wie es soll, aber das verdeutlicht, daß Problem mit "unsigned" vs. "signed" char.

    #include <ostream>
    #include <iostream>
    #include <string>
    
    int main () {
            std::string Test = "ä";
            int Temp = static_cast<unsigned char>(Test[0]);
    
            std::cout << Test << std::endl;                // gibt das ä ordentlich aus
            std::cout << Test[0] << ", " << Temp << "\n";    // gibt ein falsches zeichen und -61 aus
    }
    


  • Bashar schrieb:

    darthdespotism schrieb:

    GCC 4.2.1 auf Debian Gnu/Linux Produziert aus Umlauten in Quelltexten in std::basic_string<char> s UTF-8.

    Sicher, dass das nicht daran liegt, dass dein Editor das als UTF-8 abspeichert? Ich meine der Compiler darf das nicht einfach so machen.

    Ich glaube nicht, dass es verboten ist. Zumal es mit dem neuen Standard ja auch explizit erlaubt sein wird, UTF-8-Strings in normalen String-Literalen (char const*) abzulegen. Im Moment ist es wahrscheinlich nur nicht sonderlich portabel.


Anmelden zum Antworten