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 ich
s 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, ob
s 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.