从C / C ++代码中移除注释

有没有一个简单的方法来删除C / C ++源文件的评论,而不做任何预处理。 (也就是说,我认为你可以使用gcc -E,但这会扩展macros。)我只是想剥离注释的源代码,没有其他的东西应该改变。

编辑:

偏好现有的工具。 我不想用正则expression式自己写这个,我预见代码中有太多惊喜。

在源文件上运行以下命令:

 gcc -fpreprocessed -dD -E test.c 

感谢KennyTMfind正确的标志。 以下是完整性的结果:

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 

gcc -fpreprocessed -dD -E对我不起作用,但是这个程序是这样做的:

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

这取决于你的评论是多么不正确。 我有一个程序scc C和C ++的注释。 我也有一个testing文件,我尝试了GCC(Mac OS X上的4.2.1)和当前select的答案中的选项 – 而GCC似乎没有做一个完美的工作,在一些可怕的屠杀评论testing用例。

注意:这不是一个现实生活中的问题 – 人们不会写这么可怕的代码。

考虑testing用例的总数(总共135行)

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

在我的Mac上,GCC的输出(gcc -fpreprocessed -dD -E subset.c)是:

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

'scc'的输出是:

 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. 

'scc -C'(可识别双斜杠注释)的输出是:

 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. 

现在在GitHub上提供SCC的源代码

目前版本的SCC是6.60(date为2016-06-12),虽然Git版本是在2017-01-18(在美国/太平洋时区)创build的。 代码可以从https://github.com/jleffler/scc-snapshots上的GitHub获得。; 您还可以查找以前版本( release/x.yz )和两个预发行版本( release/x.yz – 这些都是标记为release/x.yz

代码仍然主要在RCS下开发。 我仍然在研究如何使用子模块或类似的机制来处理像stderr.cstderr.h这样的公共库文件(也可以在https://github.com/jleffler/soqfind); 。

SCC 6.60版试图理解C ++ 11,C ++ 14和C ++ 17的构造,如二进制常量,数字标点符号,原始string和hex浮点数。 它默认为C11模式操作。 (请注意,上面提到的-C标志的含义在答案的正文中描述的4.0x版本和当前是最新版本的6.60版本之间翻转)。

有一个stripcmt程序可以做到这一点:

StripCmt是用C编写的一个简单的实用程序,用于从C,C ++和Java源文件中删除注释。 在Unix文本处理程序的伟大传统中,它可以作为FIFO(先入先出)filter或接受命令行上的参数。

(根据hlovdal的回答: 有关Python代码的问题 )

这是一个perl脚本,用于删除//单行和/ *多行* /注释

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

它需要你的源文件作为命令行参数。 将脚本保存到一个文件,让说remove_comments.pl并使用以下命令调用它:perl -w remove_comments.pl [您的源文件]

希望这会有帮助

我也有这个问题。 我发现这个工具( Cpp-Decomment ),它为我工作。 但是它会忽略注释行是否延伸到下一行。 例如:

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

在这种情况下,我找不到在程序中的方式,所以只是search被忽略的行并手动修复。 我相信会有一个select,或者你可以改变程序的源文件来这样做。

我相信如果您使用一个语句,您可以轻松地删除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 

只有这个命令的问题它不能删除包含多个行的注释,但通过使用此regEx,您可以轻松地实现多行删除注释

因为你使用C,所以你可能想要对C使用“自然”的东西。你可以使用C预处理器来删除注释。 下面的例子与GCC的C预处理器一起工作。 它们应该与其他C处理器一样或以类似的方式工作。

对于C,使用

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

它也适用于从JSON中删除评论,例如像这样:

 cpp -P -o - - <input.json >output.json 

如果您的C预处理器不能直接访问,您可以尝试用cc -Ereplacecppcc -E会调用C编译器,告诉它在预处理器阶段后停止。 如果您的C编译器二进制文件不是cc ,则可以使用C编译器二进制文件的名称replacecc ,例如clang 。 请注意,并非所有预处理器都支持-fpreprocessed

最近我写了一些Ruby代码来解决这个问题。 我曾考虑过下列例外情况:

  • string评论
  • 一行多行注释,修复贪婪匹配。
  • 多行上多行

这里是代码: Github,删除评论

它使用下面的代码来预处理每一行,以防这些注释出现在string中。 如果它出现在你的代码中,呃,运气不好。 你可以用一个更复杂的stringreplace它。

  • MUL_REPLACE_LEFT =“ MUL_REPLACE_LEFT
  • MUL_REPLACE_RIGHT =“ MUL_REPLACE_RIGHT
  • SIG_REPLACE =“ SIG_REPLACE

用法:ruby -winput文件的输出文件

我知道已经很晚了,但是我想我会分享我的代码,并且第一次尝试编写一个编译器。

注意:这不包含多行注释中的"\*/"例如/\*...."*/"...\* 。 然后再一次,gcc 4.8.1也没有。

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

这个程序运行的条件,即/ / / ….. /