Wie sollte ein gutes Stringframework aussehen?



  • otze schrieb:

    @optimizer

    Ich finde es nicht falsch, wenn ein Stream formattiert - aber das sollte nicht der selbe Stream sein, der eine Bytefolge in eine Datei schreibt. Es sollte ein Textstream sein. Diese Konzepte würde ich auf jeden Fall trennen.

    Vielleicht reden wir aneinander vorbei. aber das ist doch in C++ getrennt. Der stream formatiert, der buffer schreibt. Es ist also nicht dasselbe Objekt.

    Wo genau käme dann eine bestimmte Kodierung ins Spiel? Also ich habe jetzt folgendes:

    #include <fstream>
    
    using namespace std;
    
    int main() {
    	string s("geiler string");
    	wofstream file("test.txt");
    	file  <<  s.c_str()  <<  endl;
    }
    

    Das Programm schreibt 15 Bytes, normalen ANSI plain text. Also so einen basic_ofstream<wchar_t> zu verwenden bewirkt nicht, dass irgendwie in der Kodierung von wchar_t geschrieben wird (wäre bei mir UTF-16), sondern es schreibt offensichtlich was im String, im Arbeitsspeicher steht, 1:1 ab in die Datei. Jetzt ist bekannt, dass C++ nicht fertige Lösungen zum Beispiel für die Formate UTF-8, UTF-16 usw. anbietet.

    Aber gibt es irgendwie ein generisches Framework, so dass ich etwas einklinken kann, was die Kodierung von Zeichen nach Bytes steuert? Ich sehe es nicht. Ich sehe nicht, wie die buffer das machen können sollen. Nochmal, IMHO wäre ein sauberes Konzept:

    (jede Menge Strings, es sollte egal sein, welcher Zeichentyp) ➡ Textstream ➡ Encoder ➡ Bytestream ➡ Datei

    Sodass man sich eine Pipeline nach seinem Geschmack zusammenstecken kann, zum Beispiel Textstream<char>, Encoder(UTF-8), Bytestream("test.txt"). Ich sehe sowas in der Art nicht verwirklicht. Ich habe das Standard C++-I/O allerdings auch immer gemieden und die OS-Funktionen dafür benutzt. Vielleicht übersehe ich was.



  • otze schrieb:

    cin.imbue(locale1);
    int i;
    cin>>i;
    
    cout.imbue(locale2);
    cout<<i;
    
    BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
    Number n = NumberFormat.getInstance(Locale.ENGLISH).parse(in.readLine());
    
    System.out.println(NumberFormat.getInstance(Locale.GERMAN).format(n));
    

    Gut, das einlesen von der Konsole ist umständlicher, aber welches Programm bei dem Internationalisierung wichtig ist liest schon von Konsole.

    Habs noch nie probiert, aber geht sowas in C++ auch so einfach?

    System.out.println(DateFormat.getDateInstance(DateFormat.LONG, Locale.GERMAN).format(Calendar.getInstance().getTime()));
    


  • Optimizer schrieb:

    Das Programm schreibt 15 Bytes, normalen ANSI plain text. Also so einen basic_ofstream<wchar_t> zu verwenden bewirkt nicht, dass irgendwie in der Kodierung von wchar_t geschrieben wird (wäre bei mir UTF-16), sondern es schreibt offensichtlich was im String, im Arbeitsspeicher steht, 1:1 ab in die Datei. Jetzt ist bekannt, dass C++ nicht fertige Lösungen zum Beispiel für die Formate UTF-8, UTF-16 usw. anbietet.

    Ein wunder ist, dass es überhaupt bei dir funktioniert. laut standard gibt es nämlich nur einen gültigen stream ausgabeoperator:

    template<class charT,class traits, class Allocator>
    basic_ostream<charT,traits>& 
    operator<<(basic_ostream<charT,traits>&,basic_string<charT,traits,Allocator);
    

    du müsstest also einen compile fehler kriegen, weil dein string auf char und dein stream auf wchar_t läuft. Aber du hast recht, egal wie mans dreht und wendet, C++ unterstützt standarmäßig nicht, dass beliebige stringtypen ausgegeben werden können.

    Das ist aber so direkt kein Problem, es gibt ja den streambuffer. Wenn man Intern nur mit einem zeichentyp arbeitet, zum Beispiel char, dann kann der streambuffer das Erledigen. Er hat zugriff auf die locales(genauer er speichert sie) und damit auf die facets ctype und codecvt. Ob die Buffer diese funktionalität standardmäßig nutzen ist wohl implementationsabhängig. Wenn die Console nur Unicode versteht, wird die Ausgabe wohl nach unicode umgewandelt.Wichtig ist in diesem Zusammenhang nur, dass die Buffer die Möglichkeiten dazu besitzen, dass es umgewandelt werden kann.

    Zusammengefasst: die konvertierung stringtyp<->streamtyp ist nicht automatisch möglich aber streamtyp<->ausgabetyp sehr wohl. Und das ist ja das wichtige. Solange die Streams die konvertierung "interner typ"->"externer typ" erbringen können ist alles in butter. Man muss nur damit rechnen, dass man im ernstfall nen eigenen bufferwrapper schreiben muss, aber soweit ich weis, gibts da was in boost.

    wayne??? schrieb:

    Habs noch nie probiert, aber geht sowas in C++ auch so einfach?

    System.out.println(DateFormat.getDateInstance(DateFormat.LONG, Locale.GERMAN).format(Calendar.getInstance().getTime()));
    

    ein einzeiler ist es leider nicht 🙂

    ist ungetestet, aber so müsste das aussehen(direkt mit locales arbeiten ist ein gräuel 😞 )

    //locale holen
    locale loc=cout.getloc();
    //facet holen
    time_put<char>& tfac = use_facet<time_put<char> >(loc);
    
    //ausgabe
    tm time=localtime(time(0));
    tfac.put(cout,cout,' ',&tm,'c',' ');
    

    das ganze dann als einzeiler:

    use_facet<time_put<char> >(cout.getloc()).put(cout,cout,' ',&localtime(time(0)),'c',' ');
    


  • Gibts außer C++ noch eine Sprache die Streams als Standardmittel zur Konvertierung zwischen Strings und zahlen hat?



  • Optimizer schrieb:

    Jetzt ist bekannt, dass C++ nicht fertige Lösungen zum Beispiel für die Formate UTF-8, UTF-16 usw. anbietet.

    Aber gibt es irgendwie ein generisches Framework, so dass ich etwas einklinken kann, was die Kodierung von Zeichen nach Bytes steuert? Ich sehe es nicht. Ich sehe nicht, wie die buffer das machen können sollen. Nochmal, IMHO wäre ein sauberes Konzept:

    http://gcc.gnu.org/onlinedocs/libstdc++/manual/codecvt.html
    http://www.boost.org/doc/libs/1_35_0/libs/serialization/doc/codecvt.html


Anmelden zum Antworten