Xóa các nhận xét dòng đơn và đa dòng khỏi chuỗi


19

Mục tiêu

Sử dụng ngôn ngữ lập trình bạn chọn, viết chương trình ngắn nhất để loại bỏ nhận xét khỏi chuỗi đại diện cho chương trình C.


Đầu vào

Chuỗi có thể được coi là bất kỳ hình thức đầu vào nào, nhưng nó cũng có thể được coi là một biến.


Hướng dẫn

Hai loại ý kiến ​​khác nhau sẽ bị xóa:

  • bình luận đa dòng , bắt đầu bằng /*và kết thúc bằng*/
  • nhận xét dòng đơn , bắt đầu bằng //và kết thúc bằng ngắt dòng theo kiểu Linux (LF, \n)

Nhận xét trong chuỗi không được xóa. Đối với mục đích của thử thách này, bạn chỉ cần xem xét các "chuỗi giới hạn. Đặc biệt, bạn có thể bỏ qua khả năng 'chữ ký tự giới hạn. Bạn cũng có thể bỏ qua các biểu tượng và tiếp tục dòng ( /\<LF>*...).


Ví dụ

Đầu vào:

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

Đầu ra:

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

Đầu vào:

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

Đầu ra:

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

    int butNotThis = 42;

    int bar = 4 * 3; 
    return 0;
}

1
Từ đâu printf("\"/* This will stay too */\"\n");xuất hiện trong nên trở thành mã?
manatwork

Rất tiếc, xin lỗi ... đó chỉ là một lỗi đánh máy. Cảm ơn đã chú ý!
Mathieu Rodic

Làm khoảng trắng đếm? Có 4 khoảng trống phía trước // this comment will be removedvừa biến mất. Bất kỳ quy tắc cho điều đó?
manatwork

1
Tôi không biết bất kỳ ngôn ngữ nào được liệt kê tốt, vì vậy một số loại thông số độc lập sẽ rất hay, cùng với nhiều ví dụ khác.
Zgarb

@manatwork: xóa khoảng trắng là không bắt buộc
Mathieu Rodic

Câu trả lời:


11

Võng mạc , 35 + 1 + 2 = 38 byte

Chương trình này bao gồm hai tệp, do đó tôi đã bao gồm hình phạt 1 byte cho tệp thứ hai .

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

Đây là một thay thế regex đơn giản, sử dụng hương vị .NET (mặc dù điều này sẽ hoạt động tương tự trong hầu hết các hương vị khác).

Ý tưởng là để khớp cả hai bình luận và chuỗi, nhưng chỉ viết lại khớp nếu đó là một chuỗi. Bằng cách kết hợp các chuỗi rõ ràng, chúng bị bỏ qua khi tìm kiếm bình luận.


1
Điều này hoạt động tốt đáng ngạc nhiên trong PHP: regex101.com/r/kB5kA4/1
Ismael Miguel

1
@IsmaelMiguel Có, tôi đã không sử dụng bất kỳ tính năng cụ thể nào. Lý do duy nhất tôi chọn .NET là vì Retina cho phép tôi viết các chương trình chỉ dành cho regex mà không cần bất kỳ chi phí nào để gọi như thế preg_replace.
Martin Ender

Tôi biết điều đó. Bạn đã sử dụng nó khá nhiều trước đây. Nếu tôi đúng, nó được tạo ra bởi bạn. Đó là cho sự tò mò. Ngoài ra, bây giờ bạn có một bộ thử nghiệm, nơi bạn có thể kiểm tra bất kỳ thay đổi nào xảy ra với câu hỏi này (tôi dự đoán nhiều)
Ismael Miguel

Tốt đẹp! Biểu thức chính quy này thậm chí hoạt động với các ngôn ngữ lập trình khác (khi dấu gạch chéo được thoát).
Mathieu Rodic

Tôi đã sử dụng kỹ thuật regex của bạn để cải thiện thư viện của bên thứ ba mà tôi làm việc với: Bộ công cụ Dojo
mbomb007

15

Shell + coreutils + bộ sưu tập trình biên dịch gcc, 31 byte

Câu trả lời này có vẻ hơi khó hiểu, nhưng tôi không thấy điều gì đặc biệt cấm nó trong câu hỏi.

Thay vì sử dụng các biểu thức thông thường vụng về, tại sao không sử dụng công cụ được xây dựng cho công việc. Không có vấn đề gì khi đưa ra kết quả chính xác:

cpp -fpreprocessed -o- -|sed 1d

Đưa đầu vào từ STDIN và đầu ra sang STDOUT. Thông thường ccpsẽ thực hiện tất cả quá trình tiền xử lý (tệp tiêu đề, mở rộng macro, xóa nhận xét, v.v.), nhưng với -fpreprocessedtùy chọn, nó sẽ bỏ qua hầu hết các bước, nhưng nó vẫn sẽ xóa nhận xét. Ngoài ra, cpp thêm một dòng giống như # 1 "<stdin>"bắt đầu của đầu ra, vì vậy sedcó sẵn để xóa nó.


1
"-Fpre được xử lý là ẩn nếu tệp đầu vào có một trong các phần mở rộng .i, .iihoặc .mi". bạn có thể lưu một số byte bằng cách lưu tệp trong một cái gì đó như a.ithay vì sử dụng cờ không?
Martin Ender

@ MartinBüttner Vâng, tôi nhận thấy rằng trong hướng dẫn cũng vậy. Vì vậy, tôi mong đợi một cái gì đó cat>i.i;cpp -o- i.i|sed 1dtương đương. Nhưng tiền xử lý đầy đủ xảy ra (ví dụ: toàn bộ nội dung của stdio.h được chèn). Lỗi gcc có thể xảy ra ??? Có lẽ tôi sẽ kiểm tra nguồn cpp khi tôi nhận được mo '.
Chấn thương kỹ thuật số

Bạn có thể loại bỏ |sed 1dnếu bạn thêm -Ptùy chọn. Lưu ý rằng (như được cho phép bởi câu hỏi), vì nó mong đợi mã được xử lý trước, nó sẽ không xử lý các dấu ba chấm hoặc tiếp tục dòng đúng cách.
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;}}

Bị đánh cắp

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 byte

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

Như bạn có thể thấy ở đây , regex bao gồm 2 nhóm bắt xen kẽ. Cái đầu tiên nắm bắt tất cả các chuỗi trích dẫn. Cái thứ hai tất cả các ý kiến.

Tất cả những gì chúng ta cần làm là loại bỏ mọi thứ được chụp bởi nhóm thứ 2.

Thí dụ:

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

Nổi loạn - 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 + một số chú thích:

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

Chuyển đổi câu trả lời của @Martin Ender cho php:

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

bây giờ $strđã mất bình luận đơn và đa dòng. Điều này rất hữu ích để tước các nhận xét trong dữ liệu JSON trước khi cho ăn json_decode().


Có lẽ bạn có thể giảm số byte bằng cách sử dụng toán tử ternary?
Mathieu Rodic

0

C # (262 ký tự):

Từ câu trả lời SO rất tốt này :

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 ký tự (lau)

DEMO: http://codepen.io/anon/pen/dPEMro

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

Lấy cảm hứng từ các công cụ khai thác được mã hóa của tôi: http://xem.github.io/miniMinifier/

chưa xử lý các bình luận trong chuỗi ...

Tôi tò mò muốn xem liệu có thể đạt được điều đó trong các biểu thức JS không.


Nếu câu trả lời này không đáp ứng các yêu cầu, nó sẽ được sửa hoặc xóa.
mbomb007
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.