Datei einlesen klappt nicht wie beabsichtigt



  • Hallo zusammen, ich will eine simple Textdatei einlesen. Das Programm soll nur Zahlen einlesen, d.h. alle alphanumerischen Zeichen überspringen, und diese Zahlen dann in einem Vektor ablegen.

    Inhalt von mydata.txt:
    2 2 2

    Die Ausgabe meines Programms lautet:
    End of file reached
    2 2
    Es vergisst aber die letzte 2, warum?

    Wenn ich den Inhalt von mydata.txt so abändere:
    2 2 2f 5

    Dann gibt mein Programm das hier aus:
    2 2 2
    f wird übersprungen aber die 5 vergessen, scheinbar wird immer das letzte Zeichen vergessen.

    Wie muss mein Programm abgeändert werden damit es richtig arbeitet?

    #include <iostream>
    #include <fstream>
    #include <vector>
    using namespace std;
    
    void fill_vector(istream& ist, vector<int>& v)
    {
        for(int n; ist>>n;) {
            if(ist.good())
                v.push_back(n);
            if(ist.eof()) {
                cout << "End of file reached" << endl;
                return;
            }
            if(ist.fail()) {    // we found something that wasn't an integer
                ist.clear();    // clear state to read character again
                for(char ch; ist>>ch && !isdigit(ch);)  // throw away non-digits
                    ;
                ist.unget();    // put the digit back, so that we can read the number
            }
        }
    }
    
    int main()
    {
        vector<int> v;
        ifstream ist {"mydata.txt"};
        if(!ist.good())
            cerr << "Cannot open File" << '\n';
        fill_vector(ist, v);
        for(auto i : v)
            cout << i;
    }
    


  • @zipehpa sagte in Datei einlesen klappt nicht wie beabsichtigt:

    for(int n; ist>>n;) 
    

    Was macht das? Wozu soll dann

    if(ist.good())
    
    if(ist.eof())
    
    if(ist.fail())
    

    gut sein?


  • Mod

    Lass das selbstgemachte Prüfen weg! Wo hast du das überhaupt her? Der Leseoperator macht doch schon selber alles richtig:

    for(int n; ist>>n;)
        v.push_back(n);
    

    Das sollte schon reichen.



  • @SeppJ

    @zipehpa sagte in Datei einlesen klappt nicht wie beabsichtigt:

    Das Programm soll nur Zahlen einlesen, d.h. alle alphanumerischen Zeichen überspringen

    Das bedeutet für mich schon zwischen EOF und conversion failure unterscheiden.

    bool valid_input;
    for (int n; (valid_input = !(ist >> n).fail()) || !ist.eof();) {  // ach, das geht sicher eloganter
    	if (valid_input)
    		v.push_back(n);
    	else {
    		ist.clear();
    		ist.get();
    	}
    }
    

    Ungetestet hingerotzt. Trotzdem Kkeine Gewärleistung.



  • Hier mal mein Lösungsvorschlag:

    #include <iostream>
    #include <string>
    #include <vector>
    #include <fstream>
    #include <sstream>
    
    void fill_vector(std::istream& ist, std::vector<int>& v) {
    	std::stringstream ss;
    	ss << ist.rdbuf();
    	for (const auto &ch : ss.str()) {
    		if (ch >= '0' && ch <= '9')
    			v.push_back(ch - '0');
    	}
    }
    
    int main() {
    	std::vector<int> v;
    	std::ifstream ist("test.txt");
    	if (!ist.good())
    		std::cerr << "Cannot open File" << '\n';
    
    	fill_vector(ist, v);
    	for (const auto &number : v) {
    		std::cout << number << '/';
    	}
    }
    

  • Mod

    Man darf auch '0' und '9' schreiben. Dann weiß jeder sofort, was gemeint ist; man kann nichts falsch machen; und es ist zumal noch viel portabler.



  • @SeppJ ja, vollkommen richtig. Habs geändert. Weiß auch nicht was mich geritten hat^^



  • @Zhavok std::isdigit() verdammt nochmal. Wenn schon.



  • OT, aber... weils in der Sig steht: Labskaus ist Rindfleisch und rote Beete. 😉



  • @ks7776 Wie gesagt, der Koch ...


Log in to reply