Dynamische Datenstrukturen



  • Moin,

    ich sitze gerade vor einem Problem und mir fällt dazu keine schöne Lösung ein:

    Über Netzwerk bekomme ich Messwerte gesendet die ich verarbeiten will. Genauer gesagt wird jeder Messwertwert mit einem Faktor multipliziert und mit einem Offset addiert. Anschließend werden die Werte in eine Datenbank geschrieben.
    Am Anfang wird die Konfiguration der Messwerte übertragen. Anschließend werden nu noch die Messwerte gesendet:

    Beispiel:
    Konfiguration:
    3 BYTE, 2 short, 1 DWORD

    Das bedeutet in jedem Datenpaket 9 Byte enthalten. Statisch würde ich die Sache so regeln:

    union {
    	struct {
    		BYTE  a[3];
    		short b[2]
    		DWORD c[1]
    	};
    	BYTE buffer[9];
    };
    

    So könnte ich die Empfangenen Daten in den buffer schreiben und bequem über das Struct drauf zu greifen.

    Ich habe aber bis zu 50 Verbindungen und jede Verbindung kann mit einer anderen Konfiguration Daten senden. Das ganze soll also etwas dynamischer werden. Wenn ich aber mit new mein struct dynamisch fülle, hängt der Speicher nicht mehr zusammen. Also geht die die Sache mit dem union schief.

    Im Moment merke ich mir in einem Array die Konfiguration für jedes Feld. Wenn in einem Feld jetzt zum Beispiel ein signed short steht sieht der Code dafür so aus:

    if (conf[confIndex].size == 2) {
        if (conf[confIndex].signed) {
            signed short a;
            memcpy(&a, recBuffer+index, sizeof(signed short))
            double value = a * conf[confIndex].factor + conf[confIndex].offset;
        }
    }
    

    Das ganze funktioniert zwar, ist aber so richtig gefällt mir die Sache nicht. Es gibt doch bestimmt eine schöner Lösung für so ein Problem?

    Ich danke schon mal im Voraus für eure geistigen Ergüsse.

    Gruß
    Volker



  • hmm hab mir jetzt nicht genau durchgelesen was du da so gemacht hast ... aber warum arbeitest du nicht einfach mit void-Pointern?



  • Hm,

    ich lass mich ja gerne korrigieren, aber ich meine das funktioniert nicht. Die Pointer im struct kommen dann zwar im Speicher hintereinander, aber den Speicher den ich mir dann dynamisch hole muss nicht zwingend hintereinander kommen. Dann bringt mir die union nix mehr.



  • Upala ... sollte mir echt mal durchlesen was du geschrieben hast ... ^^ naja ... hab den code net so wirklich mir angeguckt ... 🤡



  • OK,

    ich hab die Nacht noch an dem Problem gegrübelt. Hier ist eine Lösung die ich gar nicht so schlecht finde:

    meine Datentyp Basisklasse

    class CDataType
    {
    public:
    	CDataType(int position, double factor, double offset);
    	~CDataType(void);
    	virtual double getValue(char *buffer) = 0;
    protected:
    	int m_position;
    	double m_factor;
    	double m_offset;
    };
    

    Für jeden Datentype baue ich jetzt eine eigene Klasse:

    class CDataTypeSBYTE : CDataType
    {
    public:
    	CDataTypeSBYTE(int position, double factor, double offset);
    	~CDataTypeSBYTE(void);
    	double getValue(char *buffer);
    };
    
    class CDataTypeSWORD : CDataType
    {
    public:
    	CDataTypeSWORD(int position, double factor, double offset);
    	~CDataTypeSWORD(void);
    	double getValue(char *buffer);
    };
    
    /*
     usw .....
    */
    

    Beispiel Implementierung der einer Klasse:

    // signed BYTE
    CDataTypeSBYTE::CDataTypeSBYTE(int position, double factor, double offset) : CDataType(position, factor, offset) { }
    
    CDataTypeSBYTE::~CDataTypeSBYTE(void) { }
    
    double CDataTypeSBYTE::getValue(char *buffer) {
    	signed char value = *(buffer + m_position);
    	return ((double)(value * m_factor)) + m_offset;
    }
    

    Um auf das Beispiel von oben zurück zu kommen:
    Konfiguration: 3 BYTE, 2 short, 1 DWORD

    // init
    CDataType *configDescription[6];
    int posIndex = 0;
    configDescription[0] = reinterpret_cast<CDataType*> (new CDataTypeUBYTE(posIndex, factor, offset));
    posIndex += sizeof(BYTE);
    
    configDescription[1] = reinterpret_cast<CDataType*> (new CDataTypeUBYTE(posIndex, factor, offset));
    posIndex += sizeof(BYTE);
    
    configDescription[2] = reinterpret_cast<CDataType*> (new CDataTypeUBYTE(posIndex, factor, offset));
    posIndex += sizeof(BYTE);
    
    configDescription[3] = reinterpret_cast<CDataType*> (new CDataTypeSWORD(posIndex, factor, offset));
    posIndex += sizeof(WORD);
    
    configDescription[4] = reinterpret_cast<CDataType*> (new CDataTypeSWORD(posIndex, factor, offset));
    posIndex += sizeof(WORD);
    
    configDescription[5] = reinterpret_cast<CDataType*> (new CDataTypeUDWORD(posIndex, factor, offset));
    posIndex += sizeof(DWORD);
    

    Später der Zugriff:

    for (int index=0; index <6; index++) {
    	value = configDescription[index]->getValue(recBuffer);
    }
    

    Wer Syntaxfehler findet kann sie behalten. Die findet auch mein Compiler ....

    Aber sonst ist konstruktive Kritik willkommen.

    Gruß
    Volker


Anmelden zum Antworten