unverständnis datei einlesen



  • Hallo alle mit einander.
    Ich suche keine Lösung meines Problems sondern eine Erklärung warum der Code
    so nicht funktioniert.
    Kann mir da jemand weiter helfen ?
    Ich bin Anfänger und nach dem was ich bisher gelesen habe müsste der Code lauffähig sein.
    Ich habe die Zeilen für die Ausgabe mal gelöscht da ich eh nur einen schwarz
    bleibende Console hatte . Dazu habe ich dann die if Abfrage geschrieben um zu erfahren ob überhaupt gelesen werden kann.
    Die sagt mir aber das der Vector leer ist also auch nichts ausgegeben werden kann.
    Die zu öffnende Datei steht im selben Ordner wie die exe sollte also
    keinen Pfad benötigen.

    [/code]#include <iostream>
    #include <fstream>
    using namespace std ;

    int main()
    {
    ifstream datei("T.txt "); // filestream anlegen und datei zum lesen öffnen

    char zeile[1000], *ptr ;

    while(datei.getline(zeile,1000))// filestream in vector zeile[] kopieren.

    cin.sync() ; cin.clear();
    if(zeile[0]=='\0') // abfrage ob inhalt im vector vorhanden
    cout <<"fehler beim einlesen";
    }



  • edit: hier stand Mist.



  • Wer hat dir gesagt was ein vector ist? Deine Variable zeile ist ganz eindeutig ein char array. Vector sieht so aus:

    vector<char> zeile;
    

    Aber eigentlich willst du einen String:

    string zeile;
    


  • #include <iostream>
    #include <fstream>
    
    using namespace std;
    
    int main()
    {
        ifstream datei("T.txt "); // filestream anlegen und datei zum lesen öffnen
    
        char zeile[1000];
    	char * ptr;
    
        while( datei.getline(zeile,1000) ) // filestream in vector zeile[] kopieren.
    		cin.sync();
    
    	cin.clear();
    
    	if ( zeile[0] == '\0' ) // abfrage ob inhalt im vector vorhanden
    		cout << "fehler beim einlesen";
    }
    

    Also das ist erstmal dein Code richtig formatiert.

    - Zeile 11 ist schonmal nicht benutzt.
    - die while Schleife ist an sich korrekt (also die Bedingung), aber sie führt in sich immer nur den sync Befehl aus. Ich weis selbst nichtmals was der macht (ok, er synchronisiert die Eingabepuffer, und das heisst??)
    - deine if-Abfrage ist naja, absolut schwachsinnig. Egal in welchem Fall



  • hm,
    mit cin.sync() und cin.clear() loesche ich den eingabepuffer.
    die if abfrage habe ich ja nur geschrieben um zu sehen ob was im vector abgelegt wurde da ich ja einen schwarzen bildschirm mit promt habe anstatt den text der in der datei liegt ueber cout anzuzeigen.
    danke fuer die info mit dem vector.
    laut meinem buch ist ein array der englische begriff fuer vector ,aber dann muss ich das noch mal nachschlagen.
    An und fuer sich sieht die schleife so aus.
    while(datei.getline(zeile,1000))
    cout<<zeile;



  • utass schrieb:

    hm,
    mit cin.sync() und cin.clear() loesche ich den eingabepuffer.
    die if abfrage habe ich ja nur geschrieben um zu sehen ob was im vector abgelegt wurde da ich ja einen schwarzen bildschirm mit promt habe anstatt den text der in der datei liegt ueber cout anzuzeigen.
    danke fuer die info mit dem vector.
    laut meinem buch ist ein array der englische begriff fuer vector ,aber dann muss ich das noch mal nachschlagen. So ich habe nachgeschlagen.Inhaltsverzeichnis unter Array ->Vector ? Kann das sein das das Buch nichts taugt ?
    An und fuer sich sieht die schleife so aus.
    while(datei.getline(zeile,1000))
    cout<<zeile;



  • Wieso zitierst du dich selbst?? oO

    Nimm statt fstream.getline(char*, streamsize) lieber std::getline(fstream, std::string)

    int main()
    {
    	std::ifstream in("T.txt");
    	std::string zeile;
    
    	while ( std::getline(in, zeile) )
    	{
    		std::cout << zeile << std::endl;
    	}
    
    	return 0x0;
    }
    


  • utass schrieb:

    mit cin.sync() und cin.clear() loesche ich den eingabepuffer.

    Nö. cin.clear() setzt die Fehlerflags zurück, verändert aber nicht den Buffer. cin.sync() hat kein wohldefiniertes Verhalten. Es gab irgendeinen alten Compiler, dessen Standardbibliothek sync() dazu benutzte, den Inhalt des Eingabepuffers wegzuwerfen, aber das ist lange her, ich weiß nicht mehr, welcher das war, und man konnte damit lustige Effekte kriegen, die man nicht haben wollte. Es gibt auch ein paar schlechte Bücher, in denen das drin steht. Wie dem auch sei, durch den C++-Standard gedeckt ist das nicht.

    Es wäre auch nicht klar, was dadurch tatsächlich passieren sollte. Würde der Puffer des mit cin verbundenen streambuf-Objektes verworfen? Das muss nicht der selbe sein wie der mit dem file descriptor verbundene. Sofern der einen hat. Was, wenn jemand dir eine Datei nach stdin umleitet oder die Ausgabe eines anderen Programms? So richtig sinnvoll ist der Ansatz des Pufferwegwerfens nicht.

    Was in solchen Situationen üblicherweise gewollt ist, ist, den Rest der Zeile zu verwerfen. Das geht so:

    #include <iostream>
    #include <limits>
    
    std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
    

    ...wobei std::numeric_limitsstd::streamsize::max() schlicht der größte Wert ist, den eine Variable des Typs std::streamsize annehmen kann. std::cin.ignore() fasst diesen Wert als "unendlich" auf. Die Zeile bedeutet: Ignorier unendlich viele Zeichen oder bis zum nächsten Zeilenumbruch, was immer früher kommt.



  • Skym0sh0 schrieb:

    Wieso zitierst du dich selbst?? oO

    Nimm statt fstream.getline(char*, streamsize) lieber std::getline(fstream, std::string)

    int main()
    {
    	std::ifstream in("T.txt");
    	std::string zeile;
    	
    	while ( std::getline(in, zeile) )
    	{
    		std::cout << zeile << std::endl;
    	}
    	
    	return 0x0;
    }
    

    vielen Dank fuer den code.
    er hilft mir aber leider nicht weiter.
    er bringt die selbe ausgabe wie meiner und dadurch habe ich den denkfehler in meinem code ja trotz alle dem nicht geloest.
    ich haette auch einen code der funktioniert aber dadurch ist mir beim verstaendnis geholfen. Ich bin ja autodidakt und kann keinen bei offenen frage auf den sack gehen ;=} ich habe auch noch 500 seiten buch vor mir aber ich
    das mit dem selbst zitieren liegt daran das ich keine foren erfahrung habe und hier noch etwas unbedarft bin.
    was sagst du zu array = vector ?



  • seldon schrieb:

    utass schrieb:

    mit cin.sync() und cin.clear() loesche ich den eingabepuffer.

    Nö. cin.clear() setzt die Fehlerflags zurück, verändert aber nicht den Buffer. cin.sync() hat kein wohldefiniertes Verhalten. Es gab irgendeinen alten Compiler, dessen Standardbibliothek sync() dazu benutzte, den Inhalt des Eingabepuffers wegzuwerfen, aber das ist lange her, ich weiß nicht mehr, welcher das war, und man konnte damit lustige Effekte kriegen, die man nicht haben wollte. Es gibt auch ein paar schlechte Bücher, in denen das drin steht. Wie dem auch sei, durch den C++-Standard gedeckt ist das nicht.

    Es wäre auch nicht klar, was dadurch tatsächlich passieren sollte. Würde der Puffer des mit cin verbundenen streambuf-Objektes verworfen? Das muss nicht der selbe sein wie der mit dem file descriptor verbundene. Sofern der einen hat. Was, wenn jemand dir eine Datei nach stdin umleitet oder die Ausgabe eines anderen Programms? So richtig sinnvoll ist der Ansatz des Pufferwegwerfens nicht.

    Was in solchen Situationen üblicherweise gewollt ist, ist, den Rest der Zeile zu verwerfen. Das geht so:

    #include <iostream>
    #include <limits>
    
    std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
    

    ...wobei std::numeric_limitsstd::streamsize::max() schlicht der größte Wert ist, den eine Variable des Typs std::streamsize annehmen kann. std::cin.ignore() fasst diesen Wert als "unendlich" auf. Die Zeile bedeutet: Ignorier unendlich viele Zeichen oder bis zum nächsten Zeilenumbruch, was immer früher kommt.

    Also mein Buch ist" C++ Lernen und profesionell anwenden" in der Aktuellen Ausgabe von Ulla Kirch und Peter Prinz.
    sollte ich dieses verwerfen das ich nichts falsches lerne und kannst Du ein Buch empfehlen ?



  • Ich habe das Buch nicht gelesen, kann also die Qualität nicht verlässlich beurteilen. Die Vermutung steht aber natürlich im Raum, dass das nicht der einzige grobe Schnitzer darin sein könnte -- zumal du gerade char-Buffer als Strings missbrauchst, wie man das eher in C-Code erwarten würde.

    Gute Einsteigerbücher sind der "C++ Primer" (nicht den "C++ Primer Plus" -- das ist ein Schwindel, der den guten Namen des Primer abzuschöpfen versucht) von Lippman, Lajoie und Moo sowie "Einführung in die Programmierung mit C++" von Stroustrup. Allerdings ist die fünfte Auflage des C++ Primer, die den neuen Standard behandelt, noch nicht ins Deutsche übersetzt. Ich weiß nicht, wie gut dein Englisch ist.



  • oh englisch gleich 0.
    Ich dacht eigendlich das ich ein gutes Buch gekauft habe da die Schriftsteller
    auch Vorlesungen an verschiedenen Unis halten.
    Aber nun wir sind alles nur Menschen.
    Ich finde das Buch auch relativ schwer zu verstehen deshalb werde ich mich mal nach Deinen Empfehlungen umschauen.Schade ist es nur um das Geld was ich dafuer ausgegeben habe.
    Du bist nicht Registriert bist Du trotz dem oeffters hier ?
    Ach und kannst Du mir sagen wo bei meinem Code der Denkfehler ist ?
    Darf die Datei die ich oeffnen will eventuell keine Textdatei sein sondern ist der Code fuer andere Dateien zu nutzen ?



  • Wenn ich richtig verstehe, was das Problem ist -- mir ist nicht ganz klar, was das Programm eigentlich genau machen soll -- sehe ich zwei Möglichkeiten:

    1. Die Datei muss im Arbeitsverzeichnis liegen, nicht notwendigerweise in dem, in dem die .exe liegt. Das Arbeitsverzeichnis ist das Verzeichnis, in dem ein Prozess arbeitet -- wen du es von der Konsole startest, ist es das Verzeichnis, in dem du dich zu diesem Zeitpunkt befindest. In Windows-Verknüpfungen ist es beispielsweise einstellbar. Wenn du direkt auf die .exe doppelklickst, meines Wissens das Verzeichnis, in dem die .exe liegt. Wenn du das Programm aus Visual Studio im Debugger startest, ist es in den Projekteinstellungen einstellbar. Du musst sicherstellen, dass die Datei im Arbeitsverzeichnis liegt bzw. der relative Pfad, den du benutzt, von dort aus richtig ist.

    2. (wahrscheinlicher) endet die Datei mit einem Zeilenumbruch, so dass die letzte Zeile stumpf leer ist. Dann ist zeile[0] == '\0', wenn das Einlesen fehlerlos geklappt hat.

    Aber was genau willst du eigentlich erreichen?



  • also ich will die Datei in einem Vector ablegen anschliessend möchte ich mein erlerntes über Zeigeraretmetik festigen und die Datei mit einem Zeiger sortieren und lesbar anzeigen. Es handelt sich um eine Messdatendatei mit unbekannter Formatierung . So das ich Zeilen und Abstände neu definieren muss.
    Wie gesagt rein aus Übungstechnischen gründen. Hier bin ich gelandet weil ich Hauptsächlich versuche ich zu verstehen warum der Code nicht das macht was ich mir vorstelle. 😞 Laut meinem Buch müsste der Code so funktionieren und mir in der Console ausgegeben werden.



  • ach jetzt fällt mir auf das daduch das die zu öfnende Datei als txt Datei
    umbenannt habe reden alle von String einlesen. Das habe ich gemacht weil ich
    die Datei in einem Texteditor unformatiert lesen kann. Das ist im Buch aber noch nicht dran.



  • Damit ich dazu sinnvoll was sagen kann, musst du mir erklären, wie die Datei aufgebaut ist.



  • Einen wunderschönen guten Morgen Seldon

    [code="cpp"]DATE,TIME,NUM,NUM,NUM,NUM,NUM,NUM,NUM,NUM,NUM,NUM,NUM,NUM,NUM,NUM,NUM,NUM,NUM,NUM,NUM,NUM,NUM,NUM,NUM,NUM,NUM,NUM,NUM,NUM,NUM,NUM,NUM,NUM,NUM,NUM,NUM,NUM,NUM,NUM,NUM,NUM,NUM,NUM,NUM,NUM,NUM,NUM,NUM,NUM,NUM,NUM
    Date,Time,Aussentemperatur,Saugdruck_40_ND_Temp,Temperatur_TK_1,Ist_Soll1_Ein_V1_TK1,Temperatur_TK_2,Ist_Soll1_Ein_V1_TK2,Temperatur_TK_3A,Ist_Soll1_Ein_V1_TK3A,Temperatur_TK_3B,Ist_Soll1_Ein_V1_TK3B,Temperatur_TK_4,Ist_Soll1_Ein_V1_TK4,Temperatur_TK_5,Ist_Soll1_Ein_V1_TK5,Temperatur_TK_6,Ist_Soll1_Ein_V1_TK6,Temperatur_TK_7,Ist_Soll1_Ein_V1_TK7,Temperatur_TK_8,Ist_Soll1_Ein_V1_TK8,Temperatur_TK_9,Ist_Soll1_Ein_V1_TK9,Temperatur_TK_10,Ist_Soll1_Ein_V1_TK10,Temperatur_TK_11,Ist_Soll1_Ein_V1_TK11,Temperatur_Froster_1,Ist_Soll1_Ein_V1_Froster_1,Temperatur_Froster_2,Ist_Soll1_Ein_V1_Froster_2,Temperatur_Froster_3,Ist_Status_V1_Froster_3,Temperatur_Haengeraum_1,Ist_Soll1_V1_Haengeraum_1,Temperatur_Haengeraum_2,Ist_Soll1_V1_Haengeraum_2,Temperatur_Haengeraum_3,Ist_Soll1_V1_Haengeraum_3,Temperatur_Lager_1,Ist_Soll1_V1_Lager_1,Temperatur_Lager_2,Ist_Soll1_V1_Lager_2,Temperatur_Zerlegung,Ist_Soll1_V1_Zerlegung,Temperatur_Verpackung_1,Ist_Soll1_V1_Verpackung_1,Temperatur_Verpackung_2,Ist_Soll1_V1_Verpackung_2,Temperatur_Kellerraum,Ist_Soll1_V1_Keller
    2012-02-28,23:15:00:187,8.5,-34.8163303158715,-19.6,-20,-20.2,-20,-23.6,-25,-23.8,-25,-21.9,-25,-19.1,-20,-20.2,-20,-20.3,-20,-25.7,-25,-24.4,-25,-2,0,-1.4,0,-9.8,-18,-29.5,-28,-18.1,1,5.6,3,7.1,3,5.8,3,8.3,2,8.9,2,8.9,15,7.9,15,7.8,7,5.1,6
    2012-02-28,23:30:00:562,8.5,-35.6672671742579,-21.1,-20,-20.2,-20,-23.7,-25,-23.8,-25,-22.2,-25,-19.3,-20,-20.1,-20,-20.1,-20,-25.5,-25,-24.3,-25,-1.6,0,-0.8,0,-9.7,-18,-29.6,-28,-17,6,5.6,3,7.1,3,5.8,3,8.2,2,8.8,2,8.8,15,7.9,15,7.8,7,5.3,6
    2012-02-28,23:45:00:140,8.5,-34.6082018512386,-21.5,-20,-20.3,-20,-23.8,-25,-23.9,-25,-22.3,-25,-19.5,-20,-20.2,-20,-20.2,-20,-25.5,-25,-24.9,-25,-1.5,0,-0.3,0,-9.8,-18,-29.4,-28,-19.7,1,5.6,3,7,3,5.8,3,8.3,2,8.8,2,8.8,15,7.9,15,7.8,7,5.1,6
    2012-02-29,00:00:00:531,8.4,-35.6672671742579,-21.9,-20,-20.2,-20,-23.9,-25,-24,-25,-22.4,-25,-19.1,-20,-20.1,-20,-20.1,-20,-25.7,-25,-24.8,-25,-1.3,0,-1,0,-9.8,-18,-30,-28,-19.1,1,5.5,3,7.1,3,5.8,3,8.3,2,8.9,2,8.8,15,7.9,15,7.9,7,5.3,6
    2012-02-29,00:15:00:546,8.4,-34.401844643366,-22.1,-20,-20.2,-20,-24,-25,-24.1,-25,-22.1,-25,-19,-20,-20.2,-20,-20.2,-20,-25.2,-25,-25.1,-25,-1.7,-2,-1.1,-2,-9.8,-18,-29.8,-28,-18.4,1,5.6,3,7.1,3,5.8,3,8.4,2,8.8,2,8.9,15,7.9,15,7.8,7,5.1,6
    2012-02-29,00:30:00:781,8.4,-34.8163303158715,-22.1,-20,-20.2,-20,-24,-25,-24,-25,-21.8,-25,-18.9,-20,-20.1,-20,-20.1,-20,-25.3,-25,-25.1,-25,-5.3,-2,-3.2,-2,-9.8,-18,-29.4,-28,-17.4,1,5.6,3,7,3,5.8,3,8.5,2,8.8,2,8.8,15,8,15,7.9,7,5.2,6
    2012-02-29,00:45:00:437,8.3,-33.7930685684441,-22.2,-20,-20.3,-20,-24,-25,-24,-25,-21.5,-25,-18.8,-20,-20,-20,-20.3,

    ich habe mal einen Teil von dem was ich im Texteditor sehe hier reingestellt
    Ich vermute das der Kopf eine Art Formatierung darstellt.

    Kannst Du daran erkennen aus welchem Grund ich die Datei über meinen Code nicht einlesen kann ? Fuer mich sind das nur Buchstaben und Zahlen .
    Dazu wie ich das sortieren kann habe ich mir schon gedanken gemacht.



  • Okay, wir reden also über eine ziemlich normale CSV-Datei, und ich sehe nicht mal quoted Strings. Das sollte sich machen lassen. Dein Code liest die Datei wohl auch ein, aber du machst nichts mit den eingelesenen Daten.

    Ich fang mal einfach an. Wenn du die Datei zeilenweise einlesen und speichern willst, geht das am einfachsten so:

    #include <fstream>
    #include <string>
    #include <vector>
    
    int main() {
      std::vector<std::string> zeilen;
      std::ifstream in("datei.csv");
      std::string s;
    
      while(std::getline(in, s)) { // Solange eine Zeile eingelesen werden konnte:
        zeilen.push_back(s);       // Häng die Zeile an den Vektor an.
      }
    
      // Hier beinhaltet zeilen die Zeilen der Datei, d. h. zeilen[0] ist "DATE,TIME,...", 
      // zeilen[1] ist "Date,Time,..." usw.
    }
    

    Das hilft dir aber nur bedingt weiter, weil du ja die Felder getrennt haben willst. Da deine Datei sehr einfach aufgebaut ist (insbesondere ohne quoted strings, die Kommata enthalten könnten), kriegt man das auch ohne größere Probleme hin. Ich führe an dieser Stelle Stringstreams ein; das sind Datenströme, die sich statt aus einer Datei aus einem String speisen (aber sonst (fast) genau so benutzt werden wie Dateien):

    #include <fstream>
    #include <sstream>
    #include <string>
    #include <vector>
    
    std::vector<std::string> zerlege_csv_zeile(std::string const &zeile) {
      std::vector<std::string> ergebnis;
      std::istringstream in(zeile); // <-- Stringstream hier
      std::string s;
    
      while(std::getline(in, s, ',')) { // Ziehe alles bis zum nächsten Komma aus dem Stream.
                                        // Merke: das ist das selbe wie das Holen einer Zeile,
                                        // nur mit Komma statt Zeilenumbruch.
        ergebnis.push_back(s);
      }
    
      return ergebnis;
    }
    
    int main() {
      std::vector<std::vector<std::string> > csv;
      std::string s;
      std::ifstream in("datei.csv");
    
      while(std::getline(in, s)) {
        csv.push_back(zerlege_csv_zeile(s));
      }
    
      // csv enthält die CSV-Datei in Tokens aufgespalten, d. h.
      // csv[0][0] == "DATE", csv[0][1] == "TIME", csv[0][2] == "NUM", ...
      // csv[1][0] == "Date", csv[1][1] == "Time", csv[1][2] == "Aussentemperatur", ...
      // csv[2][0] == "2012-02-28", csv[2][1] == "23:15:00", csv[2][2] == "187", ...
    }
    

    Damit kann man schon mal weiterarbeiten. Jetzt sind die einzelnen Tokens noch als String gespeichert, und ich gehe stark davon aus, dass du sie später als Zahlen behandeln willst, von daher wirst du sie noch umwandeln müssen -- das ist bei den Zahlen relativ simpel:

    #include <limits>
    #include <sstream>
    #include <string>
    
    double string_to_double(std::string const &s) {
      double d = std::numeric_limits<double>::quiet_NaN(); // im Fehlerfall NaN
    
      std::istringstream in(s);
      in >> d;
    
      return d;
    }
    

    Für das Datum und die Uhrzeit wirst du dir selbst was schreiben/suchen müssen. Ich wäre nicht überrascht, wenn Boost.DateTime da schon etwas hätte; Du hast den Kram ja im ISO-Format. Das hauptsächliche Gefummel bei diesem Schritt ist die Fehlerbehandlung (was passieren soll, wenn dir jemand in die Datei in ein Zahlenfeld "abc" reinschreibt und so). Oh, und du musst natürlich aufpassen, dass du nicht über die Vektorgrenzen hinaus liest. Es kann durchaus passieren, dass in einer Eingabedatei die Zeilen unterschiedlich lang sind; so was musst du dann abfangen.



  • erst einmal vielen Dank für Deine Mühe , ich weiss garnicht wie ich das wieder gut machen kann.
    Ich sehe aber auch es gibt noch sehr viel zu lernen .Auf jeden Fall werde ich schauen was ich damit machen kann.
    Was sind den die Merkmale einer csv Datei ? Woran hast Du das erkannt ?
    Was bedeutet die Schreibweise "Vector<string>" ? Ist das die Deklaration für einen Container oder Template ? Ich greife dem Buch einfach mal vorweg , davon habe ich nämlich noch nichts gelesen. Kannst Du mir dazu noch etwas sagen.
    Dann will ich Deine freundliche Unterstützung aber auch nicht länger strapazieren und ich werde mich erst einmal mit dem von Dir gezeigten Code beschäftigen sowie weiter im Buch lesen.
    Ich sage nochmals vielen Dank und würde mich freuen wenn bei mir mal wieder offenen Fragen auftauchen hier mal wieder Deinen Rat erhalten zu dürfen.



  • utass schrieb:

    Was sind den die Merkmale einer csv Datei ? Woran hast Du das erkannt ?

    Eine csv-Datei ist sozusagen eine einfache txt-Tabelle. Einzelne spalten sind durch ein Zeichen ( meinst ; ) getrennt.

    utass schrieb:

    Was bedeutet die Schreibweise "Vector<string>" ? Ist das die Deklaration für einen Container oder Template ?

    std::vector ist ein Container der STL. In diesem fall hält der Container Elemente des Typs std::string .

    utass schrieb:

    Ich sage nochmals vielen Dank und würde mich freuen wenn bei mir mal wieder offenen Fragen auftauchen hier mal wieder Deinen Rat erhalten zu dürfen.

    Dafür ist das Forum da. :p


Log in to reply