Parameter aus .cpp und .h auslesen und Formatiert ausgeben



  • Hallo zusammen,
    ich wurde mit einem Projekt vertraut, dass mich grade noch ein bischen überfordert. Hab leider auch nichts passendes gefunden. Und meine ehemals guten C++ Kenntnisse sind sehr am schwinden.

    Darum geht es: In einer .cpp und einer .h-Datei sind zahlreiche Parameter enthalten, die herauszufinden und sauber zu Formatieren sind, hier ein Beispiel.

    #define     PWM1_MIN      								8,B_EEPROM_2BYTE_U/*1,mA,#PWM#ESX#STROM*/
    #define     PWM1_MAX      								10,B_EEPROM_2BYTE_U/*1,mA,#PWM#ESX#STROM*/
    #define RAMPE_P1_AUF        						   	12,B_EEPROM_2BYTE_U/*0.1,s,#PWM#ESX#RAMPE*/
    #define RAMPE_P1_AB     								14,B_EEPROM_2BYTE_U/*0.1,s,#PWM#ESX#RAMPE*/
    #define     PWM2_MIN      								16,B_EEPROM_2BYTE_U/*1,mA,#PWM#ESX#STROM*/
    

    Das soll etwa so Formatiert werden.

    Adresse Bezeichnung   Faktor  Einheit
    8       PWM1_MIN      1       mA
    10      PWM1_MAX      1       mA
    12      RAMPE_P1_AUF  0.1     s
    14      RAMPE_P1_AB   0.1     s
    16      PWM2_MIN      1       mA
    

    Die Formatierung der .cpp bzw. der .h-Datei ist nicht Einheitlich, sprich nach #define sind immer unterschiedlich viele Leerzeichen, auch die Adresse ist nicht immer eine gerade Zahl z.B. 18 nächste 19 nächste 20. Dazu kommt noch, dass der Faktor und die Einheit aus dem Kommentar herauszuangeln sind.

    Ich möchte natürlich keine fertige Lösung präsentiert bekommen, sonder nur wie man da vorgehen könnte, z.B. erst mal alle Leerzeichen entfernen um somit die Bezeichnung zu finden...

    Mir fehlt noch vollkommen ein Konzept, bin daher über jeden Vorschlag dankbar

    2. Schritt, der ist aber noch nicht so wichtig, zu jeder Bezeichnung gehört noch ein bestimmter Wert, der sich in der anderen Datei versteckt z.B.

    s32_error |= ba_llt_writeTempEEPROM(PWM1_MAX, 800);
    s32_error |= ba_llt_writeTempEEPROM(PWM2_MIN, 200);
    s32_error |= ba_llt_writeTempEEPROM(PWM2_MAX, 800);
    s32_error |= ba_llt_writeTempEEPROM(PWM3_MIN, 200);
    

    hier hätte PWM1_MAX den Wert 800, der dann auch noch mit in die formatierte Liste mitaufgenommen werden soll. Aber wie gesagt, brauch erst mal ein Konzept für mein erstes Problem

    Vielen Dank Leute
    Michael


  • Mod

    1. Das hat mit C++ erstmal herzlich wenig zu tun. Das ist eher etwas für awk. Falls es sehr komplizierte Formatierung in der Datei sein sollte eventuell auch Python. Aber mit awk sollte das nach dem was du hier zeigst nur ein Programm von ein paar Zeilen sein. Ein Zweizeiler, falls du dich mit Regex auskennst.

    2. Noch eine Kombination mit grep um den Wert zu suchen und dann nochmals awk auf die Daten hübsch zu formatieren.



  • Gut, Danke, da werde ich mich gleich mal einlesen. Ich bekam aber die Bedingung, dass die Formatierung mit einem Tastendruck unter Code::Blocks ablaufen soll. Am besten soll daraus ne .exe erstellt werden, die die Formatierung durchführt und beispielsweise eine .csv ausgibt.

    Hat noch jemand einen Vorschlag?



  • Hallo Michael,

    SeppJ hat schon Recht, C++ ist für diese Aufgabe nicht die erste Wahl, aber es geht natürlich. Die Idee ist, zunächst eine struct oder class zu definieren, die den Eintrag aus einer Zeile aufnimmt. Die Member sollten die Form haben, die Du wirklich benötigst - also z.B. Faktor sollte ein double sein.
    Dann definiert man einen Streaming-Operator für das Einlesen und einen für das Ausgeben.

    Also im Prinzip so:

    #include <iostream>
    #include <iomanip>
    #include <fstream>
    #include <string>
    
    struct Entry
    {
        int m_addr;
        std::string m_name;
        double m_faktor;
        std::string m_einheit;
    };
    
    std::istream& operator>>( std::istream& in, Entry& e )
    {
        for( std::string wort; in >> wort && wort != "#define"; )
            ;
        char komma;
        // #define     PWM1_MIN    8,B_EEPROM_2BYTE_U/*1,mA,#PWM#ESX#STROM*/ 
        return getline( (in >> e.m_name >> e.m_addr).ignore( 999, '*' ) >> e.m_faktor >> komma, e.m_einheit, ',' );
    }
        //      "Adresse Bezeichnung   Faktor  Einheit" << endl;
        //       1234567 1234567890123 1234567 1234567
    std::ostream& operator<<( std::ostream& out, const Entry& e )
    {
        using std::setw;
        return out << setw(7) << e.m_addr << " " << setw(13) << e.m_name << " "
            << setw(7) << e.m_faktor << " " << e.m_einheit; 
    }
    
    int main()
    {
        using namespace std;
        ifstream h_file( "defines.h" );
        if( !h_file.is_open() )
        {
            cerr << "Fehler beim Oeffnen der Datei" << endl;
            return -1;
        }
        cout << "Adresse Bezeichnung   Faktor  Einheit" << left << endl;
        for( Entry e; h_file >> e; )
        {
            // verarbeite den Eintrag 'e'
            cout << e << endl;
            // ggf. in einem Contaier alle Einträge merken; wg. Teil 2.
        }
        return 0;
    };
    

    Zum Teil 2.: zunächst musst Du dort die einzelnen Werte finden. Ignoriere alles bis Du auf eine '(' triffst, dann lese mit getline den String bis ',' ein - ggf. trimmen, d.h Space am Ende entfernen und dann in einem Container von Entries (s.o.) suchen, ob der Name dort vorkommt. Falls ja, liest Du einfach den dann folgenden Wert ein - ich unterstelle mal, das ist immer ein int.

    Gruß
    Werner



  • Also mit welcher Sprache du das schlussendlich machen musst/sollst spielt ja keine Rolle. Auch unter C++ kann man Regex benutzen (was hier wahrscheinlich wirklich am einfachsten ist, wenn man sich mal mit den Ausdrücken auskennt).

    Eine Ausführbare Datei bauen kannst du dann auch praktisch von jeder (Skript-)Sprache und in eine IDE einbinden sollte kein Problem sein. Gibt sicher ein System für externe Programme und dann kannst du das wahrscheinlich auch über die Tasten simulieren.

    Der Knackpunkt ist hier wirklich der Regex Code. Kann die Ausdrücke auch nicht mehr, aber Prinzipiell hast du ein "#define", dann beliebig viele Whitespaces (oder allenfalls nur Leerzeichen), dann ein Wort, wieder Leerzeichen, ein ",", dann ein Wort, ein "/*", dann eine Zahl, ein "," und die Einheit (ein Wort). Den Rest scheinst du ja wegfallen lassen zu können. Auf jeden Fall ist das kein all zu schwerer Ausdruck und kann mit dem hier z.B recht gut ermittelt werden.
    Leider merke ich gerade, dass die Seite down ist, darum noch den hier:
    http://txt2re.com/

    Damit geht das dann relativ einfach. Auch wenn ich dir dennoch empfehle die Syntax von Regex Ausdrücken zu lernen.


Anmelden zum Antworten