Daten aus Datei einlesen


  • Mod

    Es gibt im Header string ein getline, welches dir eher passen dürfte:
    http://www.cplusplus.com/reference/string/getline/

    Das getline welches Member der istreams ist und auf char-Feldern arbeitet ist eher historisch interessant.

    Ja, die Einlesefunktionen (und auch die Ausgabefunktionen) der Streams geben (fast) alle den Stream selber zurück. Nur so ist es möglich, mehrere dieser Funktionen aneinander zu reihen:

    int a,b;
    std::cin >> a >> b; // std::cin >> a gibt std::cin zurück, darauf kann dann std::cin >> b arbeiten
    

    Außerdem können Streams auf ihren Status geprüft werden, indem man sie in einem boolschen-Ausdruck auswertet. Dabei spielen eine Rolle:
    http://www.cplusplus.com/reference/iostream/ios/operatornot/
    http://www.cplusplus.com/reference/iostream/ios/operator_voidpt/
    Da, wie schon gesagt, die Eingabefunktionen den Stream selber zurück liefern, kann man daher das gezeigte

    while(std::cin >> s)
    

    benutzen, um bis zum Auftreten eines Fehlers zu lesen. Dies ist auch eine sehr übliche Art und Weise aus einem Stream zu lesen. Hier wird also erst der operator>> benutzt, dieser liefert wieder std::cin, dieses wird dann in einen void* konvertiert und dieser kann dann 0 oder etwas anderes sein, je nach Fehler oder kein Fehler. Und dies ist für die while-Schleife dann eben false oder true.

    (Achtung: Die mögliche Konvertierung der Streams nach void* führt manchmal zu interessanten Anfängerfehlern:

    std::stringstream foo("Hallo Welt");
    std::cout << foo;
    

    Dies ist kein Compilerfehler, gibt aber nicht "Hallo Welt" aus, sondern einen kryptischen Zahlenwert.)



  • SeppJ schrieb:

    (Achtung: Die mögliche Konvertierung der Streams nach void* führt manchmal zu interessanten Anfängerfehlern:

    std::stringstream foo("Hallo Welt");
    std::cout << foo;
    

    Dies ist kein Compilerfehler, gibt aber nicht "Hallo Welt" aus, sondern einen kryptischen Zahlenwert.)

    Öm, ja. Das hatte ich gestern erst. 🙄 😃

    'unschuldig-an-die-Decke-guck-und-pfeif'

    EDIT:
    Na immerhin kann ich es reproduzieren:

    #include <iostream>
    #include <string>
    #include <fstream>
    
    int main()
    {
    	std::string filename("data.dat");
    
    	std::ifstream infile(filename.c_str());
    
    	std::cout << infile << std::endl;
    
    	return 0;
    }
    

    Dann kriege ich

    0x7fff0b4474f0
    

    Also ich nehme an, dass ich mir damit die Adresse zeigen lasse, wo der 'Stream liegt' und ich eigentlich den Inhalt sehen möchte?

    So wie ich z.B. einen Pointer derefenzieren muss, wenn ich das verändern möchte, worauf er zeigt?

    Kann man das so vergleichen?

    Gruß,
    Klaus.



  • Juhuuuu!!! Es funktioniert!

    #include <iostream>
    #include <string>
    #include <fstream>
    
    int main()
    {
    	std::string filename("data.dat");
    
    	std::ifstream infile(filename.c_str());
    
    	std::string x_value, y_value;
    
    	for(int i = 0; i < 4; ++i)
    	{
    		infile >> x_value;
    		infile >> y_value;
    
    		std::cout << x_value << "\t" << y_value << std::endl;
    	}
    
    	return 0;
    }
    

    Liefert tatsächlich:

    1	1
    2	4
    3	9
    4	16
    

    Genau was in der Datei steht! 🕶

    Gruß,
    Klaus.



  • Klaus82 schrieb:

    Also ich nehme an, dass ich mir damit die Adresse zeigen lasse, wo der 'Stream liegt' und ich eigentlich den Inhalt sehen möchte?

    Hier der Standard:

    C++-Standard 27.4.4.3 Klausel 1 schrieb:

    Returns: If fail() then a null pointer; otherwise some non-null pointer to indicate success then a value that will
    evaluate false in a boolean context; otherwise a value that will evaluate true in a boolean context. The value type
    returned shall not be convertible to int.

    Es ist also (seit C++11?) nicht definiert, welchen Rückgabetyp der überladene Operator hat. Lediglich, dass der Rückgabetyp zu bool konvertierbar sein muss. Außerdem ist festgehalten, dass der Typ nicht zu einem Integral (sprich: zu int, long, short, char oder long long ) konvertierbar sein darf (was eigentlich schon impliziert, dass es sich um einen Pointer handeln soll, ich sehe keinen Grund es anders zu machen).

    Lange Rede kurzer Sinn: Versuch ja nicht, etwas mit dieser Adresse zu machen 😉


  • Mod

    Hacker schrieb:

    Klaus82 schrieb:

    Also ich nehme an, dass ich mir damit die Adresse zeigen lasse, wo der 'Stream liegt' und ich eigentlich den Inhalt sehen möchte?

    Hier der Standard:

    C++-Standard 27.4.4.3 Klausel 1 schrieb:

    Returns: If fail() then a null pointer; otherwise some non-null pointer to indicate success then a value that will
    evaluate false in a boolean context; otherwise a value that will evaluate true in a boolean context. The value type
    returned shall not be convertible to int.

    Es ist also (seit C++11?) nicht definiert, welchen Rückgabetyp der überladene Operator hat. Lediglich, dass der Rückgabetyp zu bool konvertierbar sein muss. Außerdem ist festgehalten, dass der Typ nicht zu einem Integral (sprich: zu int, long, short, char oder long long ) konvertierbar sein darf (was eigentlich schon impliziert, dass es sich um einen Pointer handeln soll, ich sehe keinen Grund es anders zu machen).

    Lange Rede kurzer Sinn: Versuch ja nicht, etwas mit dieser Adresse zu machen 😉

    Bitte nur als Standard zitieren, was auch Standard ist.

    n3290 schrieb:

    27.5.5.4 basic_ios flags functions [iostate.flags]
    explicit operator bool() const;
    1 Returns: !fail().



  • camper schrieb:

    Hacker schrieb:

    Klaus82 schrieb:

    Also ich nehme an, dass ich mir damit die Adresse zeigen lasse, wo der 'Stream liegt' und ich eigentlich den Inhalt sehen möchte?

    Hier der Standard:

    C++-Standard 27.4.4.3 Klausel 1 schrieb:

    Returns: If fail() then a null pointer; otherwise some non-null pointer to indicate success then a value that will
    evaluate false in a boolean context; otherwise a value that will evaluate true in a boolean context. The value type
    returned shall not be convertible to int.

    Es ist also (seit C++11?) nicht definiert, welchen Rückgabetyp der überladene Operator hat. Lediglich, dass der Rückgabetyp zu bool konvertierbar sein muss. Außerdem ist festgehalten, dass der Typ nicht zu einem Integral (sprich: zu int, long, short, char oder long long ) konvertierbar sein darf (was eigentlich schon impliziert, dass es sich um einen Pointer handeln soll, ich sehe keinen Grund es anders zu machen).

    Lange Rede kurzer Sinn: Versuch ja nicht, etwas mit dieser Adresse zu machen 😉

    Bitte nur als Standard zitieren, was auch Standard ist.

    n3290 schrieb:

    27.5.5.4 basic_ios flags functions [iostate.flags]
    explicit operator bool() const;
    1 Returns: !fail().

    In welchem Standard bin ich denn?

    www.open-std.org/jtc1/sc22/wg21/docs/papers/2005/n1905.pdf
    Und du?



  • Hi,

    jetzt natürlich die Masterfrage:
    Wie kriege ich die Werte meiner Strings in wissenschaftlicher Notation in einen integer umgewandelt.
    Also bisher habe ich

    #include <iostream>
    #include <string>
    #include <fstream>
    #include <vector>
    #include <stdlib.h>
    
    int main()
    {
    	std::string filename("f.positive.dat");
    
    	std::ifstream infile(filename.c_str());
    
    	std::string s1,s2,s3;
    	double energy;
    	long int number, integrated_number;
    
    	for(int i = 0; i < 4; ++i)
    	{
    		infile >> s1;
    		infile >> s2;
    		infile >> s3;
    
    		energy = atof(s1.data());
    		number = atol(s2.data());
    
    		std::cout << s1 << "\t" << s2 << std::endl;
    		std::cout << energy << "\t" << number << std::endl;
    	}
    
    	return 0;
    }
    

    Was mir dann die Ausgabe liefert

    0.000000000000000E+000	7.460079967364139E+023
    0	7
    3.300000000000000E-002	9.496822501615066E+020
    0.033	9
    6.600000000000000E-002	7.581970551546497E+020
    0.066	7
    9.900000000000002E-002	6.117185676453359E+020
    0.099	6
    

    Also die eine Zeile zeigt schön den Inhalt des Strings, während die andere Zahl gerade bei der Konvertierung in einen Integer leider versagt. 😞

    Also Bonus will ich das ganze sowieso noch durch 1.0e16 teilen, geht das nicht auch direkt mit dem String?
    Die einfache Zeile

    s2 / 1.0e16
    

    führt leider zu einer Fehlermeldung.

    Gruß,
    Klaus.



  • @Klaus: Lies doch gleich eine Zahl anstatt eines Strings ein 😕



  • Du meinst anstatt

    infile >> s1;
    infile >> s2;
    infile >> s3;
    

    eben nur

    infile >> energy;
    infile >> number;
    infile >> integrated_number;
    

    EDIT:
    Ne, geht nicht. 😞

    Gruß,
    Klaus.



  • Klaus82 schrieb:

    eben nur

    infile >> energy;
    infile >> number;
    infile >> integrated_number;
    

    EDIT:
    Ne, geht nicht. 😞

    Das kann nicht sein.
    Zeig den Fehler.


  • Mod

    Hacker schrieb:

    In welchem Standard bin ich denn?

    www.open-std.org/jtc1/sc22/wg21/docs/papers/2005/n1905.pdf

    In gar keinem. Wie schon auf der ersten Seite steht handelt es sich nur um einen Entwurf, noch dazu um einen uralten (wie man auch an der url erkennen kann).

    n3290 ist zwar auch nur ein Entwurf, bis auf die Formatierung (und Kleinigkeiten wie Vorwort etc.) aber identisch mit dem Standard.

    Der letzte frei zugängliche Entwurf ist n3242, der recht nah am endültigen Standard ist (die Änderungen seit 3242 sind in 3292 aufgefüht, man kann es sich also theoretisch selbst zusammensuchen).



  • Komisch - auf meiner Festplatte liegt n3337.pdf. :p



  • Kellerautomat schrieb:

    Komisch - auf meiner Festplatte liegt n3337.pdf. :p

    Hä? Dann hast du ein altes gedownloadet und umbenannt XD
    Oder weisste wo man das bekommt? Das von camper genannte PDF ist bei Wikipedia verlinkt.


  • Mod

    n3337 ist keine schlechte Wahl. Laut n3338 sind darin nur redaktionelle Änderungen (seit n3291) enthalten, also gewissermaßen der Text des Standards berichtigt um einige (offsichtliche) Schreibfehler.



  • Klaus82 schrieb:

    Hi,
    jetzt natürlich die Masterfrage:
    Wie kriege ich die Werte meiner Strings in wissenschaftlicher Notation in einen integer umgewandelt.

    Mit C++ geht das wohl am einfachsten, indem man die Bibliothek sstream verwendet.
    Beispiel:

    #include <sstream>
    #include <string>
    #include <iostream>
    
    using namespace std;
    
    int main()
    {
    double d;
    string s = "3345.5";
    stringstream sstr;
    sstr << s;
    sstr >> d;
    cout<<d;
    }
    

    Das von dir verwendete atol geht auch, ist aber c, nicht c++.

    Davon ab macht Hackers Frage aber Sinn, warum Du nicht gleich Integerwerte einliest.



  • camper schrieb:

    n3337 ist keine schlechte Wahl. Laut n3338 sind darin nur redaktionelle Änderungen (seit n3291) enthalten, also gewissermaßen der Text des Standards berichtigt um einige (offsichtliche) Schreibfehler.

    Wow, der neue ist viel besser geordnet als der alte, IMHO.

    Zurück zum Thema: Es ist völlig unnötig (Coding-Aufwand bspw.) Zuerst einen String einzulesen, welchen man dann als Ganzzahl/Fließkommazahl auswertet. Das macht bereits der globale operator>> für die entsprechenden Skalare.

    @redrew99: Boah, bei so 'ner Formatierung krieg ich son Hals! 😃


Anmelden zum Antworten