C-Kommentare entfernen



  • Hab ein rießiges Problem: Ich möchte ein Programm schreiben, dass aus alten C-Quelltexten die C-Kommentare (/* bzw. */)entfernen soll. Das Einlesen der Datei habe ich, auch das Ausgeben des Originales. Jetzt soll das Original unter neuem Namen gespeichert werden, dieser wieder aufgerufen (was auch nicht das Problem ist) und dann die C-Kommentare entfernt werden. Also was mir fehlt, ist das Entfernen der C-Kommentare...Kann mir da jemand helfen?
    Danke schon mal



  • Hallo,

    lies zeichenweise ein, wenn du die Kombo /* bemerkst über springe alles zeichen bis du ne Kombo */ bemerkst. Da Kommentare nicht geschachtelt werden dürfen sollte das ohne Probs funktionieren.



  • prolog schrieb:

    Da Kommentare nicht geschachtelt werden dürfen sollte das ohne Probs funktionieren.

    allerdings gilt es noch Zeichenkette und chars auszulassen 😉



  • Aber aufpassen:

    - In Strings kann /* und */ auch vorkommen
    - /* kann nach des Öfteren vorkommen bis zum nächsten */ (Also: / beendet alle vorherigen /!)

    Edit: grml, Shade war schneller

    MfG SideWinder



  • Hmm stimmt.
    Na dann einfach noch zusätzlich merken wenn " anfangen und aufhören.
    Das sollte doch dann gehen.?



  • Das reicht auch nicht, weil " escaped sein können:

    "foo bar\"/* kein kommentar */"
    

    Ausserdem gibts noch den Backslash am Zeilenende:

    /\
    * Das ist ein Kommentar, ob du's glaubst oder nicht
    *??/
    /
    

    Der Backslash kann, wie man sieht, auch als Trigraph geschrieben sein (jedenfalls theoretisch). Alles in allem ist es *so* einfach nun auch wieder nicht.



  • Also soweit hab ichs mal, aber es funzt einfach noch nicht.... Habe Datei einlesen bzw. ausgeben in Implementierungsdatei geschrieben, das geht auch.. C-Kommentare entfernen ist auch in der Implementierungsdatei drin, aber irgendwie greift das ganze nicht, habe das Gefühl, das u. stehendes Programm völlig ignoriert wird (weiß allerdings auch nicht, obs funktioniert).
    Sollte u. stehendes Programm stimmen, dann muss wohl der Fehler in der main sein...verzweifel...

    string entferne_c_kommentare(const string& programm)
    {
       int a = 0,b = 0, c = 0, len = 0, count = 0;
       bool cstyle    = false;
       char cstr[1000];
       string str,space;
       fstream source,dest;
    
       source.open("dateiname",ios::in);
        if(source.is_open())
        {
            dest.open("ziel.cpp",ios::out);
            if(dest.is_open())
            {
                while(!source.eof())
                {
                    // Beim ersten Durchlauf kein Zeilenumbruch in Zieldatei
                    if(count!=0)
                        dest << endl;
                    // Zeilenzähler
                    count++;
                    // Aktuelle Zeile bis '\n' auslesen
                    source.getline(cstr, 1000, '\n');
                    // von char in string kopieren
                    str = cstr;
                    // Länge der Zeile ermitteln
                    len = str.length();
                    // Wurde ein C-Style Kommentar noch nicht geschlossen?
                    if(cstyle)
                    {
                       // Ist in der aktuellen Zeile ein C-Style Kommentar zu Ende?
                        b = str.find("*/");
                        if(b>0)
                        {
                           // Da find() nur auf den Anfang des Kommentarendes zeigt
                            b += 2;
                            // String mit passenden Leerzeichen füllen
                            for(int i=0; i<b; i++)
                                space += " ";
                            // Leerzeichen an passender Stelle einfügen
                            str.replace(0, b, space, 0, b);
                            // Ein Ende wurde gefunden
                            cstyle = false;
                        }
                        else
                        {
                          //In der aktuellen Zeile wurde kein Ende gefunden. Daher 
                          //muss die ganze Zeile mit Leerzeichen ersetzt werden.
                          //String mit passenden Leerzeichen füllen
    
                            for(int i=0; i<len; i++)
                                space += " ";
    
                            // Leerzeichen einfügen
                            str.replace(1, len, space, 1, len);
                        }
                    }
                    else
                    {
                       // Ist in der aktuellen Zeile ein C-Style Kommentar Anfang?
    
                        a = str.find("/*");
                            if(b>0)
                            {
                                c = (b+2)-(a);
                                a--;
                                c=c+2;
                                for(int i=0; i<c; i++)
                                    space += " ";
    
                                // Leerzeichen an passender Stelle einfügen
                                str.replace(a, c, space, 0, c);
                            }
                            else
                            {
                                // In aktueller Zeile wurde nur ein Anfang
                                //  gefunden, daher muss der Rest der Zeile
                                //  durch Leerzeichen ersetz werden und
                                //  weiterhin muss nach einem Ende gesucht
                                //  werden. Daher "cstyle=true" ...
    
                                cstyle = true;
                                c = len-a;
                                for(int i=0; i<c; i++)
                                    space += " ";
                                str.replace(a, c, space, 0, c);
                            }
                     }
    
                }
                dest.close();
            }
            else
                cout << "Kann kein C-Kommentar entfernen"<< endl;
            source.close();
        }
        else
            cout << "Kann kein C-Kommentar ersetzen"<< endl;
      return 0;
    }
    


  • Viel zu kompliziert. Versuchs mal zeichenweise statt zeilenweise.



  • Hmm ich kann nicht garantieren dass es funktuioniert. Is ja auch schon spät.

    //nocomment.h
    #ifndef nocommentH
    #define nocommentH
    
    #include <iostream>
    
    class NoComment{
        private:
            char mCur;
            char mLookAhead;
            bool mInComment;
            bool mInQuotes;
            bool mHadBackSlash;
        public:
            NoComment();
            ~NoComment();
            void Write(std::ostream &) const;
            void Read(std::istream &);
    
    };
    const std::ostream &operator<<(std::ostream &stream,const NoComment &);
    std::istream &operator>>(std::istream &,NoComment &);
    
    #endif
    
    //nocomment.cpp
    #include "nocomment.h"
    
    NoComment::NoComment():mInComment(false),mInQuotes(false),mHadBackSlash(false){}
    NoComment::~NoComment(){}
    
    void NoComment::Read(std::istream &stream){
    
        stream.get(mCur);
        if(mCur=='"' && !mHadBackSlash){
          if(mInComment)  // " in Kommentaren
                return;
          mInQuotes=(mInQuotes) ? false : true; //Anfang oder Ende des Quoting
    
        }
        mHadBackSlash=(mCur=='\\') ? true : false; //Wird evtl. für nächstes Zeichen  gebraucht
    
        if(mInQuotes)  //alles in Quotes überspringen
          return;
    
        if(mCur=='/' && !mInQuotes){  //Commentar ?
            stream.get(mLookAhead);
            if(mLookAhead=='*')
                    mInComment=true;
            else
                stream.unget();
    
        }else if(mCur=='*' && !mInQuotes){ //Commentarende ?
            stream.get(mLookAhead);
            if(mLookAhead=='/'){
                    mInComment=false;
                    mCur=' ';
            }else
                stream.unget();
    
        }
    }
    void NoComment::Write(std::ostream &stream) const{
        if(mInComment)
              return;
         else
              stream<<mCur;
    }
    const std::ostream &operator<<(std::ostream &stream,const NoComment &obj){
       obj.Write(stream);
       return stream;
    }
    std::istream &operator>>(std::istream &stream,NoComment &obj){
       obj.Read(stream);
       return stream;
    }
    
    //main.cpp
    #include<iostream>
    #include<fstream>
    #include "nocomment.h"
    
    using namespace std;
    int main(int argc, char* argv[])
    {
          NoComment nocom;
          ifstream in("test.c");
          ofstream out("testout.c");
          while(!in.eof()){
                in>>nocom;
                out<<nocom;
          }
          return 0;
    }
    

    Wie gesagt ohne Garantie. Hier ist allerdings die ??/-Schreibweise nicht berücksichtigt. Bei nem Testlauf hats funktioniert. Naja soll ja nur ne Anregung sein.


Anmelden zum Antworten