Dizeden tek satır ve çok satırlı yorumları kaldırma


19

Hedef

Seçtiğiniz programlama dilini kullanarak, bir C programını temsil eden bir dizeden yorumları kaldırmak için en kısa programı yazın.


Giriş

Dize herhangi bir girdi biçimi olarak alınabilir, ancak değişken olarak da alınabilir.


Talimatlar

İki farklı yorum kaldırılacaktır:

  • ile başlayan /*ve biten çok satırlı yorumlar*/
  • //Linux tarzı satır kesmeleriyle başlayan ve biten tek satır yorumları (LF, \n)

Dizelerdeki yorumlar silinmez. Bu zorluğun amacı için, yalnızca "ayrılmış dizeleri dikkate almanız gerekir . Özellikle, - 'ayrılmış karakter değişmezleri olasılığını yoksayabilirsiniz . Üçgenleri ve satır devamlarını da ( /\<LF>*...) göz ardı edebilirsiniz .


Örnekler

Giriş:

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

Çıktı:

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

Giriş:

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

Çıktı:

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

    int butNotThis = 42;

    int bar = 4 * 3; 
    return 0;
}

1
Kodun printf("\"/* This will stay too */\"\n");ortaya çıktığı yer nereden gelmeli ?
manatwork

Üzgünüz, sadece bir yazım hatasıydı. Fark ettiğiniz için teşekkürler!
Mathieu Rodic

Beyaz alanlar sayar mı? Önünde // this comment will be removedkaybolan 4 boşluk var . Bunun için herhangi bir kural var mı?
manatwork

1
Listelenen dillerden hiçbirini çok iyi bilmiyorum, bu yüzden bir tür müstakil özellik daha fazla örnekle birlikte güzel olurdu.
Zgarb

@manatwork: boşlukların kaldırılması zorunlu değildir
Mathieu Rodic

Yanıtlar:


11

Retina , 35 + 1 + 2 = 38 bayt

Bu program iki dosyadan oluşur, bu yüzden ikinci dosya için 1 baytlık bir ceza ekledim .

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

Bu, .NET lezzetini kullanan basit bir normal regex yedeğidir (diğer lezzetlerin çoğunda aynı şekilde çalışmasına rağmen).

Fikir hem yorumları hem de dizeleri eşleştirmek, ancak eşleşmeyi yalnızca bir dize ise geri yazmaktır. Dizeleri açıkça eşleştirerek, yorum ararken atlanırlar.


1
PHP'de şaşırtıcı derecede iyi çalışıyor: regex101.com/r/kB5kA4/1
Ismael Miguel

1
@IsmaelMiguel Evet, belirli bir özelliği kullanmadım. Ben .NET seçti tek nedeni Retina gibi bir şey çağırmak yükü olmadan sadece regex programları yazmak için izin çünkü preg_replace.
Martin Ender

Farkındayım. Daha önce çok kullandın. Doğruysam, sizin tarafınızdan yaratıldı. Meraklıydı. Ve ayrıca, şimdi bu soruya gelen değişiklikleri test edebileceğiniz bir test paketiniz var (birçok tahmin ediyorum)
Ismael Miguel

Güzel! Bu normal ifade diğer programlama dilleriyle bile çalışır (eğik çizgilerden kaçıldığında).
Mathieu Rodic

Regex tekniğinizi, birlikte çalıştığım bir üçüncü taraf kütüphanesini geliştirmek için kullandım: Dojo Toolkit
mbomb007

15

Shell + coreutils + gcc derleyici koleksiyonu, 31 bayt

Bu cevap biraz boşluk gibi görünebilir, ancak soruda özellikle yasaklayan hiçbir şey görmedim.

Sakar düzenli ifadeler kullanmak yerine, neden bu iş için tasarlanmış aracı kullanmıyorsunuz? Doğru sonuçları verirken sorun yaşamamalı:

cpp -fpreprocessed -o- -|sed 1d

STDIN'den giriş ve STDOUT'a çıkış alır. Normalde ccptüm önişlemleri (başlık dosyaları, makro genişletme, açıklama kaldırma vb.) Yapar, ancak -fpreprocessedseçenekle adımların çoğunu atlar, ancak yine de yorumları kaldırır. Buna ek olarak, cpp # 1 "<stdin>"çıktının başına benzer bir çizgi ekler , böylece sedonu silmek için oradadır.


1
"Girdi dosyası uzantılarından birini varsa -fpreprocessed örtülü olduğu .i, .iiya da .mi". a.iBayrağı kullanmak yerine dosyayı kaydederek bazı baytları kaydedebilir misiniz ?
Martin Ender

@ MartinBüttner Evet, bunu kılavuzda da fark ettim. Bu yüzden cat>i.i;cpp -o- i.i|sed 1deşdeğer bir şey beklerdim . Ancak tam önişleme sağlanır (örn. Stdio.h'nin tüm içeriği eklenir). Olası gcc hatası ??? Bir mo aldığımda belki de cpp kaynağını kontrol edeceğim.
Dijital Travma

Seçeneği |sed 1deklerseniz kaldırabilirsiniz -P. Önceden işlenmiş kod beklediğinden (soru tarafından izin verildiği gibi), trigrafları veya satır devamlarını düzgün işlemeyeceğini unutmayın.
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;}}

Ungolfed

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 bayt

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

Burada görebileceğiniz gibi normal ifade 2 alternatif yakalama grubundan oluşmaktadır. Birincisi, alıntı yapılan tüm dizeleri yakalar. İkincisi tüm yorumlar.

Tek yapmamız gereken 2. grup tarafından yakalanan her şeyi kaldırmak.

Misal:

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

Asi - 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 + bazı ek açıklamalar:

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'in php için cevabını dönüştürme:

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

artık $strtek ve çok satırlı yorumları kaybetti. Bu, beslemeden önce JSON verilerindeki yorumları çıkarmak için kullanışlıdır json_decode().


Üçlü bir operatör kullanarak bayt sayısını azaltabilirsiniz.
Mathieu Rodic

0

C # (262 karakter):

Bu çok iyi SO cevabından:

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

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.