81 votes

Supprimer les commentaires du code C/C++

Existe-t-il un moyen facile de supprimer les commentaires d'un fichier source C/C++ sans effectuer de prétraitement (par exemple, je pense que vous pouvez utiliser gcc -E mais cela développera les macros). (Je pense que vous pouvez utiliser gcc -E mais cela développera les macros.) Je veux juste le code source avec les commentaires, rien d'autre ne doit être modifié.

EDIT :

Préférence pour un outil existant. Je ne veux pas avoir à écrire cela moi-même avec des regex, je prévois trop de surprises dans le code.

5 votes

Il s'agit en fait d'un bon exercice pour utiliser un lexer et un analyseur syntaxique simples !

0 votes

Devons-nous nous attendre à des astuces comme /* dans des commentaires ou des chaînes de caractères ?

59 votes

Il s'agit en fait d'un bon exercice pour utiliser un lexer et un analyseur syntaxique très compliqués.

114voto

Josh Lee Points 53741

Exécutez la commande suivante sur votre fichier source :

gcc -fpreprocessed -dD -E test.c

Merci à KennyTM pour avoir trouvé les bons drapeaux. Voici le résultat pour être complet :

test.c :

#define foo bar
foo foo foo
#ifdef foo
#undef foo
#define foo baz
#endif
foo foo
/* comments? comments. */
// c++ style comments

gcc -fpreprocessed -dD -E test.c :

#define foo bar
foo foo foo
#ifdef foo
#undef foo
#define foo baz
#endif
foo foo

3 votes

Je pense que le résultat attendu par Mike est #define foo bar\nfoo foo foo

3 votes

@Pascal : Cours gcc -fpreprocessed -dM -E test.c pour obtenir le #define -mais ils ne sont pas dans les emplacements originaux.

15 votes

J'ai ajouté -P aux options de gcc pour supprimer les marqueurs de ligne bizarres qui apparaissent parfois lorsque les commentaires de début de fonction sont supprimés.

15voto

Jonathan Leffler Points 299946

Cela dépend de la perversité de vos propos. J'ai un programme scc pour dépouiller les commentaires C et C++. J'ai également un fichier de test pour cela, et j'ai essayé GCC (4.2.1 sur MacOS X) avec les options de la réponse actuellement sélectionnée - et GCC ne semble pas faire un travail parfait sur certains des commentaires horriblement massacrés dans le cas de test.

NB : Il ne s'agit pas d'un problème réel - les gens n'écrivent pas un code aussi épouvantable.

Considérons le (sous-ensemble - 36 des 135 lignes au total) du scénario de test :

/\
*\
Regular
comment
*\
/
The regular C comment number 1 has finished.

/\
\/ This is not a C++/C99 comment!

This is followed by C++/C99 comment number 3.
/\
\
\
/ But this is a C++/C99 comment!
The C++/C99 comment number 3 has finished.

/\
\* This is not a C or C++ comment!

This is followed by regular C comment number 2.
/\
*/ This is a regular C comment *\
but this is just a routine continuation *\
and that was not the end either - but this is *\
\
/
The regular C comment number 2 has finished.

This is followed by regular C comment number 3.
/\
\
\
\
* C comment */

Sur mon Mac, la sortie de GCC ( gcc -fpreprocessed -dD -E subset.c ) est :

/\
*\
Regular
comment
*\
/
The regular C comment number 1 has finished.

/\
\/ This is not a C++/C99 comment!

This is followed by C++/C99 comment number 3.
/\
\
\
/ But this is a C++/C99 comment!
The C++/C99 comment number 3 has finished.

/\
\* This is not a C or C++ comment!

This is followed by regular C comment number 2.
/\
*/ This is a regular C comment *\
but this is just a routine continuation *\
and that was not the end either - but this is *\
\
/
The regular C comment number 2 has finished.

This is followed by regular C comment number 3.
/\
\
\
\
* C comment */

La sortie de 'scc' est :

The regular C comment number 1 has finished.

/\
\/ This is not a C++/C99 comment!

This is followed by C++/C99 comment number 3.
/\
\
\
/ But this is a C++/C99 comment!
The C++/C99 comment number 3 has finished.

/\
\* This is not a C or C++ comment!

This is followed by regular C comment number 2.

The regular C comment number 2 has finished.

This is followed by regular C comment number 3.

La sortie de 'scc -C' (qui reconnaît les commentaires à double barre oblique) est la suivante :

The regular C comment number 1 has finished.

/\
\/ This is not a C++/C99 comment!

This is followed by C++/C99 comment number 3.

The C++/C99 comment number 3 has finished.

/\
\* This is not a C or C++ comment!

This is followed by regular C comment number 2.

