Wie sollte ein gutes Stringframework aussehen?



  • Cool, danke für die guten Erläuterungen! 👍



  • otze schrieb:

    Ähnliches bei den Formatierungen in verschiedene Kodierungen. Das ist eigentlich nicht aufgabe eines streams. Da brauch man sich doch nur mal umschauen wo die Kodierung wichtig wird: bei der ein- und ausgabe. Bei der eingabe wird, soweit erforderlich der String in die programminterne Codierung umgewandelt, und bei der Ausgabe von der Internen Codierung in das Ausgabeformat. Es besteht also keine erforderlichkeit, diese Funktionalität aus den streams auszulagern.

    Halte ich so pauschal nicht für ganz richtig.

    Man muss IMHO unterscheiden zwischen Textstreams und Bytestreams. Ich habe einen Haufen Strings, den stopfe ich in einen Textstream. Der Textstream wird von einem Encoder (z.B. UTF-8) gelesen, der einen Bytestream ausgibt, der dann schließlich in eine Datei geschrieben wird. So hat jede Komponente seine Aufgabe und die Komponenten lassen sich einzeln leicht austauschen.

    Ich wüsste jetzt auch nicht, warum das, was du als "Stream" bezeichnest, nämlich der Bytestrom, der in die Datei schreibt, für evtl. Formatierungen von Zahlen zuständig sein sollte. Das klappt nur wenn byte == Zeichen, was nicht gerade eine zukunftssichere Annahme ist. Das bisherige Konzept in der C++ Standardbibliothek sieht nach meinem Verständnis keine Textstreams vor, oder eben nur unter der Annahme, dass byte == Zeichen. Das zeigen auch so Sachen wie eine Datei "als Text" öffnen. Sowas ist IMHO fix und fertig, eine Datei sollte immer als Bytestrom geöffnet werden und was dann reingeschrieben wird, hat so einen Stream nichts anzugehen.



  • c++ hat eben den ansatz dass ein stream formatierungen enthalten kann. wenn ich das nicht will, kann ich in jeden stream immer auch einfach bytefolgen reinwerfen.

    die trennung ist bei java imho etwas sauberer gelöst, wenn auch sehr nervig - da ich dauernd adapter erstellen muss. c++ ist da eben pragmatischer was auf dem papier nicht ganz so sauber ist, aber in der verwendung eigentlich ganz praktisch ist.



  • Shade Of Mine schrieb:

    c++ hat eben den ansatz dass ein stream formatierungen enthalten kann. wenn ich das nicht will, kann ich in jeden stream immer auch einfach bytefolgen reinwerfen.

    die trennung ist bei java imho etwas sauberer gelöst, wenn auch sehr nervig - da ich dauernd adapter erstellen muss. c++ ist da eben pragmatischer was auf dem papier nicht ganz so sauber ist, aber in der verwendung eigentlich ganz praktisch ist.

    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. Ich denke auch, dass es damals einfach noch kein Thema war, dass byte != Zeichen. Von daher kein Vorwurf, ich würde nur das System heute so nicht als löblich hinstellen.



  • otze schrieb:

    In Java ist das nicht so extrem schlimm, weil man sich im Desktopbereich nicht soviel mit locales rumschlagen muss, die meisten Nutzer sind froh, wenn ein und ausgabe dasselbe Format haben. Da dies in C++ allerdings nicht vorausgesetzt werden kann, muss man solche Probleme lösen.

    😕 C++ ist doch auf dem Desktopbereich viel mehr vertreten als Java.

    Zeigt mal nen C++ Beispielcode mit locales, dass man in Java nicht so einfach hin bekommt.



  • Optimizer schrieb:

    Shade Of Mine schrieb:

    c++ hat eben den ansatz dass ein stream formatierungen enthalten kann. wenn ich das nicht will, kann ich in jeden stream immer auch einfach bytefolgen reinwerfen.

    die trennung ist bei java imho etwas sauberer gelöst, wenn auch sehr nervig - da ich dauernd adapter erstellen muss. c++ ist da eben pragmatischer was auf dem papier nicht ganz so sauber ist, aber in der verwendung eigentlich ganz praktisch ist.

    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. Ich denke auch, dass es damals einfach noch kein Thema war, dass byte != Zeichen. Von daher kein Vorwurf, ich würde nur das System heute so nicht als löblich hinstellen.

    Unicode geht auf 1987 zurueck. 1990 waren bereits Sun, Microsoft, und paar andere dabei, 1991 wurde das erste Buch des Unicode Standards veroeffentlicht, 1992 das zweite.

    Im 1987 Original wurde schon an 16bit pro Zeichen gedacht. UTF wurde angefangen 1992 und damals war 32bit fuer ein Zeichen. Die vorletze Spezifikation von C++ war 1998, die letzte 2003. Da war wohl genuegent Zeit...

    Ich persoehnlich finde die ganze Sprachunterstuetzung und Formate nur ein Haufen Chaos. Ist alles nur Halbherzig dahingemacht und voller Kompromisse. Das zieht sich durch von normalen Windows-Anwendungen ueber Emails und bis ins Internet.



  • wayne??? schrieb:

    Zeigt mal nen C++ Beispielcode mit locales, dass man in Java nicht so einfach hin bekommt.

    cin.imbue(locale1);
    int i;
    cin>>i;
    
    cout.imbue(locale2);
    cout<<i;
    

    @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.



  • 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