寻找一个脚本将C / C ++中的多行“块”注释转换为单行注释

时间:2010-06-16 19:28:35

标签: c++ c scripting comments

对于这样注释掉的代码,简单的查找/替换不起作用:

例如:

/* templine1
   templine2
   templine3 */

有什么想法吗?

7 个答案:

答案 0 :(得分:1)

精心构造的正则表达式可能会让你到达目的地。

(好吧,这不是作业...... try here;))

答案 1 :(得分:1)

小心......以下是合法的:

if (x > /*let's think...
          I think comparing it to 3 will be a good idea! */ 3) {
     peanut();
}

因此,任何脚本都必须确保将单行注释放在行尾。这会丢失评论的准确位置,而且您需要考虑如何处理这样的事情:

if (/*hmm...
      x?*/ x /* yes,
      x! */ > 3) {
    butter();
}

因此,您可能希望将自己限制为不与其他代码出现在同一行的注释块。在这种情况下,请注意单个正则表达式可以捕获块注释,因此小Perl script可能会完成这项工作。

编辑:实际上,“代码没有出现在同一行”是不够的:

char* s = "hello \
           /* this is not a comment";
           /* this is */

EDIT2:如果您想涵盖所有极端情况,我认为更好的解决方案是tokenize整个文件。既然你可以忽略很多东西,那就不会太难了 - 我过去自己也是这样做的,就像C语言一样。获得令牌流后,您可以检查它,持有“状态”模式以跟踪字符串/单行注释/多行注释。

答案 2 :(得分:1)

Perl hack,未经测试或证实;将破坏其中包含f(blah /*, bar*/)的代码

#open the $file and read it in
my ($fh, $file);
open $fh, "<", $ARGV[0] or die($!);

{ 
 local $/ = undef; 
 $file = <$fh>; 
}
close $fh;

#process it. does some assumptions about aliasing here, may not be valid.
#used the link from elsewhere for the regex
foreach my $comment ($file =~ m//\*(?:.|[\r\n])*?\*///g)
{
  my @lines = split(/\n/, $comment);
  s/^/\/\/ for @lines;
  $comment = join("\n", @lines);
}

open ">", $ARGV[0] or die($!);
print $fh $file;
close $fh;

答案 3 :(得分:1)

如果您使用vim,则可以使用Nerd Commenter插件。

答案 4 :(得分:0)

现在这是DevCpp中的工作代码:

void convert_single(char source[], char dest[]){
    ifstream fin(source);
    ofstream fout(dest);
    char ch;
    while(fin.get(ch)){
        if(ch=='/')
          {
            /*strcpy(line,ch);*/
            fout<<ch;
            fin.get(ch);
            if(ch=='/')
             {
                /*strcat(line,'*');*/
                fout<<'*';
                while(fin.get(ch))
                  {
                    if(ch=='\n')
                      {
                        fout<<"*/\n";
                        break;
                        }
                    else
                       fout<<ch;
                   }
             }
            else
              fout<<ch;
            }
        else
            fout<<ch;       
    } /*end of while loop*/
    fout.close();
    fin.close();    
    return ;
}

答案 5 :(得分:0)

我意识到这是一个老问题,但它没有得到妥善回答。

<强>解

我遇到了这个问题并提出了以下正则表达式(&#39;。&#39;匹配所需的新行标志):

((?<!\/)\/\*[^\r\n]*(?<!\*\/))(([\r\n]\/\/[^\r\n]*(?<!\*\/))*)([\r\n]+)((?!\/\/).*?\*\/)

这可以用来重复用#34; //&#34;替换注释中每行的开头。使用:

$1$2$4\/\/$5

然后是第二个正则表达式:

\/\*(.*?)\*\/

可以替换为:

\/\/$1 

删除块的开始和结束。

<强>说明

所以,问题在于保持插入&#34; //&#34;识别。为此,评论被分解为块:

((?<!\/)\/\*[^\r\n]*(?<!\*\/))

$ 1 - 使用开头&#34; / *&#34;捕获评论的第一行(只要它实际上不是单个注释后跟星号,将匹配除新行之外的任何后续字符,并且如果遇到注释结束将会失败(负面看后面)。

(([\r\n]\/\/[^\r\n]*(?<!\*\/))*)

$ 2 - 使用开头&#34; //&#34;捕获任何已经处理过的评论行后跟与$ 1相同的模式。它包含3美元,因为它会根据需要重复多次。

([\r\n]+)

$ 4 - 在已处理的块之后捕获下一行,我们知道我们想要放置&#34; //&#34;在此之后。

((?!\/\/).*?\*\/)

$ 5 - 捕获剩余的未处理评论,非贪婪,直至结束&#34; * /&#34;

一旦所有的线都有&#34; //&#34;补充说,正则表达式不再匹配,也不匹配单行注释,因此秒步骤完成了整个过程(但它非常简单,不需要解释)。

注意

如果在结束后有&#34; * /&#34;后面有空白空格,则正则表达式仍然匹配。这将导致它注释出块的边界之外的线。为了避免这种替换:

(\*\/)[\t ]+$

使用:

$1

我还发现了一个notepad ++的错误,它错误地匹配整个文件。在这种情况下,您可以使用以下表达式作为第二个正则表达式的替代,以完成仅完全处理的块的转换并防止错误匹配:

\/\*(([^\r\n]*(?<!\*\/))(([\r\n]\/\/[^\r\n]*(?<!\*\/))*))\*\/

在替换次数大幅减少之后(最好是处理更少的块),最好这样做。

答案 6 :(得分:-6)

一步一步:

  1. 将光标放在第一个*。
  2. 的右侧
  3. 点击退格
  4. 点击退格
  5. 输入'//'
  6. 点击箭头
  7. 重复步骤2-5
  8. 重复步骤2-4
  9. 点击结束
  10. 点击退格
  11. 点击退格。
  12. 步骤8-10并非绝对必要。