文字列から単一行と複数行のコメントを削除します


19

ゴール

選択したプログラミング言語を使用して、Cプログラムを表す文字列からコメントを削除する最短のプログラムを作成します。


入力

文字列は任意の形式の入力として使用できますが、変数として使用することもできます。


説明書

次の2種類のコメントを削除します。

  • 複数行コメントで始まり、/*で終わる*/
  • //Linuxスタイルの改行(LF、\n)で始まり、末尾が単一行のコメント

文字列内のコメントは削除されません。この課題のために、考慮する必要があるのは、"区切り文字列のみです。特に、'区切り文字リテラルの可能性は無視できます。3文字表記と行継続(/\<LF>*...)を無視することもできます。


入力:

#include <stdio.h>

int main(int argc, char** argv)
{
    // this comment will be removed
    if (argc > 1) {
        printf("Too many arguments.\n");   // this too will be removed
        return 1;
    }
    printf("Please vist http://this.will.not.be.removed.com\n");
    printf("/* This will stay */\n");
    printf("\"/* This will stay too */\"\n");
    printf("//and so will this\\");
    // but not this
    printf("just \"ano//ther\" test.");
    return 0;
}

出力:

#include <stdio.h>

int main(int argc, char** argv)
{

    if (argc > 1) {
        printf("Too many arguments.\n");   
        return 1;
    }
    printf("Please vist http://this.will.not.be.removed.com\n");
    printf("/* This will stay */\n");
    printf("\"/* This will stay too */\"\n");
    printf("//and so will this\\");

    printf("just \"ano//ther\" test.");
    return 0;
}

入力:

/*
    this shall disappear
*/
#include <string>
int main(int argc, char** argv)
{
    string foo = ""/*remove that!**/;
    // Remove /* this
    int butNotThis = 42;
    // But do */ remove this
    int bar = 4 /*remove this*/* 3; // but don't remove that 3. */
    return 0;//just a comment
}/*end of the file has been reached.*/

出力:

#include <string>
int main(int argc, char** argv)
{
    string foo = "";

    int butNotThis = 42;

    int bar = 4 * 3; 
    return 0;
}

1
それにprintf("\"/* This will stay too */\"\n");登場した場所からコードになるはずですか?
マナトワーク

申し訳ありませんが、それは単なるタイプミスでした。気づいてくれてありがとう!
マチューロディック

空白はカウントされますか?前に4つのスペースがありますが、// this comment will be removedそれらはちょうど消えました。そのためのルールはありますか?
マナトワーク

1
リストされている言語のどれもよくわからないので、いくつかの種類の自己完結型の仕様は、より多くの例と一緒に素晴らしいでしょう。
ズガーブ

@manatwork:空白の削除は必須ではありません
Mathieu Rodic

回答:


11

網膜、35 + 1 + 2 = 38バイト

このプログラムは2つのファイルで構成されているため、2番目のファイルに1バイトのペナルティが含まれています

//.*|/\*[\s\S]*?\*/|("(\\.|[^"])*")
$1

これは、.NETフレーバーを使用した単純な正規表現の置き換えです(ただし、他のほとんどのフレーバーでも同じように機能します)。

アイデアはコメントと文字列の両方を一致させることですが、文字列である場合にのみ一致を書き戻します。文字列を明示的に照合することにより、コメントを検索するときにそれらはスキップされます。


1
これはPHPで驚くほどうまく機能します:regex101.com/r/kB5kA4/1
イスマエルミゲル

1
@IsmaelMiguelはい、特定の機能は使用していません。.NETを選んだ唯一の理由は、Retinaを使用すると、などの呼び出しのオーバーヘッドなしで正規表現のみのプログラムを作成できるためpreg_replaceです。
マーティンエンダー

私はそれを知っています。かなり前に使用したことがあります。私が正しい場合、それはあなたによって作成されました。好奇心が強い人のためでした。また、この質問に含まれる変更をテストできるテストスイートもあります(多くの人が予測しています)
Ismael Miguel

いいね!この正規表現は、他のプログラミング言語でも機能します(スラッシュがエスケープされている場合)。
マチューロディック

私は、サードパーティのライブラリIの仕事を改善するために、あなたの正規表現技法を使用:道場ツールキット
mbomb007

15

シェル+ coreutils + gccコンパイラコレクション、31バイト

