Konsolenproblem



  • Hallo,
    ich versuche gerade eine Datei (.txt) einzulesen um diese dann in der Konsole auszugeben, allerdings zeigt mir die Konsole nichts, lediglich einen "Black Screen".

    Hier der Code:

    #include <iostream>
    #include <fstream>
    #include <string>
    
    using namespace std;
    
    void Load()
    {
        string text;
        ifstream file;								//Datei-Handle
        file.open("Datei_2.txt", ios::in);			//Datei wird geöffnet
    
    												// Solange noch Daten vorhanden sind wird die Schleife ausgeführt
        while (!file.eof()) 
    	{
            getline(file, text);					//Es wird jeweils eine Zeile ausgelesen
            cout << text << endl;
    	}
    
        file.close();
    } 
    
    int main(int argc, char **argv)
    {
        Load();
        return 0;
    }
    

    Kann mir bitte jemand helfen und mir sagen, wo mein Fehler liegt.
    Wäre dankbar.
    (Programm: Visual Studio C++)

    Grüße



  • Das Programm funktioniert. Vermutlich hast Du die einzulesende Datei nicht im Verzeichnis der ausführbaren Datei liegen?

    Folgendes könntest Du vereinfachen:

    void Load()
    {
    
        ifstream file("Datei_2.txt");    //Datei-Handle, Datei wird geöffnet
    
        if(!file)
        {
            cout << "Datei konnte nicht geoeffnet werden\n";
            return;
        }   
    
        string text;  //wird erst jetzt benötigt
        while(getline(file, text))  //solange Zeilen gefunden werden
            cout << text << '\n';
    } //Scope - Ende --> file wird zerstört und schliesst die Datei
    


  • Die Load-Funktion kann man ganz einfach umschreiben, da du viele unnötige Sachen machst:

    void Load() 
    {
        ifstream file("Datei_2.txt");//Es gibt auch den entsprechenden Konstruktor, außerdem muss das ios::in flag bei std::ifstream sowieso nie angegeben werden
    
        for(std::string text;getline(file, text);) //getline gibt den Stream zurück, der lässt sich zu einem boolschen Wert konvertieren
            cout << text << '\n'; //nicht flushen
    } ///Der Stream wird dank RAII sowieso beim Zerstören geschlossen
    

    Man könnte sogar noch weiter gehen, da du hier einfach nur den Inhalt der Datei ausgeben willst:

    std::cout << std::ifstream("Datei_2.txt").rdbuf();
    

    Zu deinem Problem: Es wird nichts ausgegeben, weil entweder die Datei leer ist, oder du den falschen Pfad angibst (guck mal, aus welchem Pfad VS deine Binary laufen lässt).
    Zum Beispiel lässt sich letzteres Prüfen in dem du den Stream direkt nach dem erstellen mit

    stream.good()
    

    prüfst.



  • Vielen Dank 😃

    Dann ist mein Problem, dass ich das den falschen Pfad angegeben habe, bzw. die Datei nicht im Verzeichnis der ausführbaren Dateien liegt.

    Wie bekomme ich diese in das Verzeichnis, bzw wo ist das Verzeichnis zu finden?



  • PDD31 schrieb:

    bzw wo ist das Verzeichnis zu finden?

    Das hängt davon ab, wie, bzw. mit welcher IDE Du Dein Programm erstellst ...
    Du kannst aber einfach den vollständig qualifizierten Pfad Deiner zu verarbeitenden Datei angeben, zB:

    ifstream file("C:\\tmp\\meinVerzeichnis\\Datei_2.txt");
    


  • Belli schrieb:

    vollständig qualifizierten

    Du meinst absoluten 😃



  • Du hast zumindest schon mal richtig erkannt, dass ein nicht absoluter Pfad nicht vollständig ist.
    Ansonsten weiß ich ja jetzt, wen ich in Zukunft fragen kann, wenn ich mal nicht weiß, was ich meine.



  • PDD31 schrieb:

    // ...
        // Solange noch Daten vorhanden sind wird die Schleife ausgeführt
        while (!file.eof()) 
    	{
            // ...
    	}
    // ...
    

    Kommentar und Code passen nicht zusammen.
    Aber der Fehler ist weitverbreitet und taucht hier immer wieder auf.

    Heute möchte ich eine neue Form ausprobieren, um Dir das auszutreiben! 😉

    Um zu zeigen, warum Du input so einlesen solltest, wie z.B. Sone es vorschlägt, hier ein hoffentlich nicht zu schräger Vergleich mit dem sprichwörtlichen Krug, der solange zum Brunnen geht, bis er bricht (http://de.wiktionary.org/wiki/Der_Krug_geht_so_lange_zum_Brunnen,_bis_er_bricht).

    Ich denke Du erkennst die Parallelen zum std::istream , und warum die erste Variante gehe_zum_brunnen() einmal häufiger aufruft als nötig:
    - ein istream setzt das eofbit , wenn eine input operation das Ende der Eingabe erreicht hat.
    - ein Krug setzt das ist_gebrochen_ flag, wenn eine gehe_zum_brunnen() operation, das Ende seiner Lebenszeit erreicht hat.

    #include <iostream>
    
    class Krug{
    public:
      Krug(int max = 5) : max_fuellungen_(max), fuellungen_(0), ist_gebrochen_(false){}
      bool ist_gebrochen() const { return ist_gebrochen_; }
      /* gehe_zum_brunnen()
       * wenn der Krug noch gefuellt werden kann: fuellt den Krug
       * sonst:
       * setzt das ist_gebrochen_ flag und macht nichts
       * Return:
       * true wenn, der Krug gefuellt werden konnte, false sonst
       */
      bool gehe_zum_brunnen(){
        if( !(fuellungen_ < max_fuellungen_) ){
          ist_gebrochen_ = true;
          return false;
        }
        ++fuellungen_;
        return true;
      }
    private:
      int  max_fuellungen_;
      int fuellungen_;
      bool ist_gebrochen_;
    };
    
    int main(){
        Krug krug0, krug1;
        int i = 0, j = 0;
    
        /* Deine Variante: solange ist_gebrochen() false ist, gehe_zum_brunnen() und... */
        std::cout << "Du:\n";
        while(!krug0.ist_gebrochen()){
          std::cout << "gehe zum Brunnen.(" << i << ")\n";
          krug0.gehe_zum_brunnen();
          ++i;
        }
    
        std::cout << "\nIch:\n";
        /* Meine Variante: gehe_zum_brunnen() und wenn das klappt, dann... */
        while(krug1.gehe_zum_brunnen()){
          std::cout << "gehe zum Brunnen.(" << j << ")\n";
          ++j;
        }
    }
    

    Einleuchtend?
    🙂



  • Furble Wurble schrieb:

    PDD31 schrieb:

    // ...
        // Solange noch Daten vorhanden sind wird die Schleife ausgeführt
        while (!file.eof()) 
    	{
            // ...
    	}
    // ...
    

    Kommentar und Code passen nicht zusammen.
    Aber der Fehler ist weitverbreitet und taucht hier immer wieder auf.

    Heute möchte ich eine neue Form ausprobieren, um Dir das auszutreiben! 😉

    Um zu zeigen, warum Du input so einlesen solltest, wie z.B. Sone es vorschlägt, hier ein hoffentlich nicht zu schräger Vergleich mit dem sprichwörtlichen Krug, der solange zum Brunnen geht, bis er bricht (http://de.wiktionary.org/wiki/Der_Krug_geht_so_lange_zum_Brunnen,_bis_er_bricht).

    Ich denke Du erkennst die Parallelen zum std::istream , und warum die erste Variante gehe_zum_brunnen() einmal häufiger aufruft als nötig:
    - ein istream setzt das eofbit , wenn eine input operation das Ende der Eingabe erreicht hat.
    - ein Krug setzt das ist_gebrochen_ flag, wenn eine gehe_zum_brunnen() operation, das Ende seiner Lebenszeit erreicht hat.

    #include <iostream>
    
    class Krug{
    public:
      Krug(int max = 5) : max_fuellungen_(max), fuellungen_(0), ist_gebrochen_(false){}
      bool ist_gebrochen() const { return ist_gebrochen_; }
      /* gehe_zum_brunnen()
       * wenn der Krug noch gefuellt werden kann: fuellt den Krug
       * sonst:
       * setzt das ist_gebrochen_ flag und macht nichts
       * Return:
       * true wenn, der Krug gefuellt werden konnte, false sonst
       */
      bool gehe_zum_brunnen(){
        if( !(fuellungen_ < max_fuellungen_) ){
          ist_gebrochen_ = true;
          return false;
        }
        ++fuellungen_;
        return true;
      }
    private:
      int  max_fuellungen_;
      int fuellungen_;
      bool ist_gebrochen_;
    };
    
    int main(){
        Krug krug0, krug1;
        int i = 0, j = 0;
    
        /* Deine Variante: solange ist_gebrochen() false ist, gehe_zum_brunnen() und... */
        std::cout << "Du:\n";
        while(!krug0.ist_gebrochen()){
          std::cout << "gehe zum Brunnen.(" << i << ")\n";
          krug0.gehe_zum_brunnen();
          ++i;
        }
        
        std::cout << "\nIch:\n";
        /* Meine Variante: gehe_zum_brunnen() und wenn das klappt, dann... */
        while(krug1.gehe_zum_brunnen()){
          std::cout << "gehe zum Brunnen.(" << j << ")\n";
          ++j;
        }
    }
    

    Einleuchtend?
    🙂

    Ist einleuchtend 👍 🙂 werde mich bemühen es in Zukunft besser zu machen 🙂

    Belli schrieb:

    PDD31 schrieb:

    bzw wo ist das Verzeichnis zu finden?

    Das hängt davon ab, wie, bzw. mit welcher IDE Du Dein Programm erstellst ...
    Du kannst aber einfach den vollständig qualifizierten Pfad Deiner zu verarbeitenden Datei angeben, zB:

    ifstream file("C:\\tmp\\meinVerzeichnis\\Datei_2.txt");
    

    Danke Belli, jetzt funktioniert alles so wie gewollt 🙂



  • was muss ich tun, wenn ich jetzt erst ab Zeile 44, Stelle 23 meiner .txt Datei lesen will, da fehlt mir gerade die Idee.

    Ich hab den Code von Sone genommen:

    #include <iostream>
    #include <fstream>
    #include <string>
    
    using namespace std;
    
    void Load()
    {
        ifstream file("C:\\Users\\patrick.dahlke\\Documents\\SWProtokoll\\Datei_2.txt");		
    
        for(std::string text;getline(file, text);) 
            cout << text << '\n'; 
    
    } 
    
    int main(int argc, char **argv)
    {
        Load();
    	getchar();
    	getchar();
        return 0;
    }
    


  • PDD31 schrieb:

    was muss ich tun, wenn ich jetzt erst ab Zeile 44, Stelle 23 meiner .txt Datei lesen will, da fehlt mir gerade die Idee.

    Schau mal, ob das so klappt:

    #include <fstream>
    #include <iostream>
    #include <limits>
    #include <string>
    using namespace std;
    
    template<size_t N>
    istream& skip_line(istream& in)
    {
    	for(size_t i=0; i<N; ++i)
    		in.ignore( numeric_limits<streamsize>::max(), '\n' );
    	return in;
    }
    
    template<size_t N>
    istream& skip_char(istream& in)
    {
    	char c;
    	for(size_t i=0; i<N; ++i)
    		in >> noskipws >> c;
    	return in;
    }
    
    int main()
    {
    	ifstream file("test.txt");
    	file >> skip_line<43>;
    	file >> skip_char<22>;
    	for(string s; getline(file,s); cout<<s<<'\n');
    }
    


  • template<size_t N> 
    istream& skip_char(istream& in) 
    { 
        char c; 
        for(size_t i=0; i<N; ++i) 
            in >> noskipws >> c; 
        return in; 
    }
    

    😃

    template<size_t N> 
    istream& skip_char(istream& in) 
    { 
        return in.ignore(N);
    }
    

    Und eigentlich kann man das gleich schreiben.



  • 😃 😃 Was hab ich den da gemacht. Änder mal eine Funktion ab:

    template<size_t N>
    istream& skip_char(istream& in)
    {
    	return in.ignore( N );
    }
    


  • PDD31 schrieb:

    was muss ich tun, wenn ich jetzt erst ab Zeile 44, Stelle 23 meiner .txt Datei lesen will, da fehlt mir gerade die Idee.

    Das geht nicht, wenn die Zeilen unterschiedlich lang sind. Du musst dann einfach die ersten 43 Zeilen überlesen - das heißt, einlesen und nicht weiter verarbeiten - wenn Du die 44 Zeile eingelesen hast, erst mal feststellen, ob sie überhaupt 23 Zeichen hat, und dann halt die ersten 22 Zeichen aus Deinem String werfen und ab da dann weiter wie gehabt ...



  • Danke out und Sone,

    Belli schrieb:

    PDD31 schrieb:

    was muss ich tun, wenn ich jetzt erst ab Zeile 44, Stelle 23 meiner .txt Datei lesen will, da fehlt mir gerade die Idee.

    Das geht nicht, wenn die Zeilen unterschiedlich lang sind. Du musst dann einfach die ersten 43 Zeilen überlesen - das heißt, einlesen und nicht weiter verarbeiten - wenn Du die 44 Zeile eingelesen hast, erst mal feststellen, ob sie überhaupt 23 Zeichen hat, und dann halt die ersten 22 Zeichen aus Deinem String werfen und ab da dann weiter wie gehabt ...

    In dem Fall ist es so, dass die Datei in Zeile 44 immer mindesten 23 Stellen hat
    und das Gesuchte auch immer an dieser Stelle steht, also müsste das von out eigentlich passen 😃
    Danke 👍



  • Ich hab jetzt am Ende der Datei noch ziemlich viel Müll, zwischendrin eine Zeile die ich brauche und ganz am Ende nochmal eine wichtige Zeile.

    Wie kann ich jetzt die Zeilen dwischendrin rausschmeisen?

    Kennung der Zeilen die nich die Zeilenzahl sondern ein Wort.
    Ich hab sowas noch nie gemacht!

    muss ich da mit fseek in eine Zeile springen, prüfen ob das gewünschte Wort vorhanden ist und wenn nicht die Zeile mit fgets wegschmeißen?

    oder kann ich das Ganze einfacher gestalten?



  • Kennung der Zeilen IST nicht die Zeilenzahl sondern ein Wort.

    sorry



  • Da würde ich durchaus auch zeilenweise vorgehen und das Wort suchen. Das hier funktioniert, wenn das Suchwort am Anfang vorkommt.

    const string searchedWord = "Gurkensalat";
    string token;
    while(stream >> token && token != searchedWord)
        stream >> skip_line; // skip_line s.o.
    
    if(!stream)
        throw InvalidFileFormat();
    


  • PDD31 schrieb:

    Ich hab jetzt am Ende der Datei noch ziemlich viel Müll, zwischendrin eine Zeile die ich brauche und ganz am Ende nochmal eine wichtige Zeile.

    Bei Deinem Kenntnisstand ist es vermutlich das Beste, Du bleibst bei der Vorgehensweise aus Deinem ersten Posting.
    D.h., Du liest jede Zeile der Datei in einen String ein. Den String kannst Du mit Hilfe der Methoden der String-Klasse untersuchen - zB ob ein bestimmtes Wort drin vorkommt -, außerdem kannst Du ja auch die Zeilen mitzählen, für den Fall zB., dass Dich die ersten x Zeilen auf keinen Fall interessieren.
    Zeilen, die für Dich wichtig sind, weil sie zum Beispiel die drölfundzwanzigste Zeile sind, oder weil ein bestimmtes Wort drin vorkommt, verarbeitest Du wie gewünscht, die anderen ignorierst Du einfach.



  • @Eisflamme

    Danke 😃 und was funktioniert, wenn das Wort nicht am Anfang vorkommt?


Log in to reply