The regular C comment number 2 has finished.

This is followed by regular C comment number 3.

Les sources de la SCC sont désormais disponibles sur GitHub

La version actuelle de SCC est 6.60 (datée du 2016-06-12), bien que les versions Git aient été créées le 2017-01-18 (dans le fuseau horaire US/Pacifique). Le code est disponible sur GitHub à l'adresse suivante https://github.com/jleffler/scc-snapshots . Vous pouvez également trouver des instantanés des versions précédentes (4.03, 4.04, 5.05) et deux préversions (6.16, 6.50) - ils sont tous étiquetés release/x.yz .

Le code est encore principalement développé sous RCS. Je suis encore en train de travailler sur la façon dont je veux utiliser les sous-modules ou un mécanisme similaire pour gérer les fichiers de la bibliothèque commune tels que stderr.c et stderr.h (que l'on peut également trouver dans https://github.com/jleffler/soq ).

La version 6.60 de SCC tente de comprendre les constructions C++11, C++14 et C++17 telles que les constantes binaires, la ponctuation numérique, les chaînes de caractères brutes et les flottants hexadécimaux. Il fonctionne par défaut en mode C11. (Notez que la signification de la balise -C le drapeau - mentionné ci-dessus - a basculé entre la version 4.0x décrite dans le corps de la réponse et la version 6.60 qui est actuellement la dernière version).

5 votes

Croyez-moi, Jonathan, ils le font. J'ai nettoyé le code et il y avait 2000 lignes de code qui étaient commentées. Je n'arrivais pas à croire qu'un être humain puisse écrire un code aussi désordonné.

0 votes

Pourriez-vous publier ce programme et donner le lien ici s'il vous plaît ? (si c'est un logiciel libre/libre)

0 votes

@Totor : C'est un logiciel libre/libre (GPL v3 par défaut). Envoyez-moi un email et je l'enverrai (mon adresse email est dans mon profil). Je n'ai tout simplement pas d'endroit où publier ce genre de code de façon régulière (pathétique, n'est-ce pas !).

8voto

lhf Points 30556

Gcc -fpreprocessed -dD -E ne fonctionnait pas pour moi mais ce programme le fait :

#include <stdio.h>

static void process(FILE *f)
{
 int c;
 while ( (c=getc(f)) != EOF )
 {
  if (c=='\'' || c=='"')            /* literal */
  {
   int q=c;
   do
   {
    putchar(c);
    if (c=='\\') putchar(getc(f));
    c=getc(f);
   } while (c!=q);
   putchar(c);
  }
  else if (c=='/')              /* opening comment ? */
  {
   c=getc(f);
   if (c!='*')                  /* no, recover */
   {
    putchar('/');
    ungetc(c,f);
   }
   else
   {
    int p;
    putchar(' ');               /* replace comment with space */
    do
    {
     p=c;
     c=getc(f);
    } while (c!='/' || p!='*');
   }
  }
  else
  {
   putchar(c);
  }
 }
}

int main(int argc, char *argv[])
{
 process(stdin);
 return 0;
}

7 votes

Ne gère pas les trigraphes.

7voto

che Points 6899

Il existe un stripcmt programme qui peut le faire :

StripCmt est un utilitaire simple écrit en C pour supprimer les commentaires des fichiers sources C, C++ et Java. Dans la grande tradition des programmes de traitement de texte Unix, il peut fonctionner comme un filtre FIFO (First In - First Out) ou accepter des arguments sur la ligne de commande.

(par hlovdal la réponse de l'entreprise : question sur le code Python pour ceci )

1 votes

Le code comporte encore quelques bogues. Par exemple, il ne peut pas gérer un code comme int /* comment // */ main() .

0 votes

Et présentent des bogues lors de la gestion de commentaires tels que // comment out next line \

0 votes

ma réponse gère ces cas. Cela fonctionne parfaitement, tant que /* , // , */ ne sont pas divisés en deux lignes.

4voto

Vladimir Points 21

Il s'agit d'un script perl pour supprimer les commentaires //à une ligne et /* multi-lignes */.

  #!/usr/bin/perl

  undef $/;
  $text = <>;

  $text =~ s/\/\/[^\n\r]*(\n\r)?//g;
  $text =~ s/\/\*+([^*]|\*(?!\/))*\*+\///g;

  print $text;

Il requiert votre fichier source comme argument de ligne de commande. Enregistrez le script dans un fichier, disons remove_comments.pl et appelez-le en utilisant la commande suivante : perl -w remove_comments.pl [votre fichier source].

J'espère que cela vous sera utile

2 votes

Ne semble pas traiter les chaînes contenant "/*" ou "//" etc. dans le terrier du lapin.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X