Hapus satu baris dan komentar multiline dari string


19

Tujuan

Dengan menggunakan bahasa pemrograman pilihan Anda, tulislah program terpendek untuk menghilangkan komentar dari string yang mewakili program C.


Memasukkan

String dapat diambil sebagai bentuk input apa pun, tetapi juga dapat dianggap sebagai variabel.


Instruksi

Dua jenis komentar harus dihapus:

  • komentar multiline , dimulai dengan /*dan diakhiri dengan*/
  • komentar satu baris , dimulai dengan //dan diakhiri dengan jeda baris bergaya Linux (LF, \n)

Komentar dalam string tidak harus dihapus. Untuk tujuan tantangan ini, Anda hanya perlu mempertimbangkan "string -ditedit. Secara khusus, Anda dapat mengabaikan kemungkinan 'karakter literal -delimited. Anda juga dapat mengabaikan trigraph dan garis lanjutan ( /\<LF>*...).


Contohnya

Memasukkan:

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

Keluaran:

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

Memasukkan:

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

Keluaran:

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

    int butNotThis = 42;

    int bar = 4 * 3; 
    return 0;
}

1
Dari mana yang printf("\"/* This will stay too */\"\n");muncul di harus menjadi kode?
manatwork

Ups, maaf ... itu hanya salah ketik. Terima kasih telah memperhatikan!
Mathieu Rodic

Apakah spasi putih dihitung? Ada 4 ruang di depan // this comment will be removedyang hilang begitu saja. Adakah aturan untuk itu?
manatwork

1
Saya tidak tahu bahasa yang terdaftar dengan baik, jadi semacam spesifikasi mandiri akan menyenangkan, bersama dengan lebih banyak contoh.
Zgarb

@manatwork: penghapusan spasi tidak wajib
Mathieu Rodic

Jawaban:


11

Retina , 35 + 1 + 2 = 38 byte

Program ini terdiri dari dua file, oleh karena itu saya telah memasukkan penalti 1 byte untuk file kedua .

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

Ini adalah penggantian regex sederhana, menggunakan rasa .NET (meskipun ini akan bekerja sama di sebagian besar rasa lain).

Idenya adalah untuk mencocokkan komentar dan string, tetapi hanya menulis pertandingan kembali jika itu adalah string. Dengan mencocokkan string secara eksplisit, mereka dilewati saat mencari komentar.


1
Ini bekerja dengan sangat baik di PHP: regex101.com/r/kB5kA4/1
Ismael Miguel

1
@ IsmaelMiguel Ya, saya tidak menggunakan fitur spesifik apa pun. Satu-satunya alasan saya memilih .NET adalah karena Retina memungkinkan saya untuk menulis program hanya-regex tanpa ada biaya panggilan seperti preg_replace.
Martin Ender

Saya sadar akan hal itu. Anda telah menggunakannya cukup banyak sebelumnya. Jika saya benar, itu dibuat oleh Anda. Itu untuk yang penasaran. Dan juga, Anda sekarang memiliki test-suite di mana Anda dapat menguji perubahan apa pun yang muncul dalam pertanyaan ini (saya perkirakan banyak)
Ismael Miguel

Bagus! Ekspresi reguler ini bahkan berfungsi dengan bahasa pemrograman lain (ketika garis miring diloloskan).
Mathieu Rodic

Saya menggunakan teknik regex Anda untuk meningkatkan perpustakaan pihak ketiga yang saya kerjakan: Dojo Toolkit
mbomb007

15

Koleksi shell + coreutils + gcc, 31 byte

Jawaban ini mungkin tampak agak loopholey, tetapi saya tidak melihat sesuatu yang secara khusus melarangnya dalam pertanyaan.

Daripada menggunakan ekspresi reguler yang canggung, mengapa tidak menggunakan alat yang dibangun untuk pekerjaan itu. Seharusnya tidak ada masalah dalam memberikan hasil yang benar:

cpp -fpreprocessed -o- -|sed 1d

Mengambil input dari STDIN dan output ke STDOUT. Biasanya ccpakan melakukan semua preprocessing (file header, ekspansi makro, penghapusan komentar, dll), tetapi dengan -fpreprocessedopsi ini, ia akan melewati sebagian besar langkah, tetapi masih akan menghapus komentar. Selain itu, cpp menambahkan garis seperti # 1 "<stdin>"ke awal output, sehingga sedada untuk menghapusnya.


1
"-proses diproses secara implisit jika file input memiliki salah satu ekstensi .i, .iiatau .mi". mungkin Anda bisa menyimpan beberapa byte dengan menyimpan file di sesuatu seperti a.idaripada menggunakan flag?
Martin Ender

@ MartinBüttner Ya, saya perhatikan itu di manual juga. Jadi saya berharap sesuatu yang cat>i.i;cpp -o- i.i|sed 1dsetara. Tetapi proses preproses penuh terjadi (misalnya, isi stdio.h lengkap dimasukkan). Kemungkinan bug gcc ??? Yah mungkin saya akan memeriksa sumber cpp ketika saya mendapatkan mo '.
Digital Trauma

Anda dapat menghapus |sed 1djika Anda menambahkan -Popsi. Perhatikan bahwa (sebagaimana diizinkan oleh pertanyaan), karena ia mengharapkan kode pra-diproses, ia tidak akan menangani trigraph atau kelanjutan garis dengan benar.
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;}}

Tidak disatukan

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

Seperti yang Anda lihat di sini , regex terdiri dari 2 kelompok penangkapan bergantian. Yang pertama menangkap semua string yang dikutip. Yang kedua semua komentar.

Yang perlu kita lakukan adalah menghapus semua yang ditangkap oleh grup ke-2.

Contoh:

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

Rebol - 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]

Tidak dikumpulkan + beberapa anotasi:

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

Konversi jawaban @Martin Ender untuk php:

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

sekarang $strtelah kehilangan komentar single dan multi-line. Ini berguna untuk menghapus komentar dalam data JSON sebelum diumpankan ke json_decode().


Mungkin Anda bisa mengurangi jumlah byte dengan menggunakan operator ternary?
Mathieu Rodic

0

C # (262 karakter):

Dari jawaban SO yang sangat bagus ini :

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);

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.