Messwerte in Klasse aufnehmen und als Vektor speichern



  • Ich glaube, du hast immer noch nicht so ganz verstanden, wozu der vector da ist... aber der Reihe nach.
    Wenn du den Zeitpunkt der Messung benötigst musst du dafür ein Datenelement in deiner Messstruktur anlegen, z.B. als time_t.
    std::vector ist ein dynamisches Array. In deinem Beispiel legst du einen vektor mit 10 Elementen an und weist der Temperatur des 1. Elements den Wert 15.0 zu.
    Die Erfassung und Speicherung der Messdaten könnte so aussehen:

    void erfasse_daten()
    {
       Messdaten data;
    
       // Messdaten wie auch immer woher auch immer erfassen
       ...
    
       // Zeitstempel eintragen
       data.Timestamp = time( 0 );
    
       // Daten in vektor eintragen (wo auch immer der gerade herkommt)
       DataVector.push_back( data );
    }
    

    vector::push_back() fügt ein neues Element am Ende des Vektors ein, du brauchst dich dabei um keinerlei Speicherverwaltung/Reservierung zu kümmern.



  • also brauch ich keine Größe angeben? Das ist prima, so bleib ich flexibel. Die Anzahl der Messwerte soll ja auch per Eingabe des Benutzers festgelegt werden, ist also unbekannt.

    hab die Funktion mal geschrieben und den Messwert mal als random genommen:

    vector<Messdaten>batch1;
    
    void ErfasseMessdaten()
    {
       Messdaten data;
       data.temperatur = rand();
       data.time_t = time(0);
       batch1.push_back(data);
    }
    

    so müsste es gehen?
    Das heisst ich muss nur noch die Funktion aufrufen und dann fült er den Vektor?



  • Probier´s doch einfach aus :p



  • Wenn du die Anzahl vorher kennst, lohnt sich ein batch1.reserve(bekannteGroesse), da so unnötiges Kopieren verhindert wird.

    Denn wenn der Speicherplatz für den Vektor nicht mehr ausreicht, wird er an eine Stelle kopiert, wo es genug Platz gibt (+ Platz für ein paar mehr). Je nach Größe des Inhalts kann das in die Performance gehen.



  • Die Größe ist vorher bekannt, da abgefragt wird wie viele Messwerte aufgenommen werden sollen.



  • am besten ich erkläre mal worum es genau geht. Vielleicht geh ich da ja ganz falsch ran und bin auf dem falschen Weg.
    Ich habe verschiedene Geräte die mittels RS232 verschiedene Messwerte liefern. Das funktioniert auch und ich kann diese auch zB auf einer Label Komponente anzeigen lassen. Der entsrechende Wert kommt zB alle 1 Sekunde (das kann ich einstellen in meinem Programm). Da es sich um mehrere Messwerte handelt wollte ich alle in eine Klasse oder Struktur packen. Dort wird aber immer nur ein Wert gespeichert. Da ich aber die Daten weiterverwenden will und auch in eine Datei speichern möchte sowie grafisch ausgeben möchte, gab man mir den Tipp Vektoren zu verwenden. Das leuchtet auch ein, da diese ja im Gegensatz zu Arrays auf keine feste Größe angewiesen sind und nützliche Funktionen mitbringen. Zu jeder Messreihe soll auch die Zeit der einzelnen Messwerte mitgespeichert werden, dass ich dann zB in einem Textfile, den ich speichere, zu jeden Messwert den Zeitwert hab. Die Anzahl der Messwerte sowie der zeitliche Abstand zwischen den einzelnen Messwerten wird über Editfelder abgefragt.
    Am besten ich fang noch mal ganz einfach an und nehme erst einmal 2 Messwerte, zB Temperatur und Füllstand.
    Für die Messwerte nehm ich erst mal 2 Labels die zufällige Messwerte alle 1sek. bekommen



  • Irgendwie habe ich den Eindruck, du liest dir die Antworten zu deinen Fragen nicht richtig durch (oder verstehst sie nicht. Oder beides).
    Dein Problem ist seit deinem ersten Beitrag bekannt und im zweiten Beitrag wurde bereits die Lösung präsentiert. Zwischendurch erfolgten ein paar Ausflüge in Konstruktordetails und die Vorzüge von Initialisierungslisten, und nach 3 Seiten Diskussion stellst du dein Problem erneut vor.
    Was genau erwartest du? Alles, aber auch wirklich alles, was du zur Lösung deines Problems benötigst wurde im Verlauf des Threads mindestens ein Mal erwähnt.
    Du hast den Thread am 8. Januar gestartet, am 8. Januar wurde dir der Tipp gegeben, std::vector zu benutzen. Am 18. Januar, das sind 10 Tage später, fragst du nach, ob du std::vector so richtig benutzt.
    Du musst schon Eigeninitiative zeigen, z.B. ein kleines Testprogramm schreiben, um sich mit den rudimentären std::vector Operationen vertraut zu machen. Zugegeben, der Einstieg in die STL ist für Anfänger vielleicht nicht ganz einfach, aber dann hättest du konkrete Fragen zu konkreten Problemen stellen können, aber so wie ich das jetzt sehe bist du genauso weit wie vor 10 Tagen...



  • ja ok, da hast du recht. Ich bin wirklich nicht viel weiter. Ich versuch die Fragen konkreter zu stellen.
    Sollte ich die Funktion ErfasseMessdaten mit in die struct schreiben oder in das Programm? (ich glaub das muss dann eine Klasse sein)

    data.Timestamp = time( 0 );
    

    Timestamp soll dann ein Element des Structs sein? welcher Datentyp ist hier sinnvoll? time() ist wohl eine Fkt aus der STL und gibt soweit ich herausbekommen hab die Uhrzeit in Sekunden an? Ich kannte nur Time(void). Da wird die aktuelle Uhrzeit im Uhrzeitformat angegeben. Ist das hier nicht besser?

    Wie greife ich denn, nachdem ich die Funktion aufgerufen habe, auf die Elemente zB Temperaturen und den einzelnen Zeiten zu, um sie zum Beispiel in einem Memo auszugeben?

    hab mal alles in eine Datei geschrieben um es übersichtlicher zu halten:

    #include <vcl.h>
    #pragma hdrstop
    
    #include "Unit1.h"
    #include <vector>
    using namespace std;
    //---------------------------------------------------------------------------
    #pragma package(smart_init)
    #pragma resource "*.dfm"
    TForm1 *Form1;
    
    class Messdaten {
       private:
          double temperatur;
          double phwert;
          time_t timestamp;
       public:
          Messdaten() : temperatur(0.0),
                        phwert(0.0) {}
          void Set_Messdaten(double temperatur,
                             double phWert,
                             time_t timestamp) {
             this->temperatur=temperatur;
             this->phwert = phwert;
             this->timestamp = timestamp;
             }
    };
    vector<Messdaten> batch;
    
    void ErfasseMessdaten() {
       Messdaten data;
    
       //Erfassg der Messdaten:
       data.Set_Messdaten(rand(),rand(),time(0));
    
       batch.push_back(data);
       }
    
    //---------------------------------------------------------------------------
    __fastcall TForm1::TForm1(TComponent* Owner)
       : TForm(Owner)
    {
    
    }
    


  • soweit klappt alles. Hab jetzt noch über einen Timer und eine Abbruchbedingung den Code implementiert, der den Vektor füllt indem die Funktion ausgeführt wird.

    void __fastcall TForm1::Timer1Timer(TObject *Sender)
    {
        static int counter = 0;
        Label1->Caption = counter;
        counter++;
        if(counter <= StrToIntDef(E_Messreihen->Text,100)) {
           ErfasseMessdaten();
           }
        else {
           Timer1->Enabled = false;
           counter = 0;
           }
    }
    

    Die Anzahl und das Intervall lässt sich einstellen. EIne Anzeige der Größe des Vektors über batch.size() bestätigt, dass der Vektor gefüllt wird.
    Nun muss ich nur noch auf die Elemente zugreifen, dass ich sie auch ausgeben und in eine Datei speichern kann. Das klappt bei mir noch nicht. Normalerweise greift man ja auf einen Vektor über den Indexoperator [] zu. Nur muss ich ja auch an die Elemente der Klasse ran. Wie geh ich da vor?



  • Hallo,

    Normalerweise greift man ja auf einen Vektor über den Indexoperator [] zu. Nur muss ich ja auch an die Elemente der Klasse ran. Wie geh ich da vor?

    Das weisst du doch schon, siehe oben:

    rudpower schrieb:

    soweit ich weiss muss ich den vector so anlegen:

    vector<Messdaten>batch(10);
    // Zugriff:
    batch[0].temperatur = 15.0;
    

    MfG,

    Probe-Nutzer



  • vielen Dank. Es funktioniert. Blöd ist hier nur, das die Größe dadurch vorgegeben ist.



  • Ich würde gern die Größe des Vektors dynamisch halten. Es gibt wohl auch die Möglichkeit, dass man die Klammern leer lässt, also

    vector<Messdaten> batch();
    

    wie ich gelesen hab, nur gibt das bei mir Fehlermeldungen. Ich nehme mal an, dass ich dann auch die reserve-Fkt. nicht verwenden darf.

    Prinzipiell ist bekannt wie groß der Vektor werden soll. Nur halt erst in der Ausführungszeit, nachdem der Benutzer die Anzahl der Messwerte in ein Editfeld eingegeben hat. Der Vektor muss aber vorher definiert werden, da er ja in der Funktion "ErfasseMessdaten" verwendet wird. Wie kann ich das Problem lösen? Ich nehme mal an, dass ein Zeiger auf das Editfeld die Lösung sein könnte. Nur bei der Umsetzung haperts.

    vector<Messdaten> batch(SIZE);
    
    void ErfasseMessdaten(int anzahl)
    {
       Messdaten data;
    
       //Erfassg der Messdaten:
       data.Set_Data(rand(), rand(), Time(), Date());
    
       batch.reserve(anzahl);
       batch.push_back(data);
    }
    


  • Das gibt dir nur einen Fehler, weil der Compiler da nicht recht weiss, was er machen soll. Sieh dir z.B mal das Beispiel hier an:

    int foo ();
    ..
    int foo ()
    {
    //mache irgendwas
    }
    

    Klar was das ist, oder?
    Jetzt möchtest du aber eine Funktion haben, die batch heisst und einen std::vector zurückgibt, also:

    vector<Messdaten> batch();
    ..
    vector<Messdaten> batch()
    {
    //mache irgendwas
    }
    

    Moment. Das erste sieht doch verdammt nach dem aus, was du da hast.. Es ist also eine Funktionsdeklaration!

    Wenn du einen leeren vector haben willst, dann lass die Klammern einfach weg:

    vector<Messdaten> batch; //schwup und es funktioniert.
    
    void ErfasseMessdaten(int anzahl)
    {
       Messdaten data;
    
       //Erfassg der Messdaten:
       data.Set_Data(rand(), rand(), Time(), Date());
    
       batch.reserve(anzahl);
       batch.push_back(data);
    }
    


  • ja supi, vielen Dank.


Anmelden zum Antworten