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


  • Mod

    FillColin schrieb:

    Ein gutes Buch habe ich schon "c++ von A-Z von Jürgen Wolf" und sogar in Hardwareform:)

    Das ist kein gutes Buch, es ist sogar ein ausgesprochen schlechtes. Eine zeitlang bestand das halbe Forum besteht nur aus Threads, die auf die Pfuscherfehler in diesem Buch zurück zu führen waren. Es gilt sogar die Vermutung, dass man schlechter in C++ wird, wenn man dieses Buch liest.

    Und wieder geht mir ein Licht auf. C kann ich ja etwas besser wie C++ nun habe ich herausgefunden das in C++ pointer anderster geschrieben werden wie in C. Also z.b. char* format bzw. char *format...das war der Grund wieso ich das nicht verstanden habe 😃

    Pointer schreibt man in C und C++ eigentlich genau gleich.

    int * a;
    int* a;
    int *a;
    

    Alles das gleiche. Es gelten jedoch in C++ entschieden andere Umwandlungsregelungen für Pointer.

    Tut mir leid, habe gerade keine Zeit, noch auf den Rest zu antworten.



  • FillColin schrieb:

    Ein gutes Buch habe ich schon "c++ von A-Z von Jürgen Wolf"

    Auf die Google-Anfrage "Jürgen Wolf C++" ist dies der erste Treffer.


  • Mod

    FillColin schrieb:

    Soweit so gut.
    Ich verstehe noch immer nicht woher das Programm weiß, dass wann und wo eine Zeile zuende ist, bzw. er eine Neue anfangen muss.
    Klar /n kenne ich und es ist ein Zeichen wie jedes andere.
    Die Frage ist auch schwer zu formulieren, tut mir leid ich versuche es etwas Bildhafter.

    Nochmal: Zeilen entstehen erst auf dem Bildschirm. Die Datei ist einfach eine lange Reihe von Zeichen. Eines dieser Zeichen kann zwischendurch ein Zeilenumbruchzeichen sein, wenn man dieses auf einem Bildschirm ausgibt, dann fängt auf dem Schirm eine neue Zeile an. In der Datei ist an der Stelle nichts anders als bei jedem anderen Zeichen.

    Werners Programm liest die Datei Zeichen für Zeichen aus und vergleicht die Zeichen mit dem Formatstring. Da die Schleife beim Ende des Formatstrings endet und (hier!) der Formatstring mit einem Zeilenumbruch endet, endet die Leseschleife jeweils bei einem Zeilenumbruchzeichen.



  • Na super, gleich ma ein schlechtes Buch gekauft*freu* Na ja, dann hohle ich mir halt ein neues. Dachte Gallileo Computing sei representativ.

    Das meine ich ja mit den Pointern, sie sind zwar gleich, aber es hat mich halt iritiert, dass das * links steht. So kannte ich das nicht da ich immer gedacht habe, dass das * rechts am Namen stehen muß.

    SeppJ schrieb:

    Nochmal: Zeilen entstehen erst auf dem Bildschirm...

    Es tut mir ja leid das ich nochmal nachgefragt habe, aber ich hatte es wirklich nicht verstanden.
    Danke und sorry.

    grüße



  • FillColin schrieb:

    Dachte Gallileo Computing sei representativ.

    Galileo ist so ziemlich der schlechteste Buchverlag überhaupt.



  • Hallo an alle

    SO..nun habe ich erstmal ein neues Buche gekauft 🙂 "C++-Primer" Danke für die Hinweise und den Tip von SeppJ, bin schon fleisig am lesen und probieren.

    Nun habe ich mal wieder eine Frage an euch?!

    // Tes.cpp: Hauptprojektdatei.
    
    #include "stdafx.h"
    #include <algorithm>	// copy 
    #include <iterator>		// i(o)stream_iterator 
    #include <string>
    #include <iostream> 
    #include <fstream> 
    #include <limits>		// numeric_limits 
    #include <time.h>		// Für wait-Funktion
    
    using namespace System;
    using namespace std;
    
    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) 
    
    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;
    
    //		a = b ? c : d;					   +--- [0] Zeichen für 'Zahl lesen' 
    //		if (b) {a=c;} else {a=d;}		   |+-- [1] lese bis zum folgenden Zeichen 
    //										   ||+- [2] nächstes Element mit 0 belegen 
    //										   ||| 
    //										   |||<- Young --><- Old --><-- nn --><--- Perm ---> 
        const char* format = token == "Full"? "%_#_[_:%K_(%K)][_>%K(%K)]%K->%K(%K)[_:%K->%K(%K)]_\n": "%_#_[_:%K_(%K)]"  "##"  "%K->%K(%K)"   "###"    "_\n";		//Full GC / 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; 
    } 
    
    void wait ( int sec )
    { 
    	clock_t count = clock () + sec * CLOCKS_PER_SEC ;
    	while (clock() < count){}
    }
    
    int main() 
    { 
    
    	for ( ; ; )																	// Endlosschleife 
    	{
    		ifstream f1("test.txt"); 
    		ofstream f2("backtest.txt");
    
    		if( !f1.is_open() || !f2.is_open())
    		{								
    			cerr << "Fehler beim Oeffnen einer der Dateien" << endl; 
    			system("PAUSE");
    			return -2;
    		}
    
    		f2.precision(3);														// 3 Nachkommastelen erzwingen
    		f2 << fixed;															// Keine expot. Darstellung => Ganzzahl
    
    		copy( istream_iterator< Eintrag >(f1), istream_iterator< Eintrag >(), ostream_iterator< Eintrag >(f2, "\n") );
    
    		f1.close();																// Schließen
    		f2.close();																//	   "
    
    		wait(60);																// Warte Funktion da, MVS-Express keine sleep unterstüzung
    
    	}
    
    	return 0;
    }
    

    Ich habe Zeile 86 eine Endlosschleife eingehabu und in Zeile 106 eine wait Funktion implementiert (gerne hätte ich sleep(); genommen hat glaube ich bessere Performance, aber Express Edittion unterstüzt dies nicht), was besseres ist mir auch nicht eingefallen und habe nichts gefunden. Wollte damit so jede Minute meine Datei auf den neusten Stand bringen.

    Nun folgendes: Das ist doch voll ineffektiv wenn meine Datei schon 10 000 Zeilen hat (im Jahr ca. 500 000)und es kommen 0 bis max 2 Neue jede Minute dazu, die ganze Datei wieder durch zu ackern??? Oder ist das zu verschmerzen??

    Gibt es da irgend eine Möglichkeit, wie ich erkenne ob etwas Neues dazugekommen ist oder nicht? Und dann dementsprechend nichts oder nur die Neuen Zeilen an die Datei mit den 10 000 Zeilen anhänge?

    Habe schon etwas mit
    ofstream File("FILE", ios::out|ios::app);
    herumexperimentiert, aber nie den Gewünschten Effekt erziehlen können.

    Oder was auch toll wäre, dass das Lesen und schreiben einfach für 1 Minaute stoppen würde wenn es nichts mehr zum schreiben findet, und dann nach 1 Minute wieder schaut ob es weiterlesen und schreiben kann ohne dabei jemals die Funktion in Zeile 101 zu verlassen. Oder ist das dumm gedacht?

    Schöne Grüße und im voraus schon mal herzlichen Dank für eure Unterstüzung

    Fill


  • Mod

    Fixe Idee: Größe merken und vergleichen. Bei Größenänderung an's alte Ende springen, von dort aus weiter lesen.

    Allgemein ist es eher eine suboptimale Idee in Dateien zu lesen, in denen gerade noch ein anderer Prozess rumpfuscht. Suchst du vielleicht eher so etwas wie eine Pipe? Vermutlich wäre es sogar ausreichend, wenn du einfach nur von stdin (also cin) liest und die Ausgabe des anderen Programms auf Shellebene in die Standardeingabe deines Programmes leitest, dann brauchst du praktisch gar nichts zu ändern. Das ist dann jedoch eher eine Frage, seinen Computer richtig bedienen zu können, nicht mehr wie man das in C++ macht (da wie gesagt nur von filestreams auf cin umgestellt werden braucht).



  • Das mit der Dateigräße ist ne super Idee...

    habe das gleich mal versucht

    // Tes.cpp: Hauptprojektdatei.
    
    #include "stdafx.h"
    #include <algorithm>	// copy 
    #include <iterator>		// i(o)stream_iterator 
    #include <string>
    #include <iostream> 
    #include <fstream> 
    #include <limits>		// numeric_limits 
    #include <time.h>		// Für wait-Funktion
    
    using namespace System;
    using namespace std;
    
    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) 
    
    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;
    
    //		a = b ? c : d;					   +--- [0] Zeichen für 'Zahl lesen' 
    //		if (b) {a=c;} else {a=d;}		   |+-- [1] lese bis zum folgenden Zeichen 
    //										   ||+- [2] nächstes Element mit 0 belegen 
    //										   ||| 
    //										   |||<- Young --><- Old --><-- nn --><--- Perm ---> 
        const char* format = token == "Full"? "%_#_[_:%K_(%K)][_>%K(%K)]%K->%K(%K)[_:%K->%K(%K)]_\n": "%_#_[_:%K_(%K)]"  "##"  "%K->%K(%K)"   "###"    "_\n";		//Full GC / 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; 
    } 
    
    void wait ( int sec )
    { 
    	clock_t count = clock () + sec * CLOCKS_PER_SEC ;
    	while (clock() < count){}
    }
    
    long int groesse()
    {
    	ifstream in ("test.txt");
    
    	in.seekg (0, ios::end);
    	long int length = in.tellg ();
    
    	cout << length << endl;
    
    	return length;
    }
    
    int main() 
    { 
    
    	for ( ; ; )																	// Endlosschleife alle 30 Sekunden
    	{		
    		long int alte_groesse, neue_groesse;
    		alte_groesse = neue_groesse;
    		neue_groesse = groesse();
    
    		if( alte_groesse != neue_groesse)
    		{
    			ifstream f1("test.txt"); 
    			ofstream f2("backtest.txt");
    
    			if( !f1.is_open() || !f2.is_open())
    			{								
    				cerr << "Fehler beim Oeffnen einer der Dateien" << endl; 
    				system("PAUSE");
    				return -2;
    			}
    
    			f2.precision(3);														// 3 Nachkommastelen erzwingen
    			f2 << fixed;															// Keine expot. Darstellung => Ganzzahl
    
    			copy( istream_iterator< Eintrag >(f1), istream_iterator< Eintrag >(), ostream_iterator< Eintrag >(f2, "\n") );
    
    			f1.close();																// Schließen
    			f2.close();																//	   "
    
    		//	cout << "Neue Größe";
    			wait(10);																// Schleife alle 30 Sekunden
    		}
    
    		else
    		{
    		//	cout << "Alte Größe";
    			wait(10);
    		}
    	}
    
    	return 0;
    }
    

    KAnn man das in Zeile 102-104 auch "schicker" kompakter lösen?

    Schöne Grüße

    PS: Versuche mich nun daran, die neuen Zeilen ans ende der Datei weiter zu schreiebn:) 🙄

    Danke für den Tip von SeppJ, mit dem "an's alte Ende springen" das werde ich mal versuchen, indem ich irgendwie den letzten dst Pointer speicher(Zeiel 61), habe ich mir mal gedacht.
    Das mit der Shellebene und den Einstellungen scheitert dann bei mir doch eher an "Computer nicht richtig bedienen können 😃 "


  • Mod

    FillColin schrieb:

    KAnn man das in Zeile 102-104 auch "schicker" kompakter lösen?

    Das ist schon ok von der Schreibweise her. ABER: Es ist falsch 🙂 .

    Die Variablen sind an der Stelle lokal für den Schleifendurchlauf! Das heißt, Zeile 103 weist einer Variablen einen undefinierten Wert zu und von da an kann dann alles passieren, besonders bei einem aggressiv optimierenden Compiler, der daraus wer weiß was machen könnte.



  • 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?

    Statt wie heißt es hier als.
    Und C ist hier tatsächlich besser geeignet, man kommt mit sehr viel weniger Code und vor allem ohne iterator und so Zeugs für solch einen trivialen Anwendungsfall wie das Interpretieren eines Strings aus.



  • Ah ok...hm dachte halt die Variablen so lokal wie möglich zu machen (also in der for schleife) und da hätte ich ihnen ja keinen Anfangswert zuweisen können. Denn jedesmal nach der Forschleife wird wieder der Anfangswert reingeschrieben und der alte Wert würde gelöscht.

    Aber ja unsicher ist das auf jeden Fall 🙂 dann probiere ich das mal so und hoffe auf etwas mehr zustimmung 🙂

    long int alte_groesse=0, neue_groesse=0;
        for ( ; ; )                                                                    // Endlosschleife alle 30 Sekunden
    
        {        
            alte_groesse = neue_groesse;
            neue_groesse = groesse();
    

    Oder sollte ich das anderster lösen? z.B. in eine Klasse?

    THX



  • mir juckt es ja in den fingern einen einzeiler zu posten, der die werte aus einer zeile in variablen extrahiert, aber da mein code vermutlich wieder gelöscht werden würde, spare ich mir die mühe lieber.
    🙂



  • b.b. schrieb:

    mir juckt es ja in den fingern einen einzeiler zu posten, der die werte aus einer zeile in variablen extrahiert, aber da mein code vermutlich wieder gelöscht werden würde, spare ich mir die mühe lieber.
    🙂

    Alle Variablen in einer einzigen Zeile einlesen?
    Träum weiter! 👎


Anmelden zum Antworten