Gibt es eine einfache Möglichkeit, Kommentare aus einer C / C ++ - Quelldatei zu entfernen, ohne eine Vorverarbeitung durchzuführen? (dh ich denke, Sie können gcc -E verwenden, aber dies erweitert die Makros.) Ich möchte nur, dass der Quellcode mit Kommentaren entfernt wird, nichts anderes sollte geändert werden.
BEARBEITEN:
Bevorzugung eines vorhandenen Werkzeugs. Ich möchte dies nicht selbst mit regulären Ausdrücken schreiben müssen, ich sehe zu viele Überraschungen im Code voraus.
error: pasting "/" and "/" does not give a valid preprocessing token
- was erwartet wird, da das Entfernen von Kommentaren vor der Vorverarbeitung erfolgtAntworten:
Führen Sie den folgenden Befehl für Ihre Quelldatei aus:
gcc -fpreprocessed -dD -E test.c
Vielen Dank an KennyTM für das Finden der richtigen Flaggen. Hier ist das Ergebnis der Vollständigkeit halber:
test.c:
#define foo bar foo foo foo #ifdef foo #undef foo #define foo baz #endif foo foo /* comments? comments. */ // c++ style comments
gcc -fpreprocessed -dD -E test.c
::#define foo bar foo foo foo #ifdef foo #undef foo #define foo baz #endif foo foo
quelle
#define foo bar\nfoo foo foo
gcc -fpreprocessed -dM -E test.c
, um auch das#define
-s zu erhalten , aber sie befinden sich nicht an den ursprünglichen Speicherorten.#include
d-Dateien eingefügt und die kommentierten Zeilen durch leere Zeilen ersetzt, anstatt die Kommentare zu löschen. FWIW eine Kombination aus sed und gcc hat bei mir immer perfekt funktioniert, siehe stackoverflow.com/a/13062682/1745001 .Es hängt davon ab, wie pervers Ihre Kommentare sind. Ich habe ein Programm
scc
zum Entfernen von C- und C ++ - Kommentaren. Ich habe auch eine Testdatei dafür und habe GCC (4.2.1 unter MacOS X) mit den Optionen in der aktuell ausgewählten Antwort ausprobiert - und GCC scheint bei einigen der schrecklich geschlachteten Kommentare im Internet keine perfekte Arbeit zu leisten Testfall.NB: Dies ist kein echtes Problem - die Leute schreiben keinen so schrecklichen Code.
Betrachten Sie die (Teilmenge - 36 von insgesamt 135 Zeilen) des Testfalls:
/\ *\ Regular comment *\ / The regular C comment number 1 has finished. /\ \/ This is not a C++/C99 comment! This is followed by C++/C99 comment number 3. /\ \ \ / But this is a C++/C99 comment! The C++/C99 comment number 3 has finished. /\ \* This is not a C or C++ comment! This is followed by regular C comment number 2. /\ */ This is a regular C comment *\ but this is just a routine continuation *\ and that was not the end either - but this is *\ \ / The regular C comment number 2 has finished. This is followed by regular C comment number 3. /\ \ \ \ * C comment */
Auf meinem Mac
gcc -fpreprocessed -dD -E subset.c
lautet die Ausgabe von GCC ( ):/\ *\ Regular comment *\ / The regular C comment number 1 has finished. /\ \/ This is not a C++/C99 comment! This is followed by C++/C99 comment number 3. /\ \ \ / But this is a C++/C99 comment! The C++/C99 comment number 3 has finished. /\ \* This is not a C or C++ comment! This is followed by regular C comment number 2. /\ */ This is a regular C comment *\ but this is just a routine continuation *\ and that was not the end either - but this is *\ \ / The regular C comment number 2 has finished. This is followed by regular C comment number 3. /\ \ \ \ * C comment */
Die Ausgabe von 'scc' ist:
The regular C comment number 1 has finished. /\ \/ This is not a C++/C99 comment! This is followed by C++/C99 comment number 3. /\ \ \ / But this is a C++/C99 comment! The C++/C99 comment number 3 has finished. /\ \* This is not a C or C++ comment! This is followed by regular C comment number 2. The regular C comment number 2 has finished. This is followed by regular C comment number 3.
Die Ausgabe von 'scc -C' (die doppelte Schrägstriche erkennt) lautet:
The regular C comment number 1 has finished. /\ \/ This is not a C++/C99 comment! This is followed by C++/C99 comment number 3. The C++/C99 comment number 3 has finished. /\ \* This is not a C or C++ comment! This is followed by regular C comment number 2. The regular C comment number 2 has finished. This is followed by regular C comment number 3.
Quelle für SCC jetzt auf GitHub verfügbar
Die aktuelle Version von SCC ist 6.60 (vom 12.06.2016), obwohl die Git-Versionen am 18.01.2017 (in der Zeitzone USA / Pazifik) erstellt wurden. Der Code ist bei GitHub unter https://github.com/jleffler/scc-snapshots erhältlich . Sie können auch Snapshots der vorherigen Versionen (4.03, 4.04, 5.05) und zwei Vorversionen (6.16, 6.50) finden - diese sind alle mit Tags versehen
release/x.yz
.Der Code wird noch hauptsächlich unter RCS entwickelt. Ich arbeite immer noch daran, wie ich Submodule oder einen ähnlichen Mechanismus verwenden möchte, um allgemeine Bibliotheksdateien wie
stderr.c
und zu verarbeitenstderr.h
(die auch unter https://github.com/jleffler/soq zu finden sind ).SCC Version 6.60 versucht, C ++ 11-, C ++ 14- und C ++ 17-Konstrukte wie Binärkonstanten, numerische Interpunktion, rohe Zeichenfolgen und hexadezimale Gleitkommazahlen zu verstehen. Standardmäßig wird der C11-Modus verwendet. (Beachten Sie, dass die Bedeutung des
-C
oben erwähnten Flags zwischen der im Hauptteil der Antwort beschriebenen Version 4.0x und der Version 6.60, die derzeit die neueste Version ist, gewechselt ist.)quelle
gcc -fpreprocessed -dD -E hat bei mir nicht funktioniert, aber dieses Programm macht es:
#include <stdio.h> static void process(FILE *f) { int c; while ( (c=getc(f)) != EOF ) { if (c=='\'' || c=='"') /* literal */ { int q=c; do { putchar(c); if (c=='\\') putchar(getc(f)); c=getc(f); } while (c!=q); putchar(c); } else if (c=='/') /* opening comment ? */ { c=getc(f); if (c!='*') /* no, recover */ { putchar('/'); ungetc(c,f); } else { int p; putchar(' '); /* replace comment with space */ do { p=c; c=getc(f); } while (c!='/' || p!='*'); } } else { putchar(c); } } } int main(int argc, char *argv[]) { process(stdin); return 0; }
quelle
Es gibt ein Stripcmt- Programm, das dies kann:
(per hlovdals Antwort auf: Frage zu Python-Code dafür )
quelle
int /* comment // */ main()
.// comment out next line \
/*
,//
,*/
nicht in zwei Zeilen aufgeteilt.Dies ist ein Perl-Skript zum Entfernen von // einzeiligen und / * mehrzeiligen * / Kommentaren
#!/usr/bin/perl undef $/; $text = <>; $text =~ s/\/\/[^\n\r]*(\n\r)?//g; $text =~ s/\/\*+([^*]|\*(?!\/))*\*+\///g; print $text;
Es erfordert Ihre Quelldatei als Befehlszeilenargument. Speichern Sie das Skript in einer Datei, sagen Sie remove_comments.pl, und rufen Sie es mit dem folgenden Befehl auf: perl -w remove_comments.pl [Ihre Quelldatei]
Hoffe es wird hilfreich sein
quelle
"/*"
oder"//"
usw. im Kaninchenbau enthalten.Ich hatte auch dieses Problem. Ich habe dieses Tool ( Cpp-Decomment ) gefunden, das für mich funktioniert hat. Es wird jedoch ignoriert, ob die Kommentarzeile bis zur nächsten Zeile reicht. Z.B:
// this is my comment \ comment continues ...
In diesem Fall konnte ich keinen Weg im Programm finden, also suchte ich einfach nach ignorierten Zeilen und korrigierte sie manuell. Ich glaube, dafür gibt es eine Option, oder Sie könnten die Quelldatei des Programms ändern, um dies zu tun.
quelle
Da Sie C verwenden, möchten Sie möglicherweise etwas verwenden, das für C "natürlich" ist. Sie können den C-Präprozessor verwenden, um nur Kommentare zu entfernen. Die folgenden Beispiele funktionieren mit dem C-Präprozessor von GCC. Sie sollten auf die gleiche oder ähnliche Weise auch mit anderen C-Perprozessoren zusammenarbeiten.
Verwenden Sie für C
cpp -dD -fpreprocessed -o output.c input.c
Es funktioniert auch zum Entfernen von Kommentaren aus JSON, zum Beispiel wie folgt:
cpp -P -o - - <input.json >output.json
Falls Ihr C - Präprozessor nicht direkt zugänglich ist , können Sie versuchen , ersetzen
cpp
mitcc -E
, die den C - Compiler nennt es erzählt nach der Prä - Prozessor Bühne zu stoppen. Falls Ihre C-Compiler-Binärdatei nicht vorhanden istcc
, können Sie sie beispielsweise durchcc
den Namen Ihrer C-Compiler-Binärdatei ersetzenclang
. Beachten Sie, dass nicht alle Präprozessoren unterstützen-fpreprocessed
.quelle
Ich schreibe ein C-Programm mit einer Standard-C-Bibliothek, ungefähr 200 Zeilen, die Kommentare der C-Quellcodedatei entfernt. qeatzy / removeccomments
Verhalten
void init(/* do initialization */) {...}
"
und respektiert\"
.\
, ist die aktuelle Zeile Teil der vorherigen Zeile.Testen & Profiling
Ich habe mit dem größten cpython-Quellcode getestet , der viele Kommentare enthält . In diesem Fall erledigt es die Arbeit korrekt und schnell, 2-5 schneller als gcc
time gcc -fpreprocessed -dD -E Modules/unicodeobject.c > res.c 2>/dev/null time ./removeccomments < Modules/unicodeobject.c > result.c
Verwendung
/path/to/removeccomments < input_file > output_file
quelle
Ich glaube, wenn Sie eine Aussage verwenden, können Sie Kommentare einfach aus C entfernen
perl -i -pe ‘s/\\\*(.*)/g’ file.c This command Use for removing * C style comments perl -i -pe 's/\\\\(.*)/g' file.cpp This command Use for removing \ C++ Style Comments
Einziges Problem mit diesem Befehl: Kommentare, die mehr als eine Zeile enthalten, können nicht entfernt werden. Mit diesem regEx können Sie jedoch problemlos eine Logik zum Entfernen von Kommentaren mit mehreren Zeilen implementieren
quelle
Kürzlich habe ich Ruby-Code geschrieben, um dieses Problem zu lösen. Ich habe folgende Ausnahmen berücksichtigt:
Hier ist der Code :
Es verwendet den folgenden Code, um jede Zeile vorzuverarbeiten, falls diese Kommentare in Zeichenfolgen angezeigt werden. Wenn es in Ihrem Code erscheint, ähm, Pech. Sie können es durch komplexere Zeichenfolgen ersetzen.
VERWENDUNG:
ruby -w inputfile outputfile
quelle
Ich weiß, dass es spät ist, aber ich dachte, ich würde meinen Code und meinen ersten Versuch, einen Compiler zu schreiben, teilen.
Hinweis: Dies gilt nicht für
"\*/"
einen mehrzeiligen Kommentar, z/\*...."*/"...\*
. Andererseits tut gcc 4.8.1 dies auch nicht.void function_removeComments(char *pchar_sourceFile, long long_sourceFileSize) { long long_sourceFileIndex = 0; long long_logIndex = 0; int int_EOF = 0; for (long_sourceFileIndex=0; long_sourceFileIndex < long_sourceFileSize;long_sourceFileIndex++) { if (pchar_sourceFile[long_sourceFileIndex] == '/' && int_EOF == 0) { long_logIndex = long_sourceFileIndex; // log "possible" start of comment if (long_sourceFileIndex+1 < long_sourceFileSize) // array bounds check given we want to peek at the next character { if (pchar_sourceFile[long_sourceFileIndex+1] == '*') // multiline comment { for (long_sourceFileIndex+=2;long_sourceFileIndex < long_sourceFileSize; long_sourceFileIndex++) { if (pchar_sourceFile[long_sourceFileIndex] == '*' && pchar_sourceFile[long_sourceFileIndex+1] == '/') { // since we've found the end of multiline comment // we want to increment the pointer position two characters // accounting for "*" and "/" long_sourceFileIndex+=2; break; // terminating sequence found } } // didn't find terminating sequence so it must be eof. // set file pointer position to initial comment start position // so we can display file contents. if (long_sourceFileIndex >= long_sourceFileSize) { long_sourceFileIndex = long_logIndex; int_EOF = 1; } } else if (pchar_sourceFile[long_sourceFileIndex+1] == '/') // single line comment { // since we know its a single line comment, increment file pointer // until we encounter a new line or its the eof for (long_sourceFileIndex++; pchar_sourceFile[long_sourceFileIndex] != '\n' && pchar_sourceFile[long_sourceFileIndex] != '\0'; long_sourceFileIndex++); } } } printf("%c",pchar_sourceFile[long_sourceFileIndex]); } }
quelle
/*
der Verarbeitung*/
der Kommentar durch die nächste Zeichenfolge ohne Leerzeichen beendet wird. In einem Kommentar gibt es keine Escape-Mechanismen - was Sie vielleicht damit meinen, dass GCC ihn auch nicht behandelt. Ihr Code hat Probleme mit"/* Magritte notes: Ceci n'est pas une commentaire */"
(weil es sich um ein String-Literal handelt, nicht um einen Kommentar - aber er hat über Pipes gesprochen, nicht über Kommentare).#include<stdio.h> { char c; char tmp = '\0'; int inside_comment = 0; // A flag to check whether we are inside comment while((c = getchar()) != EOF) { if(tmp) { if(c == '/') { while((c = getchar()) !='\n'); tmp = '\0'; putchar('\n'); continue; }else if(c == '*') { inside_comment = 1; while(inside_comment) { while((c = getchar()) != '*'); c = getchar(); if(c == '/'){ tmp = '\0'; inside_comment = 0; } } continue; }else { putchar(c); tmp = '\0'; continue; } } if(c == '/') { tmp = c; } else { putchar(c); } } return 0; }
Dieses Programm läuft für beide Bedingungen, dh // und / ..... /
quelle
int main(void)
. 2. Es werden keine Kommentarbegrenzer in Zeichenfolgenliteralen und Zeichenkonstanten behandelt. 3. Es löscht ein einzelnes/
Zeichen (versuchen Sie es mit seinem eigenen Quellcode auszuführen).