Wie kann ich variable Zahlen aus einer Zeile, die in einem Buffer ist, extrahieren?


  • Mod

    Mit mehr Hintergrundinformationen wäre das natürlich viel leserlicher, da man dann nicht zahl1, zahl2, usw. schreiben würde. Außerdem habe ich natürlich keine Ahnung, worauf es bei dem Format genau ankommt. Ich habe hier angenommen, dass der nicht-fett geschriebene Text im Beispiel immer gleich ist. Um dir eine Idee zu geben, sollte es reichen:

    #include <iostream>
    #include <limits>
    
    class Daten
    {
      double zahl1;
      unsigned zahl2;
      unsigned zahl3;
      unsigned zahl4;
      unsigned zahl5;
      unsigned zahl6;
      unsigned zahl7;
      unsigned zahl8;
      unsigned zahl9;
      unsigned zahl10;
    
      friend std::istream& operator>>(std::istream &in, Daten& daten)
      {
        const std::streamsize max = std::numeric_limits<std::streamsize>::max();
        in >> daten.zahl1;
        in.ignore(1);
        in.ignore(max, ':');
        in >> daten.zahl1;
        in.ignore(max,'(');
        in >> daten.zahl2;
        in.ignore(max,'>');
        in >> daten.zahl3;
        in.ignore(max,'(');
        in >> daten.zahl4;
        in.ignore(max,']');
        in >> daten.zahl5;
        in.ignore(max,'>');
        in >> daten.zahl6;
        in.ignore(max,'(');
        in >> daten.zahl7;
        in.ignore(max,':');
        in >> daten.zahl8;
        in.ignore(max,'>');
        in >> daten.zahl9;
        in.ignore(max,'(');
        in >> daten.zahl10;
        in.ignore(max,'\n');  
        return in;
      }
    
      friend std::ostream& operator<<(std::ostream &out, const Daten& daten)
      {
        return out << daten.zahl1 << ' '
                   << daten.zahl2 << ' '
                   << daten.zahl3 << ' '
                   << daten.zahl4 << ' '
                   << daten.zahl5 << ' '
                   << daten.zahl6 << ' '
                   << daten.zahl7 << ' '
                   << daten.zahl8 << ' '
                   << daten.zahl9 << ' '
                   << daten.zahl10;
      }
    };
    
    #include <sstream>
    int main()
    {
      std::stringstream beispiel("35.121: [Full GC (System) [PSYoungGen: 51172K-> \
    0K(764608K)] [PSOldGen: 0K->50789K(1747648K)] 51172K->50789K(2512256K) [PSPerm\
    Gen: 73515K->73515K(147072K)], 0.3471350 secs] [Times: user=0.33 sys=0.02, rea\
    l=0.35 secs]\n35.121: [Full GC (System) [PSYoungGen: 51172K->0K(764608K)] [PSO\
    ldGen: 0K->50789K(1747648K)] 51172K->50789K(2512256K) [PSPermGen: 73515K->7351\
    5K(147072K)], 0.3471350 secs] [Times: user=0.33 sys=0.02, real=0.35 secs]\n35.\
    121: [Full GC (System) [PSYoungGen: 51172K->0K(764608K)] [PSOldGen: 0K->50789K\
    (1747648K)] 51172K->50789K(2512256K) [PSPermGen: 73515K->73515K(147072K)], 0.3\
    471350 secs] [Times: user=0.33 sys=0.02, real=0.35 secs]\n");
    
      for(Daten daten; beispiel >> daten; std::cout << daten << '\n');
    }
    

    C++ klingt aber eigentlich eher nach einer ungünstigen Wahl für diese Aufgabe, wenn du die Daten einfach nur wieder in eine Datei schreiben möchtest, statt sie in einem C++-Programm weiter zu verarbeiten. Eine Scriptsprache mit RegEx wäre eigentlich eine viel bessere Wahl. Du siehst an meinem Beispiel, dass das in C++ recht frickelig ist.



  • Hallo erstam und herzlichen Dank für die Antwort.

    Sorry das ich diese Zusatzinformationen vergessen habe anzugeben.
    Also:

    - Es handelt sich bei dieser Zeile um eine Speicherauslastung und Bereinigung meines Servers die in eine Datei geschrieben wird

    - Der erste Zahlenwert ist der Zeitstempel, ich gehe davon aus alles vor dem Punkt sind Sekunden, hinter dem Punkt Millisec.

    - Die anderen Zahlen räpresentieren die Speicher(Haupt-Sp./Statischer-Sp.)jeweils "Wieviel gerade belegt ist" dann "die Bereinigungsmenge" und "der Max-Speicher"

    Ich hoffe das Hilft ein wenig um die Zeile nachvolziehen zu können.

    ICh versuche der weil mal einen Datentyp "Eintrag" zu erstellen.



  • Hallo Fill,

    wie Kellerautomat schon sagte, wäre Schritt 1, eine Struktur Eintrag (oder so) zu bauen, die sozusagen der Datensatz ist, der den Inhalt einer Zeile beschreibt. Für diese struct Eintrag baue man sich die sogenannten Streaming-Operatoren und dort findet dann das eigentliche Lesen und Schreiben genau eines Eintrags statt.
    In Deinem Fall ist es sicher angebracht, sich auf markante Zeichen in dem Text zu konzentrieren, die möglichst nur vor der jeweils nächsten Zahl auftauchen. Solche Stellen kann man mit der Methode ignore gezielt 'anspringen'.
    Also bei "35.121**:** [Full GC (System) [PSYoungGen**:** 51172K->0K**(**764608K)] ... " ist das der ':' und die '('. Bei der zweiten Zahl (hier 51172K) muss man schon aufpassen, da der ':' bis dahin zweimal auftaucht.

    Ich habe das ganze hier mal skizziert:

    #include <algorithm> // copy
    #include <fstream>
    #include <iterator> // i(o)stream_iterator
    #include <iostream>
    #include <limits> // numeric_limits
    
    struct Eintrag
    {
        static int const N = 10;
        double prefix_;
        int ps_[N];
    };
    // --   Streaming-Operator für das Lesen
    // 1 "35.121: [Full GC (System) 
    // 2      [PSYoungGen: 51172K->0K(764608K)] 
    // 3      [PSOldGen: 0K->50789K(1747648K)] 
    // 4          51172K->50789K(2512256K) 
    // 5      [PSPermGen: 73515K->73515K(147072K)],
    //      .. Rest bis EOL"
    std::istream& operator>>( std::istream& in, Eintrag& e )
    {
        const std::streamsize ALL = std::numeric_limits< std::streamsize >::max();
        in >> e.prefix_;
        in.ignore( ALL, ':' ); // ersten ':' hinter 'prefix' überspringen
        const char* tags = ":(>(]>(:>(";
        const char* tag = tags;
        for( int i=0; i<Eintrag::N; ++i, ++tag )
            in.ignore( ALL, *tag ) >> e.ps_[i];
        return in.ignore( ALL, '\n' ); // Rest der Zeile überlesen
    }
    // --   Streaming-Operator für das Schreiben
    std::ostream& operator<<( std::ostream& out, const Eintrag& e )
    {
        out << e.prefix_ << " ";
        std::copy( e.ps_, e.ps_ + Eintrag::N, std::ostream_iterator< int >( out, " " ) );
        return out;
    }
    
    int main()
    {
        using namespace std;
        ifstream f1("test.txt");
        ofstream f2("backtest.txt");
        if( !f1.is_open() || !f2.is_open() )
        {
            cerr << "Fehler beim Oeffnen einer der Dateien" << endl;
            return -2;
        }
        copy( istream_iterator< Eintrag >(f1), istream_iterator< Eintrag >(), ostream_iterator< Eintrag >(f2, "\n") );
        return 0;
    }
    

    Gruß
    Werner

    Ups: SeppJ war schneller, aber ich habe alle Zahlen 😉
    @Edit: Schleife beim Lesen



  • Na ja aus den Zahlen wollte ich dann nachher eventuell ein kleines Diagramm zeichnen lassen. 😃

    Aber so weite Schritte kann ich nicht überblicken, daher wollte ich in kleinen Schritten vorrangehen.

    Man hat mir auch schon gesagt das Java besser gewesen wäre, aber ich wollte halt was in c++ machen da ich java nicht kann um da etwas fitter zu werden und dan kam mir halt so eine "hirnrissige idee" mit dieser Datei😋



  • Ihr seid ja mal der Hammer ich doktor da Wochen dran rum und Ihr braucht 5 Minuten 😞
    irgendwie deprimiert das:)

    Auf jeden fall ma herzlichen Dank



  • FillColin schrieb:

    Man hat mir auch schon gesagt das Java besser gewesen wäre, aber ich wollte halt was in c++ machen da ich java nicht kann um da etwas fitter zu werden und dan kam mir halt so eine "hirnrissige idee" mit dieser Datei😋

    Mit Java hast du keine Vorteile - eher mit Python/Perl/Ruby oae.



  • zum Einlesen des Eintrags ist mir noch eine weit lustigere Variante eingefallen, als mein erster Vorschlag oben:

    // --   Streaming-Operator für das Lesen
    // 1 "35.121: [Full GC (System)
    // 2      [PSYoungGen: 51172K->0K(764608K)]
    // 3      [PSOldGen: 0K->50789K(1747648K)]
    // 4          51172K->50789K(2512256K)
    // 5      [PSPermGen: 73515K->73515K(147072K)],
    //      .. Rest bis EOL"
    std::istream& operator>>( std::istream& in, Eintrag& e )
    {
        in >> e.prefix_;
        //                    +--- Zeichen für 'Zahl lesen'
        //                    |+-- lese bis zum folgenden Zeichen
        //                    ||             |3       |4        |5
        const char* format = "%_:[_[_:%_(%_)_->%K(%K)]%K->%K(%K)[_:%K->%K(%K)]_\n";
        int i=0;
        for( const char* p = format+2; *p; ++p )
            *p == *format ? in >> e.ps_[i++]: *p == *(format+1)? in.ignore( std::numeric_limits< std::streamsize >::max(), *++p ): in >> check( *p );
        return in;
    }
    

    Dazu braucht man noch die struct check :

    struct check
    {
        check( char c ) : c_( c ) {}
        friend std::istream& operator>>( std::istream& in, check ch )
        {
            char c;
            if( in >> c && c != ch.c_ )
                in.setstate( std::ios_base::failbit );
            return in;
        }
    private:
        char c_;
    };
    

    Die Variante ist sicherer, was den Syntax-Check angeht, und auch universeller einsetzbar.

    Gruß
    Werner


  • Mod

    jetzt noch mit tmp? ist ja nicht viel anders als brainfuck... :p



  • Na ja mit dem letzten code kann ich mal gar nichts anfangen, da verbiegen sich bei mir die Hirnwindungen 😮 , leider bin ich ja auch noch lange nicht so fit wie ihr 😃
    _____________________________________________

    Aber hätte noch eine Frage??? 😕

    Warum muss ich "FETT" das nochmal aufrufen und ohne File Angabe? Oder ist das nur ein Platzhalter?

    copy( istream_iterator< Eintrag >(f1), istream_iterator< Eintrag >(), ostream_iterator< Eintrag >(f2, "\n") );

    Werner Salomon schrieb:

    Hallo Fill,

    ... copy( istream_iterator< Eintrag >(f1), istream_iterator< Eintrag >(), ostream_iterator< Eintrag >(f2, "\n") );...


  • Mod

    FillColin schrieb:

    Warum muss ich "FETT" das nochmal aufrufen und ohne File Angabe? Oder ist das nur ein Platzhalter?

    copy( istream_iterator< Eintrag >(f1), istream_iterator< Eintrag >(), ostream_iterator< Eintrag >(f2, "\n") );

    Das copy muss wisssen, bis wohin kopiert werden soll. Ein istream_iterator ohne Streamargument im Konstruktor steht für das Ende eines Streams. Siehe:
    http://www.cplusplus.com/reference/std/iterator/istream_iterator/
    http://www.cplusplus.com/reference/algorithm/copy/



  • FillColin schrieb:

    Na ja aus den Zahlen wollte ich dann nachher eventuell ein kleines Diagramm zeichnen lassen. 😃

    Man hat mir auch schon gesagt das Java besser gewesen wäre, aber ich wollte halt was in c++ machen da ich java nicht kann um da etwas fitter zu werden und dan kam mir halt so eine "hirnrissige idee" mit dieser Datei😋

    Du solltest uns etwas mehr über deine Ziele mitteilen.
    Zahlenwerte aus einer Datei rauslesen, geht so gut wie mit jeder Programmiersprache und sogar mit Applikationen.

    Nimm eine Tabellenkalkulation Excel oder OpenOffice:

    • Kann auch Diagramme erzeugen
    • Kann strukturierte Text-Dateien einlesen


  • Nochmal Hallo,

    alles funktioniert nun einwandfrei *freu*
    --- Auf basis von "Werner Salomon" 22:41:49 05.07.2012---

    Nur hat meine Aufzeichnung nun einen "kritischen Wert" erreicht.

    126032.403: [Full GC (System) [PSYoungGen: 2400K->0K(764608K)] [PSOldGen: 58257K->51512K(1747648K)] 60657K->51512K(2512256K) [PSPermGen: 81683K->81341K(82112K)], 0.3413080 secs] [Times: user=0.34 sys=0.00, real=0.34 secs]

    Wenn nun mein Zeitstempel immer größer wird "FETT", dann ist nachher nur noch 126032 zu sehen. Der rest .403 wird verschluckt.

    Nun habe ich versucht im Programm die Datentypen zu vergrößern also "long", dies hatte aber nicht den gewünschten Erfolg.

    Dann habe ich mal etwas mit Zahlen gespielt
    z.b. 200000000 der wird schön ausgegeben, aber sobald was mit Komma kommt schmeist der das weg z.B. 200000000.222

    Kann es sein, dass das Programm automatisch castet und rundet und wenn ja wie unterbinde ich das?

    Scchöne Grüße
    Fill



  • float und double sind mMn. denkbar schlechte Typen für Zeitstempel. Zumindest wenn der Zeitstempel exakt gespeichert/verarbeitet werden soll. Das geht mit float/double nämlich nur, wenn die binäre (!) Darstellung der Kommazahl ausreichend wenig signifikante Stellen hat.

    Was noch dazukommt: je nach verwendeter Funktion (printf, operator << (ostream, ...), ...) werden floats/doubles per Default unterschiedlich genau formatiert. Und das kann eben dazu führen, dass Kommastellen die eigentlich da wären einfach nicht angezeigt werden.

    Kann man natürlich alles mittels diverser Formatierungs-Optionen umstellen, aber es bleibt immer noch das Problem dass sich Dezimal-mit-Kommastellen nicht gut mit Binär-mit-Kommastellen verträgt.



  • Hallo Fill,

    hustbaer hat wahrscheinlich recht mit seinem Verdacht, dass es sich nur um ein Darstellungsproblem handelt. Ein double reicht für 126032.403 locker aus.
    Füge in meinem Listing vor dem 'copy( istream_iterator<>..' noch eine Formatierung für double ein:

    f2.precision(3);
        f2 << fixed;
        copy( istream_iterator< Eintrag >(f1), istream_iterator< Eintrag >(), ostream_iterator< Eintrag >(f2, "\n") );
    

    Damit erzwingst Du, dass double mit 3 Nachkommastellen ausgegeben wird.

    Gruß
    Werner



  • Danke für die thematisch Erörterrung!!

    Sind diese Delauft-Werte in denen automatisch und unterschiedlich Formatiert wird eigentlich willkürlich ausgedachte Standardts oder entspricht das einer durchdachten Norm von c++.

    Habe ich nur das Gefühl, dass das suboptimal ist oder ist meine Aufgabe eher Suboptimal 😃

    Dabei dachte ich das c++ mehr Vorgaben/-schriften bekommen hat wie C um es "sicherer/einfacher" zu machen und nun muss ich quasi doch so spitzfindig sein? 🙄
    ____________________________________________
    Auf jeden fall super lieben Dank für die Komments bis jetzt, ihr habt mich echt weitergebracht und es macht sogar richtig spaß in diesem Forum

    Grüße


  • Mod

    Der Anfangswert für precision ist laut Standard als 6 definiert.



  • FillColin schrieb:

    Dabei dachte ich das c++ mehr Vorgaben/-schriften bekommen hat wie C um es "sicherer/einfacher" zu machen und nun muss ich quasi doch so spitzfindig sein? 🙄

    Nein, du musst bloss den passenden Datentyp verwenden 🙄



  • Hallo, ich bin's wieder.

    zu meiner Freude läuft das Programm auf basis von WERNER SALOMON (Thread 12:43:51 05.07.2012) einwandfrei und konnte es gut weiterverarbeiten.

    Nun habe ich feststellen müssen, das in meine Textdatei 1 mal im Monat ein Sondereintag (Sonderprüfung) stadtfindet. Und zwar kein Full GC sondern nur ein CG

    ....
    3636.211: [Full GC (System) [PSYoungGen: 6520K->0K(764608K)] [PSOldGen: 50789K->56413K(1747648K)] 57309K->56413K(2512256K) [PSPermGen: 82267K->82267K(172288K)], 0.3546920 secs] [Times: user=0.35 sys=0.00, real=0.36 secs]
    7237.275: [GC [PSYoungGen: 91438K->2416K(764608K)] 147852K->58829K(2512256K), 0.0123960 secs] [Times: user=0.02 sys=0.00, real=0.01 secs]
    7237.287: [Full GC (System) [PSYoungGen: 2416K->0K(764608K)] [PSOldGen: 56413K->58662K(1747648K)] 58829K->58662K(2512256K) [PSPermGen: 82381K->82381K(170048K)], 0.3349310 secs] [Times: user=0.33 sys=0.00, real=0.34 secs]
    ...

    Ab hier bricht das Programm dann ab 😞
    _____________________________________
    Wie ich aus der Zeile GC meine gewünschten Zahlen herausbekomme weiß ich nun dank euch.

    Nur wie kann ich in das Programm einbauen, dass die Zeilen vorab geprüft werden ob ein FullGC oder ein GC vorliegt, um dann mit einem passenden Copy(...); darauf zu reagieren.

    int main() 
    { 
        using namespace std; 
        ifstream f1("test.txt"); 
        ofstream f2("backtest.txt"); 
        if( !f1.is_open() || !f2.is_open() ) 
        { 
            cerr << "Fehler beim Oeffnen einer der Dateien" << endl; 
            return -2; 
        } 
    	struc.precision(3);															// 3 Nachkommastelen erzwingen
        struc << fixed;																// Keine expot. Darstellung => Ganzzahl
        copy( istream_iterator< Eintrag >(f1), istream_iterator< Eintrag >(), ostream_iterator< Eintrag >(f2, "\n") );
         return 0; 
    }
    

    Habe mir überlegt, ob ich zwischen Zeile 10 und 14 irgendwie die Zeile Abfrage, dann prüfe und dann mit einer IF-Schleife in den passenden Coppy(..); gehe.
    Aber ich muss das irgendwie immer Zeilenweise machen und nicht die gesammte Datei...hm...

    Hat mir eventuell jm. einen Gedankengang wie ich das umsetzen könnte?

    Herzlichen Dank schon mal
    Fill



  • FillColin schrieb:

    Habe mir überlegt, ob ich zwischen Zeile 10 und 14 irgendwie die Zeile Abfrage, dann prüfe und dann mit einer IF-Schleife in den passenden Coppy(..); gehe.

    Hallo Fill,

    wenn Du eine Änderung machen willst (und das gilt immer bei Programmänderungen), so solltest Du zunächst feststellen, welches Modul/Funktion für diese Funktionalität, die Du ändern willst, verantwortlich ist.
    Was Du hier vorhast, ist das Einlesen zu ändern. Das Einlesen geschieht im Streaming-Operator von struct Eintrag ; also ist da die Baustelle, nirgendwo sonst.

    Wenn man die lustige Variante, die ich bereits gepostet habe, weiter entwickelt, so kann sie auch das.

    #include <algorithm> // copy
    #include <fstream>
    #include <iterator> // i(o)stream_iterator
    #include <iostream>
    #include <limits> // numeric_limits
    #include <string>
    
    struct check
    {
        check( char c ) : c_( c ) {}
        friend std::istream& operator>>( std::istream& in, check ch )
        {
            char c;
            if( in >> c && c != ch.c_ )
                in.setstate( std::ios_base::failbit );
            return in;
        }
    private:
        char c_;
    };
    
    struct Eintrag
    {
        static int const N = 10;
        double time_;
        int ps_[N];
    };
    
    // --   Streaming-Operator für das Lesen
    //      einiger(!) Logging Ausgaben des Garbage Collectors von Java
    //      Bem.: PS := Parallel Scavenge (scavenge -> Reinigung)
    //
    //  Format: (Beispiel, im Orginal einzeilig)
    //  35.121:
    //      [Full GC (System)
    //          [PSYoungGen: 51172K->0K(764608K)]
    //          [PSOldGen: 0K->50789K(1747648K)]
    //          51172K->50789K(2512256K)
    //          [PSPermGen: 73515K->73515K(147072K)],
    //      .. Rest bis EOL
    //
    //  -oder:
    //  7237.275:
    //      [GC
    //          [PSYoungGen: 91438K->2416K(764608K)]
    //          147852K->58829K(2512256K),
    //      .. Rest bis EOL
    //
    std::istream& operator>>( std::istream& in, Eintrag& e )
    {
        const std::streamsize ALL = std::numeric_limits< std::streamsize >::max();
        std::string token;
        (in >> e.time_).ignore( ALL, '[' ) >> token;
        const char* format = token == "Full"?
        //   +--- [0] Zeichen für 'Zahl lesen'
        //   |+-- [1] lese bis zum folgenden Zeichen
        //   ||+- [2] nächstes Element mit 0 belegen
        //   |||
        //   |||<- Young --><- Old --><-- nn --><--- Perm --->
            "%_#_[_:%K_(%K)][_>%K(%K)]%K->%K(%K)[_:%K->%K(%K)]_\n": // Full GC (System)
            "%_#_[_:%K_(%K)]"  "##"  "%K->%K(%K)"   "###"    "_\n"; // GC
        int* dst = e.ps_;
        for( const char* p = format+3; *p; ++p )
        {
            if( *p == format[0] )
                in >> *dst++;
            else if( *p == format[1] )
                in.ignore( ALL, *++p );
            else if( *p == format[2] )
                *dst++ = 0; // Eintrag hier nicht vorhanden
            else
                in >> check( *p );
        }
        return in;
    }
    
    // --   Streaming-Operator für das Schreiben
    std::ostream& operator<<( std::ostream& out, const Eintrag& e )
    {
        out << e.time_ << " ";
        std::copy( e.ps_, e.ps_ + Eintrag::N, std::ostream_iterator< int >( out, " " ) );
        return out;
    }
    
    int main()
    {
        using namespace std;
        ifstream f1("test.txt");
        ofstream f2("backtest.txt");
        if( !f1.is_open() || !f2.is_open() )
        {
            cerr << "Fehler beim Oeffnen einer der Dateien" << endl;
            return -2;
        }
        copy( istream_iterator< Eintrag >(f1), istream_iterator< Eintrag >(), ostream_iterator< Eintrag >(f2, "\n") );
        return 0;
    }
    

    beachte bitte, dass ich die gelesenen Zahlen nicht einfach in das Feld von Eintrag fülle, sondern zunächst noch zwei Elemente mit 0 belege. Das ist dann der fehlende Eintrag für das Feld [PSOldGen] .
    In den Zeilen 60 und 61 habe ich das Format für Full GC und GC definiert.
    Wenn Du dazu Fragen hast, so nur heraus damit.

    Gruß
    Werner



  • Hallo Werner,

    danke für die Antwort. Ich hatte zu beginn bewusst deine "lustige Variante" nicht genomme, da ich leider nur 40% davon verstanden habe. Also den "struct check" und den "streaming operator".

    Wenn du mir allerdings anbietest meine Fragen dazu zu beantworten, dann werde ich ihn wohl einsetzen, weil ich grundsätzlich nur das verwenden will was ich auch verstehen und handhaben kann.
    __________________________________
    Ich würde mich bei den Zeilenangaben auf deinen letzten Post beziehen.

    8-20 Ich verstehe nicht warum nach dem friend(11) eine Schachtelung erfolgt und was diese bewirkt (12 u. 17)

    18-19 Also private kenn ich, aber in der Form habe ich das noch nie eingesetzt. Sondern nur wenn ich ne Klasse private oder public gemacht habe. Daher erschließt sich mir der Teil nicht, da er mittem im struct ist.

    54 Was bezweckt diese Zeile mit dem Gleich und dem Vergleich-Operator?

    63-73 Ich kann mit zwar zusammenreimen was die Funktion macht und die Erklärung von dir bestätigt das auch, aber die Frage ist wie macht sie das.
    In der for-schleife prüfst du ja ob % oder _ oder # vorhanden ist.
    Pointer / Zeiger kenne ich zwar auch, aber da ich nicht so fit bin verbiegt es hier meine Hirnwindungen 🙂

    Und allgemein, bzum Leseoperator.
    Betrachtet er eine Zeile und springt dann in die nächste ? (wenn ja wie? wo? oder macht das die for schleife)
    Oder geht er das Dokument auf einmal durch und merkt dann wenn die Zeile zuende ist?
    _____________________________________________
    Es tut mir sehr leid wenn ich so viele Fragen stelle, leider ist dieser Programmcode doch zu hoch für mich, um ihn in seiner Gesammtheit zu überschauen.

    Auf jeden Fall herzlichen Dank für die Mühe deinerseits

    Grüße

    Fill


Anmelden zum Antworten