有没有一种简单的方法可以从C/C++源文件中删除注释,而不进行任何预处理呢?(即,我认为可以使用gcc -E,但这将展开宏。)我只想要没有注释的源代码,不应该改变任何其他内容。
编辑:
更喜欢现有的工具。我不想用正则表达式自己编写代码,因为我预见到会有太多的问题。
有没有一种简单的方法可以从C/C++源文件中删除注释,而不进行任何预处理呢?(即,我认为可以使用gcc -E,但这将展开宏。)我只想要没有注释的源代码,不应该改变任何其他内容。
编辑:
更喜欢现有的工具。我不想用正则表达式自己编写代码,因为我预见到会有太多的问题。
在您的源文件上运行以下命令:
gcc -fpreprocessed -dD -E test.c
感谢KennyTM找到正确的标志。 以下是完整性的结果:
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
#define foo bar\nfoo foo foo
。 - Pascal Cuoqgcc -fpreprocessed -dM -E test.c
命令以获取#define
,但它们将不会出现在原始位置。 - kennytm#include
文件内联,并将注释行替换为空白行,而不是删除注释。对我来说,sed和gcc的组合一直都非常完美,详情请见https://dev59.com/vGcs5IYBdhLWcg3wMg-z#13062682。 - Ed Morton这取决于你的评论有多恶劣。我有一个程序scc
用于去除C和C++注释。我还有一个测试文件,我尝试了GCC(在MacOS X上的4.2.1版本)并使用了当前选定答案中的选项 - 但是GCC似乎不能完美地处理测试用例中一些被切割殆尽的注释。
请考虑测试用例的子集(共135行中的36行):
/\
*\
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 */
的输出结果是: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.
SCC的当前版本是6.60(日期为2016-06-12),但Git版本是在2017-01-18(美国/太平洋时区)创建的。该代码可从GitHub获取,网址为https://github.com/jleffler/scc-snapshots。您还可以找到之前的版本(4.03、4.04、5.05)和两个预发布版本(6.16、6.50)的快照,这些都被标记为release/x.yz
。
该代码仍然主要在RCS下开发。作者仍在思考如何使用子模块或类似机制来处理通用库文件,例如 stderr.c
和 stderr.h
文件(也可以在https://github.com/jleffler/soq中找到)。
SCC 6.60版本试图理解C++11、C++14和C++17结构,如二进制常量、数字标点、原始字符串和十六进制浮点数。它默认使用C11模式操作。(请注意,上述提到的-C
标志的含义,在主体回答中描述的4.0x版本和目前最新版本6.60之间发生了变化。)
#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;
c = 0;
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;
}
int /* comment // */ main()
这样的代码。 - pynexj//注释掉下一行\
的注释时,会出现错误。 - sleepsort/*
、//
、*/
不分成两行,它就能完美地工作。 - qeatzy #!/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 ...
因为您使用C语言,您可能希望使用一些与C语言“自然”相似的东西。您可以使用C预处理器来仅删除注释。下面给出的示例适用于来自GCC的C预处理器。它们也应该以相同或类似的方式与其他C预处理器一起工作。
对于C语言,请使用:
cpp -dD -fpreprocessed -o output.c input.c
cpp -P -o - - <input.json >output.json
cpp
替换为cc -E
,这会调用C编译器并告诉它在预处理阶段停止。
如果您的C编译器二进制文件不是cc
,则可以将cc
替换为您的C编译器二进制文件的名称,例如clang
。请注意,并非所有预处理器都支持-fpreprocessed
。我使用标准C库编写了一个C程序,大约200行,用于删除C源代码文件中的注释。 qeatzy/removeccomments
void init(/* do initialization */) {...}
"
和\"
来尊重C字符串文字。\
结尾,则当前行是前一行的一部分。我使用包含许多注释的最大cpython源代码进行了测试。 在这种情况下,它可以正确且快速地完成任务,比gcc快2-5倍。
time gcc -fpreprocessed -dD -E Modules/unicodeobject.c > res.c 2>/dev/null
time ./removeccomments < Modules/unicodeobject.c > result.c
/path/to/removeccomments < input_file > output_file
最近我写了一些Ruby代码来解决这个问题。我考虑了以下几种异常情况:
这里是代码:
它使用以下代码来预处理每一行,以防止这些注释出现在字符串中。如果它出现在你的代码中,那么,很不幸。你可以用更复杂的字符串替换它。
用法:ruby -w inputfile outputfile
我相信如果你使用一个语句,就可以轻松地从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
这个命令的唯一问题是它不能删除包含多行的注释。但是,通过使用这个正则表达式,您可以轻松实现逻辑以删除多行注释。