문자열에서 한 줄 및 여러 줄 주석 제거


19

선택한 프로그래밍 언어를 사용하여 C 프로그램을 나타내는 문자열에서 주석을 제거 하는 가장 짧은 프로그램 을 작성하십시오 .


입력

문자열은 모든 형태의 입력으로 사용할 수 있지만 변수로도 사용할 수 있습니다.


명령

두 가지 다른 종류의 주석이 제거됩니다.

  • 여러 줄 주석 으로 시작 /*하고 끝나는*/
  • //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");에서 코드 가 나타나야 합니까?
manatwork

죄송합니다. 오타 일뿐입니다. 알아 주셔서 감사합니다!
Mathieu Rodic

공백은 중요합니까? // this comment will be removed방금 사라진 4 개의 공간이 있습니다 . 그것에 대한 규칙?
manatwork

1
나열된 언어를 잘 모르므로 더 많은 예제와 함께 자체 포함 사양이 좋을 것입니다.
Zgarb

@manatwork : 공백 제거는 필수가 아닙니다
Mathieu Rodic

답변:


11

망막 , 35 + 1 + 2 = 38 바이트

이 프로그램은 두 개의 파일로 구성되므로 두 번째 파일에 대해 1 바이트의 페널티 가 포함되었습니다 .

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

이것은 .NET 맛을 사용하는 간단한 정규식 대체물입니다 (그러나 대부분의 다른 풍미에서 동일하게 작동하지만).

아이디어는 주석과 문자열을 모두 일치시키는 것이지만 문자열 인 경우에만 일치 항목을 다시 작성하십시오. 문자열을 명시 적으로 일치 시키면 주석을 검색 할 때 생략됩니다.


1
이것은 PHP에서 놀랍게 잘 작동합니다 : regex101.com/r/kB5kA4/1
Ismael Miguel

1
@IsmaelMiguel 예, 특정 기능을 사용하지 않았습니다. 내가 .NET을 선택한 유일한 이유는 Retina가과 같은 호출의 오버 헤드없이 정규식 전용 프로그램을 작성할 수 있기 때문 preg_replace입니다.
Martin Ender

알고 있습니다. 당신은 전에 그것을 많이 사용했습니다. 내가 맞다면, 그것은 당신에 의해 만들어졌습니다. 호기심이 많았습니다. 또한, 이제이 질문에 대한 모든 변경 사항을 테스트 할 수있는 테스트 스위트가 있습니다 (많은 예측)
Ismael Miguel

좋은! 이 정규 표현식은 다른 프로그래밍 언어와도 작동합니다 (슬래시를 이스케이프 처리 할 때).
Mathieu Rodic

정규식 기술을 사용하여 함께 작업하는 타사 라이브러리를 개선했습니다. Dojo Toolkit
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 버그 ??? 아마 내가 얻을 때 cpp 소스를 확인합니다.
Digital Trauma

옵션 |sed 1d을 추가 하면를 제거 할 수 있습니다 -P. (질문에 의해 허용되는 바와 같이), 사전 처리 된 코드가 예상되기 때문에 3 자 그래프 나 줄 연속을 제대로 처리하지 못합니다.
sch

3

자바 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

파이썬 2- 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 개의 대체 캡처 그룹으로 구성됩니다. 첫 번째는 인용 된 모든 문자열을 캡처합니다. 두 번째는 모든 의견입니다.

우리가해야 할 일은 두 번째 그룹이 캡처 한 모든 것을 제거하는 것입니다.

예:

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

PHP에 대한 @Martin Ender의 답변을 변환 :

$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().


삼항 연산자를 사용하여 바이트 수를 줄일 수 있습니까?
Mathieu Rodic

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 자 (wip)

데모 : http://codepen.io/anon/pen/dPEMro

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

내 코드 골프 축소 기에서 영감을 얻었습니다 : http://xem.github.io/miniMinifier/

아직 문자열의 주석을 처리하지 않습니다 ...

JS 정규 표현식에서 그것을 달성 할 수 있는지 궁금합니다.


이 답변이 요구 사항을 충족하지 않으면 수정하거나 삭제해야합니다.
mbomb007
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.