この答えは少し抜け目がないように思えるかもしれませんが、質問で具体的に禁止しているものは見当たりませんでした。

不器用な正規表現を使用するのではなく、ジョブ用に作成されたツールを使用してください。正しい結果を与えるのに問題はないはずです:

cpp -fpreprocessed -o- -|sed 1d

STDINから入力を受け取り、STDOUTに出力します。通常、ccpすべての前処理(ヘッダーファイル、マクロ展開、コメントの削除など)を行い-fpreprocessedますが、このオプションを使用すると、ほとんどの手順がスキップされますが、コメントは削除されます。さらに、cppは# 1 "<stdin>"出力の先頭に次のような行を追加するので、sed削除する必要があります。


1
「-fpreprocessedは、入力ファイルは、拡張子のいずれかを持っている場合、暗黙的である.i.iiまたは.mi」。a.iフラグを使用する代わりにファイルを次のような場所に保存することで、いくつかのバイトを保存できるかもしれませんか?
マーティンエンダー

@MartinBüttnerはい、マニュアルにもそのことに気付きました。だから私は何かcat>i.i;cpp -o- i.i|sed 1dが同等になることを期待しています。ただし、完全な前処理が行われます(たとえば、stdio.hの完全なコンテンツが挿入されます)。考えられるgccのバグ??? おそらく、moを取得したらcppソースをチェックします。
デジタル外傷

オプション|sed 1dを追加する場合は削除でき-Pます。(質問で許可されているように)前処理されたコードを予期しているため、3文字表記または行継続を適切に処理しないことに注意してください。
sch

3

Java 365

String a(String s){String o="";int m=1;for(int i=0;i<s.length();i++){String u=s.substring(i,Math.min(i+2,s.length()));char c=s.charAt(i);switch(m){case 1:m=u.equals("/*")?5:u.equals("//")?4:c=='"'?3:1;break;case 3:m=c=='"'?1:c=='\\'?2:3;break;case 2:m=3;break;case 4:m=c=='\n'?1:4;continue;case 5:m=u.equals("*/")?1:5;i+=m==1?1:0;continue;}o+=m<4?c:"";}return o;}}

非ゴルフ

public static final int DEFAULT = 1;
public static final int ESCAPE = 2;
public static final int STRING = 3;
public static final int ONE_LINE_COMMENT = 4;
public static final int MULTI_LINE_COMMENT = 5;

String clear(String s) {
    String out = "";
    int mod = DEFAULT;
    for (int i = 0; i < s.length(); i++) {
        String substring = s.substring(i, Math.min(i + 2 , s.length()));
        char c = s.charAt(i);
        switch (mod) {
            case DEFAULT: // default
                mod = substring.equals("/*") ? MULTI_LINE_COMMENT : substring.equals("//") ? ONE_LINE_COMMENT : c == '"' ? STRING : DEFAULT;
                break;
            case STRING: // string
                mod = c == '"' ? DEFAULT : c == '\\' ? ESCAPE : STRING;
                break;
            case ESCAPE: // string
                mod = STRING;
                break;
            case ONE_LINE_COMMENT: // one line comment
                mod = c == '\n' ? DEFAULT : ONE_LINE_COMMENT;
                continue;
            case MULTI_LINE_COMMENT: // multi line comment
                mod = substring.equals("*/") ? DEFAULT : MULTI_LINE_COMMENT;
                i += mod == DEFAULT ? 1 : 0;
                continue;
        }
        out += mod < 4 ? c : "";
    }

    return out;
}

2

Python2- 163 134バイト

import re
def f(s):
 for x in re.findall(r'("[^\n]*"(?!\\))|(//[^\n]*$|/(?!\\)\*[\s\S]*?\*(?!\\)/)',s,8):s=s.replace(x[1],'')
 print s

ご覧のとおり、正規表現は2つの交互のキャプチャグループで構成されています。最初のものは、引用符で囲まれたすべての文字列をキャプチャします。2番目はすべてのコメントです。

必要なのは、2番目のグループによってキャプチャされたすべてを削除することです。

例:

