Daten in .txt Datei sortieren und ausgeben



  • Hallo,

    Ich habe folgendes Problem zu lösen:

    Ich habe eine Datei mit dem folgenden Format:

    Die gesamte .txt - Datei ist in dutzende Zeitschritte (ramp point, time..) unterteilt.
    Für jeden Zeitschritt gibt es 2 Unterkategorien "Forces from Surface Loads" und "Forces from Body Loads" mit den entsprechenden Werten. Die Indizes sind für alle Zeitschritte an der gleichen Position. D.h. die Reihenfolge für beispielsweise "Forces from Surface Loads" ist immer: 1681,1689,1502,...

    -------------------------------------------------------------------------------
    SOLUTION AT RAMP POINT 1 TIME 0
    -------------------------------------------------------------------------------

    FORCES FROM SURFACE LOADS :
    Index Face Fx Fy Fz
    1681 14457 1.459187E+01 -3.793072E+03 0.000000E+00 Stream
    1689 15182 7.431102E+02 -7.433599E+02 0.000000E+00 Duct
    1502 14876 4.547474E-13 -2.273737E-13 0.000000E+00 Duct
    1204 14604 1.653944E+03 -1.960825E+04 0.000000E+00 Zone
    **** 23097 0.000000E+00 -2.436386E+04 0.000000E+00 Void
    ...

    FORCES FROM BODY LOADS :
    Domain Fx Fy Fz
    1 0.000000E+00 0.000000E+00 0.000000E+00
    2 0.000000E+00 0.000000E+00 0.000000E+00
    3 0.000000E+00 2.199441E-01 0.000000E+00
    4 0.000000E+00 4.059419E-02 0.000000E+00
    5 0.000000E+00 3.987269E-03 0.000000E+00
    ...

    -------------------------------------------------------------------------------
    SOLUTION AT RAMP POINT 2 TIME 30
    -------------------------------------------------------------------------------

    FORCES FROM SURFACE LOADS :
    Index Face Fx Fy Fz
    1681 14457 1.459187E+01 -3.793072E+03 0.000000E+00 Stream
    1689 15182 7.431102E+02 -7.433599E+02 0.000000E+00 Duct
    1502 14876 4.547474E-13 -2.273737E-13 0.000000E+00 Duct
    1204 14604 1.653944E+03 -1.960825E+04 0.000000E+00 Zone
    **** 23097 0.000000E+00 -2.436004E+04 0.000000E+00 Void
    ...

    FORCES FROM BODY LOADS :
    Domain Fx Fy Fz
    1 0.000000E+00 0.000000E+00 0.000000E+00
    2 0.000000E+00 0.000000E+00 0.000000E+00
    3 0.000000E+00 2.199441E-01 0.000000E+00
    4 0.000000E+00 4.059419E-02 0.000000E+00
    5 0.000000E+00 3.987269E-03 0.000000E+00
    ...

    -------------------------------------------------------------------------------
    SOLUTION AT RAMP POINT 3 TIME 60
    -------------------------------------------------------------------------------
    ...

    Jetzt wäre es nützlich, wenn die Daten nach der jeweiligen Index/Domain-nummer für alle Zeitschritte sortiert werden. D.h. dass für jeden Zeitschritt jeweils die gleiche Zeile zusammengefasst wird. Also zuerst alle 1. Zeilen, dann alle 2. usw.
    Am Ende sieht es dann so aus: (Mit Einfügen der Zeit in die 1. Spalte)

    FORCES FROM SURFACE LOADS:

    Time Index Face Fx Fy Fz
    00 1681 14457 1.459187E+01 -3.793072E+03 0.000000E+00 Stream
    30 1681 14457 1.459187E+01 -3.793072E+03 0.000000E+00 Stream
    60 1681 14457 ... ... ...

    Time Index Face Fx Fy Fz
    00 1689 15182 7.431102E+02 -7.433599E+02 0.000000E+00 Duct
    30 1689 15182 7.431102E+02 -7.433599E+02 0.000000E+00 Duct
    60 1689 15182 ... ... ...

    FORCES FROM BODY LOADS :

    Time Domain Fx Fy Fz
    00 1 0.000000E+00 0.000000E+00 0.000000E+00
    30 1 0.000000E+00 0.000000E+00 0.000000E+00
    60 1 ...

    Time Domain Fx Fy Fz
    00 2 0.000000E+00 0.000000E+00 0.000000E+00
    30 2 0.000000E+00 0.000000E+00 0.000000E+00
    60 2 ...

    Ist das mit C++ zu lösen? Habe es mit einem Excel Macro probiert, doch aufgrund der enormen Grösse der Datei (400MB) ist es ziemlich daneben gegangen.

    Wäre dir für eine Hilfe unglaublich dankbar 🙂

    Grüsse



  • Das geht auf jeden Fall die Frage ist nur wie. Ich würde wahrscheinlich das ganze, Solution weise, in ein XML packen und dann per XSLT die gewünschte Ausgabe erzeugen. Aber du kannst natürlich auch 'von Hand' parsen und ausgeben.



  • Ich würde das eher in Access importieren und dann gemütlich per SQL/Order By ausgeben lassen!



  • Hallo,

    Danke euch für die schnelle Antwort.

    Leider habe ich auf meinem Computer im Büro ausser den C++ compiler und Office ohne Access keine andere Software zur Verfügung, kann leider auch nichts runterladen.

    Ich habe eben schon ein C++ Program, das aber viel zu aufwändig ist und nicht ganz funktioniert 😞

    Habt ihr C++ Codes mit eingebautem Sortieralgorithmus? Habe bis jetzt keine entsprechenden Codes im Forum gefunden.

    Vielen Dank für eure Bemühungen!


  • Mod

    1. In der CRT gibt es qsort
    2. In C++ kannst du set und map verwenden um Datenzu gruppieren.



  • So wie Deine Datei aussieht, musst Du auch in Access mit VBA und mit SQL-Scripten bei SQL Datenbanken programmieren, also kannst Du auch gleich eine eigene Routine schreiben.
    Sortieren kannst Du erst, wenn die Daten auch zusammenpassen, ansonsten schmeisst Du ja Sachen zusammen, die nicht zusammengehören, denn wie ich Deine Datei verstanden habe, ist zB die 1681 in Surface Loads und in Body Loads vorhanden, eine einfache Sortierung über die Datei würde dies aber nicht auseinanderhalten können.
    Mein Vorschlag wäre mit einigen Schleifen die Datei auszulesen und in eine weitere Textdatei zu schreiben: als Ablaufbeschreibung

    while (not end of file)
    read Zeile in CString Zeile Objekt
    Zeile.Find ("TIME")
    wenn ja Zeit in tmpZeit
    Zeile.Find ("Surface Load"")
    wenn ja folgende Zeilen in Surface.txt schreiben mit tmpZeit vorweg
    break wenn Zeile.Find ("Body Loads")
    dann folgende Zeilen in Body.txt
    bis Zeile.Find ("TIME")
    end of while (nun beginnt der Turnus wider)

    In den neuen Dateien kannst Du dann leichter sortieren.
    Du kannst das natürlich auch in ein Array packen, dort dann sortieren und erst später in eine Datei schreiben, aber dann mußt Du Dich mit der Speicherverwaltung abärgern (unbekannte Größe bis 400 MB).

    Ich hoffe ich habe Dich und Dein Problem richtig verstanden und meine Ablaufbeschreibung ist verständlich und hilft vielleicht als Idee weiter.



  • Vielen Dank für die Hilfe.

    Werde mal versuchen, deine Hinweise in einen Code umzuwandeln.



  • Hallo zusammen,

    Lang ist's her, doch nun habe ich bei diesem Thema wieder Zeit gefunden weiterzuarbeiten 😉

    Habe folgenden Code:

    #include <vector>
    #include <string>
    #include <iostream>
    #include <algorithm>
    #include <string.h>
    #include <stdlib.h>
    #include <fstream>
    using namespace std; 
    
    class myItem {
    public:
    myItem(int T, int S, int I, const string& L): Time(T), Section(S), Id(I), Line(L) {}
    int Time, Section, Id;
    string Line;
    bool operator < (const myItem& o) const {
    if (Section != o.Section) return Section < o.Section;
    if (Id != o.Id) return Id < o.Id;
    return Time < o.Time;
    }
    }; 
    int main() {
    string line;
    string header1 = "FORCES FROM REACTIONS AT POINT TIES:"
    string header2 = "FORCES FROM REACTIONS AT RESTRAINED FACES :"
    vector <string> Sections, TableHeads;
    vector <myItem> AllData;
    int curTime, curSection, curId;
    // INPUT
    while (getline(cin,line).good()) {
    cerr << line << endl;
    char dummy;
    if (sscanf(line.c_str()," SOLUTION AT RAMP POINT %*d TIME %d",&curTime) == 1) { 
    // A new ramp point and time, restart sections
    curSection = -1;
    } else if (line.find(':') != string::npos) {
    // A new heading
    string tablehead;
    getline(cin,tablehead);
    curSection++;
    if (Sections.size() <= curSection) {
    Sections.push_back(line);
    TableHeads.push_back(tablehead);
    }
    } else if (line.find_first_not_of("- \r\n\t")==string::npos) {
    // ignore line
    } else {
    // data line
    int curId = line[0] == '*'? (~0u)>>1 : atoi(line.c_str());
    AllData.push_back(myItem(curTime,curSection,curId,line));
    }
    }
    // SORT
    sort(AllData.begin(), AllData.end());
    // OUTPUT
    std::ofstream output ("//gt//home//h113027//GT26//forces_moments//final1//output.txt"); 
    
    curSection = -1; curId = -1; 
    for (vector<myItem>::iterator i=AllData.begin(); i!= AllData.end(); i++) { 
    if (i->Section != curSection) { 
    curSection = i->Section; 
    curId = -1; 
    output << Sections[curSection].c_str() << std::endl; 
    } 
    if (i->Id != curId) { 
    curId = i->Id; 
    output << "\nTime " << TableHeads[curSection].c_str() << std::endl; 
    } 
    output << i->Time << std::endl << i->Line.c_str() << std::endl; 
    } 
    output.close(); 
    }
    

    Was der Code macht ist folgendes: Habe das gleiche input file wie früher:

    http://cid-daa1966be9348935.skydrive.live.com/embedicon.aspx/.Public

    Der Code sucht nun nach dem ":" was ja am Ende der Überschrift jedes Datenpakets steht (z.B. "Forces from...Loads:"),
    Danach liest es die darunterliegenden Daten, sortiert sie und gibt sie ins output file aus. Soweit so gut 😉

    Doch nun möchte ich nicht unbedingt alle Daten sortieren und ausgeben, sondern nur beispielsweise "Forces from Reactions at Point Ties:"
    Dazu habe ich ein String mit dem Titel definiert. Jetzt brauche ich noch den entsprechenden Befehl in der Zeile 35.
    Kenn mich leider nicht so gut aus, aber denke mit einer Bool-Abfrage - wenn der vordefinierte Titel gelesen wurde, dann Daten lesen, sonst überspringen - kann man das lösen.

    Bin ich da komplett falsch oder gibt es eine bessere Möglichkeit?

    Vielen Dank schon mal für euer Feedback... 😉

    Grüsse


Anmelden zum Antworten