Supprimer les commentaires d'une seule ligne et multilignes de la chaîne

19

Objectif

En utilisant le langage de programmation de votre choix, écrivez le programme le plus court pour éliminer les commentaires d'une chaîne représentant un programme C.


Contribution

La chaîne peut être considérée comme n'importe quelle forme d'entrée, mais elle peut également être considérée comme une variable.


Instructions

Deux types de commentaires différents doivent être supprimés:

  • commentaires multilignes , commençant par /*et se terminant par*/
  • commentaires sur une seule ligne , commençant //et se terminant par des sauts de ligne de style Linux (LF, \n)

Les commentaires dans les chaînes ne doivent pas être supprimés. Aux fins de ce défi, il vous suffit de considérer les "chaînes délimitées. En particulier, vous pouvez ignorer la possibilité de 'littéraux de caractères délimités. Vous pouvez également ignorer les trigraphes et les continuations de ligne ( /\<LF>*...).


Exemples

Contribution:

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

Production:

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

Contribution:

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

Production:

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

    int butNotThis = 42;

    int bar = 4 * 3; 
    return 0;
}
Mathieu Rodic
la source
1
D'où cela printf("\"/* This will stay too */\"\n");est apparu dans le code devrait devenir ?
manatwork du
Oups, désolé ... c'était juste une faute de frappe. Merci d'avoir remarqué!
Mathieu Rodic
Les espaces blancs comptent-ils? Il y a 4 espaces devant // this comment will be removedlesquels viennent de disparaître. Une règle pour ça?
manatwork du
1
Je ne connais pas bien les langues répertoriées, donc une sorte de spécification autonome serait bien, avec plus d'exemples.
Zgarb
@manatwork: la suppression des espaces blancs n'est pas obligatoire
Mathieu Rodic

Réponses:

11

Rétine , 35 + 1 + 2 = 38 octets

Ce programme se compose de deux fichiers, j'ai donc inclus une pénalité de 1 octet pour le deuxième fichier .

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

Il s'agit d'un simple remplacement d'expression régulière, utilisant la saveur .NET (bien que cela fonctionnerait de la même manière dans la plupart des autres saveurs).

L'idée est de faire correspondre les commentaires et les chaînes, mais de réécrire la correspondance uniquement s'il s'agissait d'une chaîne. En faisant correspondre explicitement les chaînes, elles sont ignorées lors de la recherche de commentaires.

Martin Ender
la source
1
Cela fonctionne étonnamment bien en PHP: regex101.com/r/kB5kA4/1
Ismael Miguel
1
@IsmaelMiguel Oui, je n'ai rien utilisé de spécifique. La seule raison pour laquelle j'ai choisi .NET est parce que Retina me permet d'écrire des programmes uniquement regex sans frais généraux d'appeler quelque chose comme preg_replace.
Martin Ender
Je suis au courant de ça. Vous l'avez déjà beaucoup utilisé auparavant. Si j'ai raison, il a été créé par vous. C'était pour les curieux. Et aussi, vous avez maintenant une suite de tests où vous pouvez tester les changements apportés à cette question (j'en prédis beaucoup)
Ismael Miguel
Agréable! Cette expression régulière fonctionne même avec d'autres langages de programmation (lorsque les barres obliques sont échappées).
Mathieu Rodic
J'ai utilisé votre technique d'expression régulière pour améliorer une bibliothèque tierce avec laquelle je travaille: Dojo Toolkit
mbomb007
15

Collection de compilateurs Shell + Coreutils + GCC, 31 octets

Cette réponse peut sembler un peu échappatoire, mais je n'ai rien vu d'interdire spécifiquement dans la question.

Plutôt que d'utiliser des expressions régulières maladroites, pourquoi ne pas utiliser l'outil qui a été conçu pour le travail. Il ne devrait y avoir aucun problème à donner des résultats corrects:

cpp -fpreprocessed -o- -|sed 1d

Prend l'entrée de STDIN et la sortie vers STDOUT. Normalement, ccpfera tout le prétraitement (fichiers d'en-tête, expansion de macro, suppression de commentaires, etc.), mais avec l' -fpreprocessedoption, il sautera la plupart des étapes, mais il supprimera toujours les commentaires. De plus, cpp ajoute une ligne comme # 1 "<stdin>"au début de la sortie, donc le sedest là pour la supprimer.

Traumatisme numérique
la source
1
"-fpreprocessed est implicite si le fichier d'entrée a l'une des extensions .i, .iiou .mi". pourriez-vous être en mesure d'enregistrer certains octets en enregistrant le fichier dans quelque chose comme a.iau lieu d'utiliser l'indicateur?
Martin Ender
@ MartinBüttner Oui, je l'ai remarqué aussi dans le manuel. Je m'attendrais donc à ce que quelque chose comme cat>i.i;cpp -o- i.i|sed 1déquivalent. Mais un prétraitement complet s'ensuit (par exemple, le contenu complet de stdio.h est inséré). Bug gcc possible ??? Eh bien peut-être que je vérifierai la source cpp quand j'aurai un mo '.
Digital Trauma
Vous pouvez supprimer le |sed 1dsi vous ajoutez l' -Poption. Notez que (comme le permet la question), car il attend du code prétraité, il ne traitera pas correctement les trigraphes ou les continuations de ligne.
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;}}

Non golfé

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;
}
Ilya Gazman
la source
2

Python2 - 163 134 octets

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

Comme vous pouvez le voir ici , l'expression régulière se compose de 2 groupes de capture alternés. La première capture toutes les chaînes citées. Le second tous les commentaires.

Tout ce que nous devons faire, c'est supprimer tout ce qui a été capturé par le 2e groupe.

Exemple:

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;
}
poivre
la source
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]

Non golfé + quelques annotations:

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
]
draegtun
la source
1

PHP

Conversion de la réponse de @Martin Ender pour php:

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

a maintenant $strperdu les commentaires sur une ou plusieurs lignes. Ceci est utile pour supprimer les commentaires dans les données JSON avant de les alimenter json_decode().

centurien
la source
Peut-être pourriez-vous réduire le nombre d'octets en utilisant un opérateur ternaire?
Mathieu Rodic
0

C # (262 caractères):

De cette très bonne réponse 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);
vrluckyin
la source
-1

JS (ES6), 47 caractères (wip)

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

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

Inspiré par mes minificateurs golfiques: http://xem.github.io/miniMinifier/

ne gère pas encore les commentaires dans les chaînes ...

Je suis curieux de voir s'il est possible d'y parvenir dans les expressions régulières JS.

xem
la source
Si cette réponse ne répond pas aux exigences, elle doit être corrigée ou supprimée.
mbomb007