Python 2.7.9 (default, Dec 11 2014, 04:42:00) 
[GCC 4.9.2] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import re
>>> def f(s):
...  for x in re.findall(r'("[^\n]*"(?!\\))|(//[^\n]*$|/(?!\\)\*[\s\S]*?\*(?!\\)/)',s,8):s=s.replace(x[1],'')
...  print s
... 
>>> code = r'''#include <stdio.h>
... 
... int main(int argc, char** argv)
... {
...     // this comment will be removed
...     if (argc > 1) {
...         printf("Too many arguments.\n");   // this too will be removed
...         return 1;
...     }
...     printf("Please vist http://this.will.not.be.removed.com\n");
...     printf("/* This will stay */\n");
...     printf("\"/* This will stay too */\"\n");
...     printf("//and so will this\\");
...     // but not this
...     printf("just \"ano//ther\" test.");
...     return 0;
... }
... /*
...     this shall disappear
... */
... #include <string>
... int main(int argc, char** argv)
... {
...     string foo = ""/*remove that!**/;
...     // Remove /* this
...     int butNotThis = 42;
...     // But do */ remove this
...     int bar = 4 /*remove this*/* 3; // but don't remove that 3. */
...     return 0;//just a comment
... }/*end of the file has been reached.*/'''
>>> f(code)
#include <stdio.h>

int main(int argc, char** argv)
{

    if (argc > 1) {
        printf("Too many arguments.\n");   
        return 1;
    }
    printf("Please vist http://this.will.not.be.removed.com\n");
    printf("/* This will stay */\n");
    printf("\"/* This will stay too */\"\n");
    printf("//and so will this\\");

    printf("just \"ano//ther\" test.");
    return 0;
}

#include <string>
int main(int argc, char** argv)
{
    string foo = "";

    int butNotThis = 42;

    int bar = 4 * 3; 
    return 0;
}

1

レボル-151

f: func[t][Q:{"}W: complement charset Q parse t[any[[Q any["\\"|"\"Q | W]Q]|[a:[["//"to[lf | end]]|["/*"thru"*/"]]b:(remove/part a b):a skip]| skip]]t]

Ungolfed +いくつかの注釈:

f: func [t] [
    Q: {"}
    W: complement charset Q     ;; any char thats not a double quote

    ; rule to parse t (c program) - it can be ANY of 
    ;     1. string 
    ;     2. OR comment (if so then remove)
    ;     3. OR pass thru

    parse t [
        any [
            ;; 1. String rule
            [Q any ["\\" | "\" Q | W] Q]

            ;; 2. OR comments rule
            | [
                a:  ;; mark beginning of match
                [
                    ;;    // comment    OR  /* comment */
                    ["//" to [lf | end]] | ["/*" thru "*/"]
                ]
                b:  ;; mark end of match 
                (remove/part a b) :a skip   ;; remove comment
            ]

            ;; 3. OR allow thru (so not a String or Comment)
            | skip
        ]
    ]

    t
]

1

PHP

@Martin Enderの回答をPHPに変換する:

$str = preg_replace_callback('/\/\/.*|\/\*[\s\S]*?\*\/|("(\\.|[^"])*")/m', 
  function($matches){
     if(\is_array($matches) && (\count($matches) > 1)){
        return $matches[1];
     }else{
        return '';
     }
  }, $str);

現在、$str単一行および複数行のコメントが失われています。これは、にフィードする前にJSONデータのコメントを取り除くのに役立ちますjson_decode()


たぶん、三項演算子を使用してバイト数を減らすことができますか?
マチューロディック

0

C#(262文字):

この非常に良いからSOの答え:

string a(string i){return Regex.Replace(i, @"/\*(.*?)\*/|//(.*?)\r?\n|""((\\[^\n]|[^""\n])*)""|@(""[^""]*"")+", m => { var v = m.Value; if (v.StartsWith("/*") || v.StartsWith("//")) return v.StartsWith("//") ? "\r\n" : ""; return v; }, RegexOptions.Singleline);

-1

JS(ES6)、47文字(ワイプ)

デモ:http : //codepen.io/anon/pen/dPEMro

a=b=>b.replace(/(\/\*[^]*?\*\/|\/\/.*)\n?/g,"")

私のcodegolfedミニファイアーに触発された:http ://xem.github.io/miniMinifier/

まだ文字列のコメントを処理していません...

JS正規表現でそれを実現できるかどうかを知りたいです。


この回答が要件を満たしていない場合は、修正するか削除する必要があります。
mbomb007
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.