Datei zeilenweise einlesen



  • Hi,

    ich habe folgende Funktion zum zeilenweisen einlesen von Dateien
    geschrieben. Innerhalb der Funktion funktioniert alles wie gewünscht,
    allerdings kriege ich es nicht hin, die eingelesenen Zeilen nach außen
    zu geben. Dort sind die Inhalte des Vektors (nicht der Vektor) leider
    leer. Ich vermute, dass es an dem Gültigkeitsbereich der Variable line
    liegt. Leider weiss ich nicht, wie ich das lösen kann. Kann mir jemand
    kurz helfen? Danke. Hier mein Erguss:

    const std::vectorstd::string Database::getOrte() const {

    // Oeffne Datei
    std::ifstream ifs(dataBaseFile.c_str(), std::ios_base::in);

    // Datei geoffnet ?
    if (!ifs) {
    std::cout << "Cannot open file.";
    }

    std::vectorstd::string lines;
    std::string line;
    while (!ifs.eof()) {
    std::getline(ifs, line);
    lines.push_back(line);
    }

    // Dateizugriff aufraeumen
    ifs.clear();
    ifs.close();

    // Liste von Zeilen zurueckgeben
    return lines;
    }

    Ich greife auf die Zeilen von Außen wie folgt zu:

    vector<string> orte = database.getOrte();
    vector<string>::iterator iOrteOuter;
    for (iOrteOuter = orte.begin(); iOrteOuter < orte.end(); +
    +iOrteOuter) {
    cout << *iOrteOuter;
    }

    In der Ausgabe erhalte ich dann leider nur leere Zeilen. Muss ich an
    irgendeiner stelle noch etwas dereferenzieren oder die zeile anders
    anders an lines.push_back(line); übergeben?

    Danke,

    Maciek



  • wenn du code Tags also [ cpp] und [ /cpp] (ohne das Leerzeichen) verwendest wird dir hier sicher besser geholfen



  • stimmt, das habe ich übersehen und freue mich auf die Hilfe auf meine Frage.

    const std::vector<std::string> Database::getOrte() const {
    
                   // Oeffne Datei
                   std::ifstream ifs(dataBaseFile.c_str(), std::ios_base::in);
    
                   // Datei geoffnet ?
                   if (!ifs) {
                           std::cout << "Cannot open file.";
                   }
    
                   std::vector<std::string> lines;
                   std::string line;
                   while (!ifs.eof()) {
                           std::getline(ifs, line);
                           lines.push_back(line);
                   }
    
                   // Dateizugriff aufraeumen
                   ifs.clear();
                   ifs.close();
    
                   // Liste von Zeilen zurueckgeben
                   return lines;
           }
    

    Ich greife auf den Vector wie folgt aus einer anderen Klasse zu:

    vector<string> orte = database.getOrte();
           vector<string>::iterator iOrteOuter;
           for (iOrteOuter = orte.begin(); iOrteOuter < orte.end(); +
    +iOrteOuter) {
                cout << *iOrteOuter;
           }
    


  • Stimmt der Pfad und ist in der Datei auch was drin?
    Wenn die Datei nicht geöffnet werden konnte, solltest du auch nicht weiter machen.
    Schon mal nen Debugger verwendet?



  • Hi,

    der Zugriff stimmt. Ich bekomme wie gewünscht einen Vektor zurück, der hat dann allerdings als Inhalt Referenzen auf line Objekte, die nicht mehr gültig sind, weil die Funktion zum Lesen der Zeilen bereits beendet wurde. Meine konkrete Frage wäre daher, wie ich die Zeilen so auslese und übergebe, dass sie dauerhaft sind.



  • Hi,

    habe mir die Funktionen noch mal angesehen und das Problem gelöst. Da ich seit mehr als 10 Jahren Java programmiere und mit Cpp nur sporadisch in Berührung komme, hatte ich die Referenzen mal wieder vergessen :-)) Hier ist die Lösung, bei der ein istringstream die lokale Gültigkeit scheinbar durchbricht.

    Frage: Ist das richtige Lösung? Muss ich ggf. noch etwas nach der Benutzung der Funktion betrachten? Also insbedondere Freigabe der übertragenen Zeichneketten um Speicherlecks zu vermeiden?

    #include <iostream>
    #include <fstream>
    #include <sstream>
    ...
    	const std::vector<std::string> Database::getZeilen(const std::string &dataBaseFile) const {
    
    		// Oeffne Datei
    		std::ifstream ifs(dataBaseFile.c_str(), std::ios_base::in);
    
    		// Datei geoffnet ?
    		if (!ifs) {
    			std::cout << "Cannot open file.";
    		}
    
    		std::vector<std::string> lines;
    		std::string linebuffer;
    
    		while (std::getline(ifs, linebuffer)) {
    			 :arrow_right: std::istringstream iss(linebuffer);
    			 :arrow_right: std::string aLine = "asas";
    			 :arrow_right: iss >> aLine;
    			 :arrow_right: lines.push_back(aLine);
    		}
    
    		// Dateizugriff aufraeumen
    		ifs.clear();
    		ifs.close();
    
    		// Liste von Zeilen zurueckgeben
    		return lines;
    	}
    


  • Das ist vollkommen unnötig was du da machst, der erste Code funktioniert genauso. Mit lines.push_back fügst du immer eine Kopie des Strings in den Vector ein. Und bei return lines; wird dann eine Kopie von allem an die Aufrufstelle zurückgegeben. Das hat mit Referenzen überhaupts nichts zu tun. Und der Gültigkeitsbereich eines Strings ändert sich nicht, wenn man ihn Durch einen Stream schiebt.



  • Coder Bene XIV schrieb:

    Das ist vollkommen unnötig was du da machst, der erste Code funktioniert genauso. Mit lines.push_back fügst du immer eine Kopie des Strings in den Vector ein. Und bei return lines; wird dann eine Kopie von allem an die Aufrufstelle zurückgegeben. Das hat mit Referenzen überhaupts nichts zu tun. Und der Gültigkeitsbereich eines Strings ändert sich nicht, wenn man ihn Durch einen Stream schiebt.

    Hallo Coder Bene XIV,

    der erste Code hat nicht funktioniert. Ich bekomme beim Auslesen dann nur leere Zeichenketten zurück.



  • const std::vector<std::string> getOrte() {
    
               // Oeffne Datei
    	 std::ifstream ifs("C:\\test.txt", std::ios_base::in);
    
               // Datei geoffnet ?
               if (!ifs) {
                       std::cout << "Cannot open file.";
               }
    
               std::vector<std::string> lines;
               std::string line;
               while (!ifs.eof()) {
                       std::getline(ifs, line);
                       lines.push_back(line);
               }
    
               // Dateizugriff aufraeumen
               ifs.clear();
               ifs.close();
    
               // Liste von Zeilen zurueckgeben
               return lines;
       } 
    int main () {  
    
    	std::vector<std::string> orte = getOrte();
    	std::vector<std::string>::iterator iOrteOuter;
          for (iOrteOuter = orte.begin(); iOrteOuter < orte.end(); ++iOrteOuter) {
    		  std::cout << *iOrteOuter;
           } 
        return 0;
    }
    

    Gibt bei mir was aus, wenns die Datei gibt.



  • Kann es sein, dass der Unterschied daher kommt, dass bei mir die Funktion in einer eigenen Klasse definiert ist?



  • maciekh schrieb:

    Kann es sein, dass der Unterschied daher kommt, dass bei mir die Funktion in einer eigenen Klasse definiert ist?

    Hier der Quellcode des Header und der Klasse:

    /*
     * Database.h
     */
    
    #ifndef DATABASE_H_
    #define DATABASE_H_
    
    #include <iostream>
    #include <vector>
    #include <string>
    
    using namespace std;
    
    namespace hw {
    
    	class Database {
    
    	public:
    
    		// Constructor
    		Database(const string &fileName);
    
    		// Constructor
    		virtual ~Database();
    
    		// Initialisiere Datenbank
    		void init();
    
    		// Lese Orte aus der datenbank
    		const vector<string> getOrte();
    
    	private:
    
    		const string dataBaseFile;
    
    	};
    }
    #endif /* DATABASE_H_ */
    
    /*
     * Database.cpp
     *
     *  Created on: 14.07.2008
     *  Author: mab
     */
    #include <iostream>
    #include <fstream>
    #include <sstream>
    #include "Database.h"
    
    using namespace std;
    
    namespace hw {
    
    	Database::Database(const std::string & fileName) :
    		dataBaseFile(fileName) {
    		std::cout << "constructed -> database: " << dataBaseFile << std::endl;
    	}
    
    	Database::~Database() {
    		std::cout << "deconstructed -> database: " << dataBaseFile << std::endl;
    	}
    
    	void Database::init() {
    		std::cout << "init --> database: " << dataBaseFile << std::endl;
    	}
    
    	const std::vector<std::string> Database::getOrte() const {
    
    		// Oeffne Datei
    		std::ifstream ifs(dataBaseFile.c_str(), std::ios_base::in);
    
    		// Datei geoffnet ?
    		if (!ifs) {
    			std::cout << "Cannot open file.";
    		}
    
    		std::vector<std::string> lineVector;
    		std::string linebuffer;
    
    		while (std::getline(ifs, linebuffer)) {
    			std::istringstream iss(linebuffer);
    			std::string aLine = "empty";
    			iss >> aLine;
    			lineVector.push_back(aLine.c_str());
    		}
    
    		// Dateizugriff aufraeumen
    		ifs.clear();
    		ifs.close();
    
    		// Liste von Orten zurueckgeben
    		return lineVector;
    	}
    
    }
    

    Und der Aufruf:

    #include "Database.h"
    
    using namespace std;
    using namespace hw;
    ...
    	Database database("orte.txt");
    	database.init();
    	vector<string> orte = database.getOrte();
    ...
    

Anmelden zum Antworten