Aus eine Datei lesen



  • Guten Abend,
    nach mehreren Tagen daran gesessen und nach Überlegungen, wo ich alleine den Fehler nicht lösen könnte.
    Ich bin noch einen Anfänger
    Ich werde mich freuen, wenn mir jemand dabei helfen würde.
    Die Aufgabe lautet:

    Die Funktion fillrand füllt das als Parameter v definierte Feld mit n zufälligen Zahlen im Wertebe-reich [x,y]. Diese Funktion hat die folgende Signatur:
    void fillrand(std::vector<int>& v, unsigned n, unsigned x, unsigned y);
    Die Funktion fillfile füllt ein Feld mit Werten aus einer Datei filename. Die Funktion hat die Signatur:
    void fillfile(std::vector<int>& v, const std::string& filename);
    Ergänzen Sie Ihr Programm um weitere Funktion zur Benutzerinteraktion, zur Bestimmung der o.g. statistischen Werte und zur Steuerung des Programmablaufs. Der Benutzer wählt zuerst aus, ob die-ser mit zufälligen Werten arbeiten oder diese aus einer Datei auslesen möchte.
    Bei mir hakt es, wie ich aus eine txt Datei Zahlen lese.

    //main.cpp
    #include <iostream>
    #include<string>
    #include<fstream>
    #include<vector>
    #include "S.h"
    
    using namespace std;
    
    void printLine(string s)
    {
        cout << s << endl;
    }
    
    void printResult(vector<int>& numbers)
    {
        cout << endl;
        cout << "Das Minimum ist " << numbers[0] << endl;
        cout << "Das Maximum ist " << numbers[numbers.size() - 1] << endl;
        cout << "Der Median ist " << numbers[(numbers.size() / 2)] << endl;
    }
    
    int main()
    {
        while (true)
        {
            vector<int> numbers;
    
            int choice,n;
    
            printLine(" *** STATISTIKA ***");
            printLine(" [1] Arbeite mit zufaelligen Zahlen.");
            printLine(" [2] Lese Daten aus Datei ein.");
            printLine(" [0] Beenden.");
            cin >> choice;
            printLine("");
    
            if (choice == 1)
            {
                cout << " Geben Sie die Anzahl der zufaelligen Zahlen an: ";
                cin >> n;
    
                if (n <= 0)
                {
                    cout << "Keine Daten vorhanden." << endl << endl;
                    return 0;
                }
    
                int x = 1;
                int y = 100;
    
                fillrand(numbers, n, x, y);
    
            }
            else if (choice == 2)
            {
                    vector<string> filename;
    fillfile("Datei.txt", filename);
    int Datei=0;
    cout<<"Geben Sie eine Dateiname"<<endl;
    cin>>Datei;
    
    for (int i=0;i<filename.size();i++)
    {
        cout<<i+1<<" "<<filename[i]<<endl;
    }
    
    }
    
            }
            else if (choice == 0)
            {
                exit(0);
    
            }
    
            // Überprüfung ob sich Zahlen im vector befinden
            if (numbers.empty())
            {
                printLine("Keine Daten vorhanden.");
                continue;
            }
    
            // Sortieren
            selectionsort(numbers);
    
            printLine("Die sortierte Folge ist:");
    
            for (unsigned i = 0; i < numbers.size(); i++)
            {
                cout << numbers[i] << " ";
            }
    
            printResult(numbers);
        }
    }
    
    
    
    //S.h
    #include <iostream>
    #include<string>
    #include<fstream>
    #include<vector>
    #include "S.h"
    
    using namespace std;
    
    void printLine(string s)
    {
        cout << s << endl;
    }
    
    void printResult(vector<int>& numbers)
    {
        cout << endl;
        cout << "Das Minimum ist " << numbers[0] << endl;
        cout << "Das Maximum ist " << numbers[numbers.size() - 1] << endl;
        cout << "Der Median ist " << numbers[(numbers.size() / 2)] << endl;
    }
    
    int main()
    {
        while (true)
        {
            vector<int> numbers;
    
            int choice,n;
    
            printLine(" *** STATISTIKA ***");
            printLine(" [1] Arbeite mit zufaelligen Zahlen.");
            printLine(" [2] Lese Daten aus Datei ein.");
            printLine(" [0] Beenden.");
            cin >> choice;
            printLine("");
    
            if (choice == 1)
            {
                cout << " Geben Sie die Anzahl der zufaelligen Zahlen an: ";
                cin >> n;
    
                if (n <= 0)
                {
                    cout << "Keine Daten vorhanden." << endl << endl;
                    return 0;
                }
    
                int x = 1;
                int y = 100;
    
                fillrand(numbers, n, x, y);
    
            }
            else if (choice == 2)
            {
                    vector<string> filename;
    fillfile("Datei.txt", filename);
    int Datei=0;
    cout<<"Geben Sie eine Dateiname"<<endl;
    cin>>Datei;
    
    for (int i=0;i<filename.size();i++)
    {
        cout<<i+1<<" "<<filename[i]<<endl;
    }
    
    }
    
            }
            else if (choice == 0)
            {
                exit(0);
    
            }
    
            // Überprüfung ob sich Zahlen im vector befinden
            if (numbers.empty())
            {
                printLine("Keine Daten vorhanden.");
                continue;
            }
    
            // Sortieren
            selectionsort(numbers);
    
            printLine("Die sortierte Folge ist:");
    
            for (unsigned i = 0; i < numbers.size(); i++)
            {
                cout << numbers[i] << " ";
            }
    
            printResult(numbers);
        }
    }
    
    
    //S.cpp
    #include <iostream>
    #include <vector>
    #include <time.h>
    #include <fstream>
    #include "S.h"
    using namespace std;
    
    void selectionsort(vector<int>& v)
    {
        for(unsigned i=v.size();i>0;i--) // Iteration wenn noch unsortiert vorhanden
        {
            int temp = -1; // Index von Vergleichswert / Kleinster Wert
    
            for(unsigned j=0;j<i;j++) // Iteration aller unsortierten Werte im unsortierten Bereich
            {
                // Falls temp nicht gesetzt
                if(temp == -1)
                {
                    temp = j; // Setze temp auf aktuellen Index
                }
                // Wenn Vektor Wert von Temp > Aktueller Iterationswert
                else if (v[temp] >  v[j])
                {
                    temp = j; // Setze temp auf aktuellen index
                }
            }
            v.push_back(v[temp]); // Füge Element am Ende ein
            v.erase(v.begin() + temp); // Lösche Element aus unsortiertem Bereich
        }
    }
    
    void fillrand(vector<int>& v, unsigned amount, unsigned from, unsigned to)
    {
        srand(time(nullptr)); // Random seed
    
        for(unsigned i=0; i<amount; i++) // Nummern Generator
        {
            int random = rand() % to + from; // Zufallszahl zwischen x und y
    
            v.push_back(random); // In Vector speichern
        }
    }
    
    void fillfile (const string datei, vector<string> & filename)
    {
        ifstream inFile(datei);
        if(!inFile)
        {
            cerr<<"Datei kann nicht geoffnet werden"<<endl;
            exit(-1);
        }
        string word;
        while(!inFile.eof())
        {
            getline(inFile, word);
            if(word.size()>0)
            {
                filename.push_back(word);
            }
        }
    }
    
    
    


  • @dooni sagte in Aus eine Datei lesen:

    fillfile("Datei.txt", filename);
    int Datei=0;
    cout<<"Geben Sie eine Dateiname"<<endl;
    cin>>Datei;
    

    Ein Dateiname in eine int-Variable?

    @dooni sagte in Aus eine Datei lesen:

    Bei mir hakt es, wie ich aus eine txt Datei Zahlen lese.

    Wie von cin auch.



  • @dooni sagte in Aus eine Datei lesen:

    vector<string> filename;

    Ein vector von strings als Dateiname?



  • Die wenigsten werden sich so eine Menge Code durchlesen. Wo ist deine konkrete Frage?



  • @Swordfish Wie ich aus eine Datei Zahlen lese
    Beispiel

    Geben Sie den Dateinamen ein: example.txt
    Die sortierte Folge ist:
    1 2 3 4 5 6 7 8 9
    Das Minimum ist 1
    Das Maximum ist 9
    Der Median ist 5
    und das soll in so eine Form sein
    void fillfile(std::vector<int>& v, const std::string& filename);



  • @manni66
    ich weiß,das es falsch ist,
    deswegen frage ich ja auch
    wie man es lösen könnte



  • @dooni sagte in Aus eine Datei lesen:

    @manni66
    ich weiß,das es falsch ist,
    deswegen frage ich ja auch
    wie man es lösen könnte

    Ernsthaft?



  • @manni66
    tut mir Leid, habe es falsch ausgedrückt.
    Natürlich nicht.
    Für einen einen Anfänger, finde ich so eine Aufgabe voll schwer



  • @dooni sagte in Aus eine Datei lesen:

    @Swordfish Wie ich aus eine Datei Zahlen lese
    Beispiel

    Geben Sie den Dateinamen ein: example.txt
    Die sortierte Folge ist:
    1 2 3 4 5 6 7 8 9
    Das Minimum ist 1
    Das Maximum ist 9
    Der Median ist 5
    und das soll in so eine Form sein
    void fillfile(std::vector<int>& v, const std::string& filename);

    fstream aufmachen, inhalt lesen (mit zb getline aus der std::getline() oder fstream.getline() müsste beides gehen, du must wissen wie es gespeichert ist, da du mit getline eine komplette zeile bekommst. (kannst auch mit Buffernarbeiten, aber das musst du selbst ergoogeln).
    Deinen Stream musst du in eine c_str oder string (oder was auch immer) speichern und dann in ein int[] oder vector<int>(oder was auch immer kannst auch ne liste nehmen) konvertieren in dem du halt die Zahlen aus dem string nimmst (durch string.substr() o.ä.) die dann in ein int castest (ACHTUNG: (int)"1" oder '1'== 49 != 1 da ein char bzw string immer in den entsprechenden ASCII code gecastet wird) und dann hast du die Zahl.

    Also garnicht mal so viel anders als du es mit deinem vector filename gemacht hast.



  • @Darktutnix sagte in Aus eine Datei lesen:

    inhalt lesen (mit zb getline aus der std::getline() oder fstream.getline() müsste beides gehen, du must wissen wie es gespeichert ist, da du mit getline eine komplette zeile bekommst. (kannst auch mit Buffernarbeiten, aber das musst du selbst ergoogeln).
    Deinen Stream musst du in eine c_str oder string (oder was auch immer) speichern und dann in ein int[] oder vector<int>(oder was auch immer kannst auch ne liste nehmen) konvertieren in dem du halt die Zahlen aus dem string nimmst (durch string.substr() o.ä.) die dann in ein int castest (ACHTUNG: (int)"1" oder '1'== 49 != 1 da ein char bzw string immer in den entsprechenden ASCII code gecastet wird) und dann hast du die Zahl.

    W. T ... Heck!?

    #include <vector>
    #include <string>
    #include <fstream>
    #include <iterator>
    
    void fillfile(std::vector<int> &values, std::string const &filename)
    {
    	std::ifstream is{ filename };
    	values = std::vector<int>{ std::istream_iterator<int>{ is }, std::istream_iterator<int>{} };
    }
    

    Ohne istream_iterator<>:

    #include <vector>
    #include <string>
    #include <fstream>
    
    void fillfile(std::vector<int> &values, std::string const &filename)
    {
    	std::ifstream is{ filename };
    	for (int value{}; is >> value; values.push_back(value));
    }
    

    @dooni sagte in Aus eine Datei lesen:

    while(!inFile.eof())
    {
        getline(inFile, word);
        // ...
    

    Ist fast nie korrekt. Du machst

    • auf Dateiende prüfen
    • lesen (eventuell Dateiende oder Fehler)
    • verarbeiten (eventuell Müll)

    richtig rum:

    • lesen
    • auf Fehler prüfen
    • verarbeiten


  • Ich möchte noch was zur Namensgebung der Funktionen beitragen:

    Ein Funktion, die Daten aus einer Datei in einen Container liest, sollte auf keinen Fall "fillFile" heißen, weil das zu Deutsch "befülle Datei" heißt und genau das Gegenteil bedeutet.
    Benenne deine Funktionen so aussagekräftig wie möglich!

    Z.B. "readDataFromFile" und "writeDataToFile" oder "generateRandomNumbers"



  • @Swordfish sagte in Aus eine Datei lesen:

    @Darktutnix sagte in Aus eine Datei lesen:

    inhalt lesen (mit zb getline aus der std::getline() oder fstream.getline() müsste beides gehen, du must wissen wie es gespeichert ist, da du mit getline eine komplette zeile bekommst. (kannst auch mit Buffernarbeiten, aber das musst du selbst ergoogeln).
    Deinen Stream musst du in eine c_str oder string (oder was auch immer) speichern und dann in ein int[] oder vector<int>(oder was auch immer kannst auch ne liste nehmen) konvertieren in dem du halt die Zahlen aus dem string nimmst (durch string.substr() o.ä.) die dann in ein int castest (ACHTUNG: (int)"1" oder '1'== 49 != 1 da ein char bzw string immer in den entsprechenden ASCII code gecastet wird) und dann hast du die Zahl.

    W. T ... Heck!?

    #include <vector>
    #include <string>
    #include <fstream>
    #include <iterator>
    
    void fillfile(std::vector<int> &values, std::string const &filename)
    {
    	std::ifstream is{ filename };
    	values = std::vector<int>{ std::istream_iterator<int>{ is }, std::istream_iterator<int>{} };
    }
    

    in seinem eigenen code hat er die auch schon nicht verwendet xD ... glaube nicht das er die jetzt verwenden würde. (aber ja ist deutlich einfacher, aber benötigt auch mehr Wissen/verständnis über Vektoren.)

    Ohne istream_iterator<>:

    #include <vector>
    #include <string>
    #include <fstream>
    
    void fillfile(std::vector<int> &values, std::string const &filename)
    {
    	std::ifstream is{ filename };
    	for (int value{}; is >> value; values.push_back(value));
    }
    

    Die so freihe verwendung von for find ich gut 😃 danke für den Tipp. (dachte immer ist extrem unflexibel und man kann nur sowas wie for(int i = 0 ... i++) zb machen oder for(int i: liste<int>))
    Wird bei ìnt value{} ein temporäre neuer leerer int speicher auf dem Stack erzeugt, oder verstehe ich das falsch?
    Und >> funktioniert bei jedem Stream um die nicht interpretierbaren sachen fallen zu lassen (leerzeichen, buschstaben und alles was kein int sein könnte)?



  • @Darktutnix sagte in Aus eine Datei lesen:

    Wird bei ìnt value{} ein temporäre neuer leerer int speicher auf dem Stack erzeugt, oder verstehe ich das falsch?

    Es wird eine int-Variable namens "value" mit "automatic storage duration" erzeugt und mit 0 initialisiert. Wahrscheinlich wird diese nicht auf dem Stack liegen, sondern nur in einem Prozessor-Register vorliegen. Das hängt aber vom Zielsystem, dem Compiler und den Optimierungseinstellungen ab.

    Und >> funktioniert bei jedem Stream um die nicht interpretierbaren sachen fallen zu lassen (leerzeichen, buschstaben und alles was kein int sein könnte)?

    Whitespace wird übersprungen (kannst du mit skipws einstellen), bei anderen Zeichen geht der Stream in einen Fehlerstatus und die Schleife wird abgebrochen.



  • @wob sagte in Aus eine Datei lesen:

    @Darktutnix sagte in Aus eine Datei lesen:

    Wird bei ìnt value{} ein temporäre neuer leerer int speicher auf dem Stack erzeugt, oder verstehe ich das falsch?

    Es wird eine int-Variable namens "value" mit "automatic storage duration" erzeugt und mit 0 initialisiert. Wahrscheinlich wird diese nicht auf dem Stack liegen, sondern nur in einem Prozessor-Register vorliegen. Das hängt aber vom Zielsystem, dem Compiler und den Optimierungseinstellungen ab.

    also das gleiche wie int value = 0? oder gibts da einen unterschied?

    ^^ sorry fürs nerven (aber danke fürs erklären)



  • @Darktutnix sagte in Aus eine Datei lesen:

    also das gleiche wie int value = 0? oder gibts da einen unterschied?

    Kein Unterschied. Ich bevorzuge die = 0-Schreibweise.



  • @Darktutnix sagte in Aus eine Datei lesen:

    also das gleiche wie int value = 0? oder gibts da einen unterschied?

    Nee kein Unterschied. Ich finde allerdings

    int value = 0;
    

    lesbarer weil klar ist was passiert.

    In diesem Fall

    int value {};
    

    Kann man nur eine Annahme treffen, was in dem Fall getan wird.



  • @It0101 sagte in Aus eine Datei lesen:

    Kann man nur eine Annahme treffen, was in dem Fall getan wird.

    Nö, auch da braucht man nicht mit Annahmen zu arbeiten.



  • @wob sagte in Aus eine Datei lesen:

    @It0101 sagte in Aus eine Datei lesen:

    Kann man nur eine Annahme treffen, was in dem Fall getan wird.

    Nö, auch da braucht man nicht mit Annahmen zu arbeiten.

    Ich finds in dem Anwendungsfall besser wenn klar da steht, was getan wird, weil selbst ein Grundschulkind versteht was dort passiert.

    Wenns um Narrowing geht, ist die initializerlist mit {} natürlich besser.


Anmelden zum Antworten