Vektoren in csv Datei abspeichern in öffnen...



  • Genau so meinte ich es und es sollte so funktionieren.

    Jetzt wo ich deinen Code noch mal detaillierter angesehen habe: compiliert er fehlerfrei?
    Denn z.B. virtual berechnung(); innerhalb der Klassendefinition sollte einen Fehler ausgeben, da der Datentyp (z.B. void) fehlt.

    Welchen Compiler und/oder welche IDE verwendest du?
    Bei einer IDE solltest du auch recht einfach den Debugger benutzen können, um den Code zeilenweise zu verfolgen (und die Variablenwerte zu sehen).
    Ansonsten lass dir die Variablenwerte, z.B. zeit_.size(), mal per std::cout ausgeben.



  • @Th69 Er kompilierte jedes Mal fehlerfrei . In der CSV Datei standen jedoch die Werte mit denen ich die Vektoren deklariert habe, nämlich 0. Ich benutze CodeBlocks



  • Ich spezifiziere das Problem einmal:
    die main-Funktion habe ich so beibehalten, da die Berechnung funktioniert.

    datei.cpp:

    #include "datei.h"
    #include "cosinus.h"
    #include <iostream>
    #include <conio.h>
    #include <vector>
    #include <cstdlib> // Für system()
    #include <math.h>
    
    using namespace std;
    datei :: datei()
    {
        sinus_ = {0};
        zeit_ = {0};
        cosinus_ = {0};
    }
    datei :: erstellung()
    {
    //cout << "zeit[" << i << "] = " << zeit_[i] << ", sinus[" << i << "] = " << sinus_[i] << endl;
        string name;//Dateinamenertsellung
        
        do
        {
            _getch();
            system("cls");
            cout << "Dateinamen : ";
            cin >> name;
            if (name.size()>4 || name.substr(name.size() - 4) == ".csv")
            {
                cout << "Der Dateiname muss auf .csv enden\n";
            }
        }while (false);
    
            FILE *f; // Zeiger auf f auf die FILE_Struktur
            f = fopen(name.c_str(),"w"); // Öffnen der Datei mit dem Namen "name", "w" steht für write
            for (size_t i = 0; i < zeit_.size(); ++i)
            {
                fprintf(f, "%.2f, %.2f, %.2f\n", zeit_[i], sinus_[i]);
            }
            fclose(f);
                cout << "Datei wurde erfolgreich erstellt: " << name << endl;
                _getch();
    }
    

    Wenn ich hin dieser datei.cpp die Vektoren nicht deklariere bekomme ich eine Fehlermeldung. Jedoch stehen diese Werte in der CSV.

    cosinus.h:

    #ifndef COSINUS.H
    #define COSINUS.H
    #include <iostream>
    #include <vector>
    #include "sinus.h"
    
    using namespace std;
    
    class cosinus : public sinus
    {
    public:
        cosinus();
        virtual ~cosinus();
    
        virtual  void berechnung();
        virtual void ausgabe_parameter();
    
    protected:
        vector <double> cosinus_;
    };
    #endif // COSINUS
    
    

    im protected Bereich steht der Vektor damit datei.cpp darauf zugreifen kann.

    sinus.h:

    #ifndef SINUS.H
    #define SINUS.H
    #include "parameter.h"
    #include <iostream>
    #include <vector>
    
    
    using namespace std;
    
    class sinus : public parameter
    {
    public:
        sinus();
        virtual ~sinus();
    
        virtual void berechnung();
        virtual void ausgabe_parameter();
    
    protected:
     vector <double> sinus_;
     vector <double> zeit_;
    };
    #endif // SINUS
    
    

    Das gleiche habe ich bei der sinus.h gemacht.

    parameter.h:

    #ifndef PARAMETER.H
    #define PARAMETER.H
    #include <iostream>
    #include <vector>
    using namespace std;
    
    class parameter
    {
    public:
        parameter();
        virtual ~parameter();
    
        void umwandlung_str_double ();
        virtual void ausgabe_parameter(); 
    protected: 
        double amplitude;
        double frequenz;
        double abtastrate;
        double anzahl_funktionswerte;
    };
    
    #endif
    
    

    cosinus.cpp

    #include "cosinus.h"
    #include <vector>
    #include <math.h>
    #include <conio.h>
    
    
    using namespace std;
    
    cosinus :: cosinus()
    {
    
    }
    
    void cosinus :: berechnung()
    {
        vector <double> cosinus_(anzahl_funktionswerte);
        vector <double> zeit_(anzahl_funktionswerte);
        int i;
            for ( i = 0 ; i < anzahl_funktionswerte ; ++i)
    
            {
                zeit_[i] = i * abtastrate;
                cosinus_[i] = amplitude * cos(2 * M_PI * frequenz * zeit_[i]);
                cout << "zeit[" << i << "] = " << zeit_[i] << ", cosinus[" << i << "] = " << cosinus_[i] << endl;
            }
            getch();
    }
    
    void cosinus :: ausgabe_parameter()
    {
        cout << "Amplitude :  " << amplitude << "\n" << "Frequenz :  " << frequenz << "\n" << "Abtastrate :  " << abtastrate << "\n" << "Anzahl der Funktionswerte :  " << anzahl_funktionswerte << "\n";
    
    }
    
    cosinus :: ~cosinus()
    {
    
    }
    
    

    sinus.cpp:

    #include "sinus.h"
    #include <vector>
    #include <math.h>
    #include <conio.h>
    
    using namespace std;
    
    sinus :: sinus()
    {
    
    }
    
    void sinus :: berechnung()
    {
            vector <double> sinus_(anzahl_funktionswerte);
            vector <double> zeit_(anzahl_funktionswerte);
            int i;
            for ( i = 0 ; i < anzahl_funktionswerte ; ++i)
    
            {
                zeit_[i] = i * abtastrate;
                sinus_[i] = amplitude * sin(2 * M_PI * frequenz * zeit_[i]);
                cout << "zeit[" << i << "] = " << zeit_[i] << ", sinus[" << i << "] = " << sinus_[i] << endl;
    
            }
    
            getch();
    }
    
    void sinus :: ausgabe_parameter()
    {
        cout << "Amplitude :  " << amplitude << "\n" << "Frequenz :  " << frequenz << "\n" << "Abtastrate :  " << abtastrate << "\n" << "Anzahl der Funktionswerte :  " << anzahl_funktionswerte << "\n";
    
    }
    
    sinus :: ~sinus()
    {
    
    }
    
    

    parameter.cpp:

    #include "parameter.h"
    #include <iostream>
    #include <conio.h>
    #include <vector>
    #include <math.h>
    
    using namespace std;
    
    //double amplitude , frequenz , abtastrate , anzahl_funktionswerte;
    //string amplitude_str, frequenz_str , abtastrate_str , anzahl_funktionswerte_str;
    
    
    // Implementierung der Funktionen/Methoden
     parameter :: parameter()
    {
        amplitude = 0;
        frequenz = 0;
        abtastrate = 0;
        anzahl_funktionswerte = 0;
    }
    
    double ueberpruefung_umwandlung ( string wert_str)
    {
       if(wert_str.find_first_not_of("1234567890.")!=string::npos)
            {
                cout << "Falsche Eingabe\n";
                getch();
                return 0;
            }
        double wert_double = stod (wert_str);
        return wert_double;
    }
    
    void parameter :: umwandlung_str_double()//Umwandlung und Überprüfung des Strings, amplitude wird sofort in en protected bereich geschoben und ist für abgeleitete klassen verfügbar
    {
        string amplitude_str, frequenz_str, abtastrate_str, anzahl_funktionswerte_str;
    
         do
        {
            system("cls");
            cout << " Amplitude :  ";
            cin >>   amplitude_str;
            amplitude = ueberpruefung_umwandlung(amplitude_str);
    
        }while (amplitude == 0 );
    
    
    
        do
        {
            system("cls");
            cout << "Frequenz  :  ";
            cin >> frequenz_str;
            frequenz = ueberpruefung_umwandlung(frequenz_str);
    
        }while (frequenz == 0);
    
    
        do
        {
            system("cls");
            cout << "Abtastrate  :  ";
            cin >> abtastrate_str;
            abtastrate = ueberpruefung_umwandlung(abtastrate_str);
        }while (abtastrate == 0);
    
    
         do
        {
            system("cls");
            cout << "Anzahl Funktionswerte  :  ";
            cin >> anzahl_funktionswerte_str;
            anzahl_funktionswerte = ueberpruefung_umwandlung(anzahl_funktionswerte_str);
        }while (anzahl_funktionswerte == 0);
    
    
    
        // Die gesetzen Parameter noch einmal gesammelt ausgeben und vielleicht die Möglichkeit anbieten die Werte (gezielt) zu ändern
    }
    
    
    
    parameter :: ~parameter()
    {
    
    }
    
    

    Ich möchte gerne verstehen warum in dieser Datei (parameter.cpp) im Konstructor amplitude etc. auf 0 gesetzt werden muss. Ich weiß das dieses Problem so ähnlich ist wie das bei der Übertragung der Vektoren in die datei.cpp.

    Edit: Wenn ich die Vektoren nicht in der datei.cpp im Konstruktor deklariere ist die csv-Datei leer (0kB) . Ich glaube ich habe verstanden warum man die Vektoren in sinus.cpp und cosinus.cpp mit 0 initialisieren muss. Da ich am Anfang ein Objekt der Klasse datei erstelle muss ich wenn diese Klasse auf die Methode erstellung() zugreift die Vektoren in sinus.cpp und cosinus.cpp initialisieren weil damit die Vektoren im protected Bereich initialisiert werden. durch die vorherige Ausführung der Berechnung werden die neuen Werte für die Vektoren überschrieben und in der Methode erstellung() wird auf diese zugegriffen werden. Das habe ich auch so programmiert nur es sind immer noch 0kB in der CSV. So langsam habe ich den Verdacht das das an etwas anderem liegt was ich gar nicht auf dem Schirm haben.



  • Ich hab jetzt nicht den ganzen Verlauf gelesen aber ich würde mal ganz strikt die Frage stellen, warum sinus und cosinus eine "ist ein"-Beziehung haben. Das macht es auf keinen Fall einfacher oder gar übersichtlicher. Die ganzen leeren Destruktoren tragen zur Übersichtlichkeit auch kein Stück bei. Auf den ersten Blick würde ich behaupten, dass du ebenfalls alle Konstruktoren entfernen könntest, wenn du die Member direkt in der Klasse initialisieren würdest => exemplarisch für parameter:

    class parameter
    {
    public:
        void umwandlung_str_double ();
        virtual void ausgabe_parameter(); 
    protected: 
        double amplitude{0.}; // entweder explizit mit 0
        double frequenz{}; // oder einfach so
        double abtastrate{};
        double anzahl_funktionswerte{};
    };
    

    Ansonsten: Schreibe niemals - ja, wirklich niemals (es gibt in c++ wirklich nicht oft Empfehlungen die sich pauschalisieren lassen) - using namespace std; in den globalen scope eines Headers!

    Die Klasse Datei wirkt auf mich auch recht unnötig => std::ofstream

    Wenn du das ganze mal ein wenig reduziert hast (die Menge an Code ist kein Qualitätsmerkmal) und ggf. mal wirklich halbwegs modernes c++ nutzt (c++-11 oder aufwärts), dann schaue ich mir auch gerne mal dein eigentliches Problem an.



  • @DNKpp Ich bin Anfänger und ich studiere kein Informatik falls das jemand denkt ich habe keine Ahnung was eine "ist-ein" Beziehnung ist und was das mit der ünnötigen datei.h zutun haben soll. ich wollte lediglich wissen was falsch gelaufen ist bei der Übertragung der Vektoren in den protected Bereich.
    Ich glaube ich belasse es dabei und frage meinen Dozenten in der nächsten Woche.
    Danke für die Antworten .



  • @bittekeinbit sagte in Vektoren in csv Datei abspeichern in öffnen...:

    ich habe keine Ahnung was eine "ist-ein" Beziehung ist

    s. Vererbung (Programmierung):

    (4. Absatz) Abgeleitete Klasse und Basisklasse stehen typischerweise in einer „ist-ein“-Beziehung zueinander.

    Sieh dir das Beispiel mit der Basisklasse Fahrzeug an:

    • ein Kraftfahrzeug ist ein Fahrzeug
    • ein PKW ist ein Kraftfahrzeug
    • usw.

    Bei deiner Vererbungshierarchie hieße es:

    • ein sinus ist ein parameter
    • ein cosinus ist ein sinus
    • eine datei ist ein cosinus

    Und das ist nun mal falsch!

    Was man machen könnte, wäre eine (abstrakte) Basisklasse Function zu erstellen, und Sinus sowie Cosinus wären jeweils davon abgeleitet.
    Und die Dateiausgabe wäre eine (virtuelle) Funktion der Basisklasse.

    Üblicherweise verwendet man jedoch in C++ einfach die Überladung des ostream& operator<<(ostream& out, MyClass& my), um die Ausgabe mittels std::cout oder std::ofstream (in eine Datei) durchzuführen, s. das Beispiel in Überladen von Operatoren.



  • Guten Morgen @bittekeinbit,
    ich würde Deinem Dozenten die Frage stellen, wie er auf die Idee kommt, Dir mit so wenig Vorkenntnissen in C++ eine solche Aufgabe vorzulegen.
    Da scheint wohl so etwas wie ein Missverständnis vorzuliegen.
    War denn C++ vorgegeben? Oder wurde eine C++ Vorlesung vorausgesetzt?
    Mal schnell eine mathematische Aufgabe mit C++ ohne Vorkenntnisse in Bezug auf "Klasse" und "Objekte" zu bewältigen, halte ich für sinnlos.
    Kannst Du nicht sowas wie Python nutzen?



  • Mich würde in diesem Fall die genaue Aufgabenstellung interessieren.

    Wenn es "nur" darum geht, Funktionswerte in einer bestimmten Range zu erstellen, dann erscheint mir die Modellierung von Sinus und Cosinus als Klassen als zu viel.
    Man könnte einen Rückgabetypen für Wertepaare (x,y) definieren und einen Overload des << Operators für Ausgabe auf dem Bildschirm und in eine Datei.

    Ansonsten: In eine Datei schreiben macht man in C++ mit ofstream nicht mit FILE, was aus C stammt (https://en.cppreference.com/w/cpp/io/basic_ofstream) das klingt für C++ Neulinge erstmal etwas überraschend, aber Streams sind eine Abstraktion von etwas an das man Daten schreiben kann oder von was man Daten lesen kann. Daher kann man damit z.B.direkt Schreiben in eine Datei und schreiben auf die Bildschirmausgabe erschlagen.

    @bittekeinbit sagte in Vektoren in csv Datei abspeichern in öffnen...:

    Ich möchte gerne verstehen warum in dieser Datei (parameter.cpp) im Konstructor amplitude etc. auf 0 gesetzt werden muss. Ich weiß das dieses Problem so ähnlich ist wie das bei der Übertragung der Vektoren in die datei.cpp.

    Das ist so eine Eigenheit von C++ (und auch C). Wenn du irgendwo eine Variable wie z.B. double hast, dann gibt es irgendwo einen Speicherbereich für die Daten, aber der wird nicht auf einen bestimmten Wert gesetzt, sondern da steht halt, was an dem Speicherbereich so steht.
    In der Theorie kann das vlt ein minimaler Performancevorteil sein, in der Realität ist das vor allem eine Fehlerquelle.



  • @bittekeinbit

    KISS: Keep It Simple and Smart.

    Was spricht gegen folgende Strukturierung?

    #include <iostream>
    #include <vector>
    
    
    /* ------------------------------- Typedefs und Co. ------------------------------- */
    
    
    enum class Func2Calc
    {
        Sin,
        Cos,
    };
    
    typedef struct
    {
        // ToDo: Fill me
        Func2Calc mFunc;                ///< Gibt die math. Funktion an, welche wir berechnen wollen
        std::string mCSVOutName;        ///< Dateiname der CSV Datei
    } tInputParameters;
    
    
    /* ------------------------------- Funktionen ------------------------------- */
    
    
    bool ReadInputParameters(tInputParameters& P)
    {
        // ToDo: Fill me
        return true;
    }
    
    void CalculateXValues(std::vector<double>& XValues, const tInputParameters& P)
    {
        // ToDo: Fill me
    }
    
    
    void CalculateYValues(std::vector<double>& YValues, const tInputParameters& P, const std::vector<double>& XValues)
    {
        // ToDo: Fill me
    }
    
    
    bool OutputData(const std::string& FileName, std::vector<double>& XValues, std::vector<double>& YValues)
    {
        // ToDo: Fill me
        return true;
    }
    
    
    
    int main() 
    {
        tInputParameters Params;
        std::vector<double> XValues;
        std::vector<double> YValues;
    
        // Lese Berechnungsparameter ein
        if (!ReadInoutParameters(Params))
        {
            std::cout << "Erläuterung" << std::endl;
            return 0;
        }
        // Berechne X Werte
        CalculateXValues(XValues, Params);
        // Berechne Y Werte
        CalculateYValues(YValues, Params, XValues);
        // Gebe Daten aus
        if (!OutputData(Params.mCSVOutName, XValues, YValues))
        {
            std::cout << "Erläuterung" << std::endl;
            return 0;
        }
        return 0;
    }
    


  • Nochmals Danke für die ganzen Antworten. Ich habe es jetzt nach mehrmaligen Umändern hinbekommen. Ich hatte noch nicht ganz die Vererbungshierarchie verstanden.


Anmelden zum Antworten