Eliminar comentarios del código C / C ++

¿Hay alguna manera fácil de eliminar comentarios de un archivo fuente de C / C ++ sin hacer ningún preprocesamiento? (es decir, creo que puedes usar gcc -E pero esto ampliará las macros.) Solo quiero que el código fuente con comentarios eliminados, nada más deba cambiarse.

EDITAR:

Preferencia hacia una herramienta existente. No quiero tener que escribir esto yo mismo con expresiones regulares, preveo demasiadas sorpresas en el código.

Ejecute el siguiente comando en su archivo fuente:

 gcc -fpreprocessed -dD -E test.c 

Gracias a KennyTM por encontrar las banderas adecuadas. Aquí está el resultado para la integridad:

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 

Depende de cuán perversos sean tus comentarios. Tengo un progtwig scc para quitar los comentarios de C y C ++. También tengo un archivo de prueba, y probé GCC (4.2.1 en MacOS X) con las opciones en la respuesta seleccionada actualmente, y GCC no parece hacer un trabajo perfecto en algunos de los comentarios horriblemente asesinados en el caso de prueba.

NB: Este no es un problema de la vida real: las personas no escriben un código tan espantoso.

Considere el (subconjunto – 36 de 135 líneas en total) del caso de prueba:

 /\ *\ 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 */ 

En mi Mac, la salida de GCC (gcc -fpreprocessed -dD -E subset.c) es:

 /\ *\ 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 */ 

El resultado de ‘scc’ es:

 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. 

El resultado de ‘scc -C’ (que reconoce los comentarios de doble barra) es:

 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. 

Fuente para SCC ahora disponible en GitHub

La versión actual de SCC es 6.60 (con fecha de 2016-06-12), aunque las versiones de Git fueron creadas el 2017-01-18 (en la zona horaria de EE. UU./Pacífico). El código está disponible en GitHub en https://github.com/jleffler/scc-snapshots . También puede encontrar instantáneas de las versiones anteriores (4.03, 4.04, 5.05) y dos prelanzamientos (6.16, 6.50); ​​todas están etiquetadas como release/x.yz

El código aún se desarrolla principalmente bajo RCS. Todavía estoy averiguando cómo quiero usar los submódulos o un mecanismo similar para manejar archivos comunes de biblioteca como stderr.c y stderr.h (que también se pueden encontrar en https://github.com/jleffler/soq ) .

La versión 6.60 de SCC intenta comprender construcciones de C ++ 11, C ++ 14 y C ++ 17, como constantes binarias, puntuación numérica, cadenas sin formato y flotantes hexadecimales. Por defecto está en modo operación C11. (Tenga en cuenta que el significado del -C – mencionado anteriormente – cambió entre la versión 4.0x descrita en el cuerpo principal de la respuesta y la versión 6.60 que actualmente es la última versión).

gcc -fpreprocessed -dD -E no funcionó para mí, pero este progtwig lo hace:

 #include  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; } 

Hay un progtwig stripcmt que puede hacer esto:

StripCmt es una utilidad simple escrita en C para eliminar comentarios de archivos fuente C, C ++ y Java. En la gran tradición de los progtwigs de procesamiento de texto de Unix, puede funcionar como un filtro FIFO (Primero en entrar, primero en salir) o aceptar argumentos en la línea de comando.

(por la respuesta de hlovdal a: pregunta sobre el código de Python para esto )

Esta es una secuencia de comandos perl para eliminar // una línea y / * líneas múltiples * / comentarios

  #!/usr/bin/perl undef $/; $text = <>; $text =~ s/\/\/[^\n\r]*(\n\r)?//g; $text =~ s/\/\*+([^*]|\*(?!\/))*\*+\///g; print $text; 

Requiere su archivo fuente como un argumento de línea de comando. Guarde el script en un archivo, digamos remove_comments.pl y llámelo utilizando el siguiente comando: perl -w remove_comments.pl [su archivo fuente]

Espero que sea de ayuda

Yo tuve este problema también. Encontré esta herramienta ( Cpp-Decomment ), que funcionó para mí. Sin embargo, ignora si la línea de comentarios se extiende a la siguiente línea. P.ej:

 // this is my comment \ comment continues ... 

En este caso, no pude encontrar un camino en el progtwig, así que solo busqué las líneas ignoradas y las arreglé manualmente. Creo que habría una opción para eso o tal vez podría cambiar el archivo fuente del progtwig para hacerlo.

Creo que si usa una statement, puede eliminar fácilmente los comentarios de C

 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 

Solo el problema con este comando no puede eliminar comentarios que contengan más de una línea. Pero al usar este regEx puede implementar fácilmente la lógica para Multiline Eliminar comentarios

Recientemente escribí un código de Ruby para resolver este problema. He considerado seguir excepciones:

  • comentar en cuerdas
  • el comentario de línea múltiple en una línea, corrige el partido codicioso.
  • múltiples líneas en múltiples líneas

Aquí está el código: Github, Eliminar comentarios

Utiliza el siguiente código para preprocesar cada línea en caso de que esos comentarios aparezcan en cadenas. Si aparece en tu código, mala suerte. Puede reemplazarlo con cadenas más complejas.

  • MUL_REPLACE_LEFT = ” MUL_REPLACE_LEFT
  • MUL_REPLACE_RIGHT = ” MUL_REPLACE_RIGHT
  • SIG_REPLACE = ” SIG_REPLACE

Uso: ruby ​​-w archivo de entrada inputfile

Debido a que usa C, es posible que desee usar algo que sea “natural” para C. Puede usar el preprocesador C para eliminar comentarios. Los ejemplos que figuran a continuación funcionan con el preprocesador C de GCC. Deberían funcionar igual o de manera similar con otros perprocesadores C.

Para C, use

 cpp -dD -fpreprocessed -o output.c input.c 

También funciona para eliminar comentarios de JSON, por ejemplo, así:

 cpp -P -o - - output.json 

En caso de que no se pueda acceder directamente a su preprocesador C, puede intentar reemplazar cpp con cc -E , que llama al comstackdor de C indicándole que se detenga después de la etapa del preprocesador. En caso de que su comstackdor C binario no sea cc , puede reemplazar cc con el nombre de su comstackdor C binario, por ejemplo, clang . Tenga en cuenta que no todos los preprocesadores admiten -fpreprocessed .

Sé que es tarde, pero pensé en compartir mi código y mi primer bash de escribir un comstackdor.

Nota: esto no cuenta para "\*/" dentro de un comentario de /\*...."*/"...\* por ejemplo /\*...."*/"...\* . Por otra parte, gcc 4.8.1 tampoco.

 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]); } } 
 #include { 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; } 

Este progtwig se ejecuta para las dos condiciones, es decir // y / ….. /