Daten kombinieren bei Verwendung von Pragma Pack und Struct?



  • Ich lese eine Datendatei mit verschiedenen Datensätzen mittels pragma pack und struct in C++ ein, konvertiere die verschiedenen Datentypen zu Dezimal wenn nötig und gebe die gesamte Datendatei mit allen verschiedenen Datensätzen als Klartext-Textdatei aus. Das klappt im Wesentlichen ganz prima, ich scheitere aber vollkommen bei dem Versuch einzelne Daten vor der Ausgabe zu kombinieren.

    Als vereinfachtes Beispiel:

    Datenpaket 1 enthält als Text einen Städtenamen, gefolgt von Einwohnerzahl und Größe. Enthalten sind zahlreiche Datenreihen bzw. Städte.

    0 Berlin;111;111
    1 Düsseldorf;111;2222
    2 Wien;1111;1234
    3 Dortmund;333;4444
    4 ...

    struct TStadt
    {
    	char				mName[64];		 
    	unsigned char		mData1[4];			  
    	unsigned char		mData2[4];			
    };
    

    Datenpaket 2 kann z.B. verschiedene Straßendaten enthalten und einen Verweis auf die Stadt, in Form der Datenreihennummer aus Datenpaket 1.

    0 3;1;3568:458
    1 3;4;4586;3
    2 2;75;474;1
    3 ...

    struct TStrassen
    {
    	short				mStaedteIndex;		  // Stadt 
    	short				mStrasseIndex;       
    	int					mSumTSData;           
    	short				mNbTSData;	          
     };
    

    Ich möchte vor der Datenausgabe den Datensatz des 2ten Paketes um den tatsächlichen Stadtnamen ergänzen, scheitere aber jedes mal kläglich. Geht das überhaupt bei meiner Einlesemethode?

    Ziel:

    0 Dortmund;1;3568:458
    1 Dortmund;4;4586;3
    2 Wien;75;474;1
    3 ...

    Meine Datendateien sind riesig und auch mein komplettes Script ist recht lang, daher kann ich nicht alles posten oder hochladen. Ich möchte am Ende auch einige Verknüpfungen mehr in der Datei machen als nur die eine da oben.

    Vielleicht sollte ich noch einen Teil des scripts posten mit dem ich die Einlese und später dann die Textausgabe vornehme:

    // Einlesen 1. Teil - Städte (786432DEZ / C0000HEX Datensatzlänge)
    void readStadt(FILE* pFile, TMapDAT& pMap)
    {
    	int	lNbStaedte = pMap.mHeader.mLumpes[cStadtLump].mLength / sizeof(TStadt);
    
    	// Zum Datenbeginn springen 
    	fseek(pFile, pMap.mHeader.mLumpes[cStadtLump].mOffset, SEEK_SET);
    
    	for
    		(int lStadtCounter = 0; lStadtCounter < lNbStaedte; ++lStadtCounter)
    	{
    		TStadt lStadt;
    
    		fread(&lStadt, 1, sizeof(TStadt), pFile);
    
    		pMap.mStaedte.push_back(lStadt);
    	}
    }
    

    P.S.: Hobbybasteler am Werk... 🤡



  • Dein Einlesen ist C und nicht C++
    http://www.cplusplus.com/reference/iostream/fstream/



  • wx++ schrieb:

    Dein Einlesen ist C und nicht C++
    http://www.cplusplus.com/reference/iostream/fstream/

    Ich glaube ich bin zu dumm dafür. Was ich auch versuche um die Daten zu kombinieren endet in Fehlern und crashes. Ich hab mir extra erst mal eine kleine Datendtei gebaut und die ganzen scripts angepasst und verkleinert um mehr Übersicht zu haben und selbst damit komm ich nicht weiter. Aber ganz nebenbei, ich have CPP und h-Dateien erstellt, also ist das doch C++ und nicht C - oder? 😞



  • MS-Office-User schrieb:

    Ich lese eine Datendatei mit verschiedenen Datensätzen mittels pragma pack und struct in C++ ein, ...

    0 Berlin;111;111
    1 Düsseldorf;111;2222
    2 Wien;1111;1234
    3 Dortmund;333;4444
    4 ...

    struct TStadt
    {
    	char				mName[64];		 
    	unsigned char		mData1[4];			  
    	unsigned char		mData2[4];			
    };
    

    ...

    Als Erstes fällt mir auf, dass in Deinem Beispiel die Daten unterschiedliche Länge haben (Städtenamen) - berücksichtigt Deine Einleseroutine das?
    Als Zweites, dass Du nicht die (praktischen, sicheren, ...) C++-Mittel verwendest:
    string, ifstream, operator>>(), vector, map, ...

    und schließlich, dass ich keine Fehlerbeschreibung in Deinem Text finde (du "scheiterst"?!?, Was meinst Du mit "Verknüpfung"?

    Ich skizziere mal kurz, wie ich so ein Einlesen normalerweise löse:

    #include <fstream>
    using std::ifstream;
    
    #include <string>
    using std::string;
    
    #include <vector>
    using std::vector;
    
    #include <iostream>
    using std::cout;
    
    struct Stadt
    {
        string name;         
        long data1, data2; // sind doch nur Zahlen, oder?
    };
    
    int main() {
       ifstream in("MeineDatei.txt");
       vector<Stadt> staedte;
       while(in) {
          Stadt stadt;
          char trenner;
          in >> stadt.name;
          in >> trenner; // Semikolon überspringen
          in >> stadt.data1; 
          in >> trenner; // Semikolon überspringen
          in >> stadt.data2; 
          in >> trenner; // Semikolon überspringen
          staedte.push_back(stadt);
       }
       // Ab hier kann ich auf die n. Stadt mittels staedte[n-1] zugreifen ...
    
       // Hier z.B. einfach Ausgabe auf die Konsole
       for(size_t i=0; i<staedte.size(); ++i) 
          cout << i << ". Stadt: name = " << staedte[i].name << ", data1 = " << staedte[i].data1  << ", data2 = " << staedte[i].data2 << "\n";
       return 0;
    };
    

    Da kann man natürlich noch eine Menge verbessern (operator>>(Stadt&) , zeilenweise einlesen, Trennerhandling besser, operator<<() passend dazu, Fehlertoleranz (gerade bei großen Files wichtig), Ausgabe via iterator, ....), aber schon mit der einfachen Variante bekommst Du ein recht gute Fehlerbehandlung (z.B. String-Längen), einen Typkonvertierung, leichte Erweiterbarkeit, Übersichtlichkeit... geschenkt.

    Kann es sein, dass Du ein "Datenmodell in C++" abzubilden versuchst? ("Index", "Verknüpfung", ... weisen für mich darauf hin) Dann solltest Du Dir unbedingt die StdLib-Container intensiv ansehen ("draufschaffen") und in 99,9% der Fälle auch verwenden!

    Gruß,

    Simon2.


Anmelden zum Antworten