Supprimer les commentaires du code C / C++

est-il un moyen facile de supprimer des commentaires d'un fichier source c/" class="blnk">C/C++ sans faire de prétraitement. (c'est-à-dire, je pense que vous pouvez utiliser gcc-E mais cela va étendre les macros.) Je veux juste que le code source avec les commentaires soit effacé, rien d'autre ne devrait être changé.

EDIT:

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

59
demandé sur Mike 2010-03-06 23:29:08

11 réponses

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
85
répondu Josh Lee 2015-07-11 20:20:25

cela dépend de la perversité de vos commentaires. J'ai un programme scc pour supprimer les commentaires C et C++. J'ai aussi un fichier de test pour cela, et J'ai essayé GCC (4.2.1 sur MacOS X) avec les options dans 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: ce n'est pas un problème réel-les gens n'écrivent pas un tel code épouvantable.

considérer le (sous-ensemble - 36 sur un total de 135 lignes) du cas d'essai:

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

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.

Source pour SCC maintenant disponible sur GitHub

la version actuelle la CCN est de 6,60 (date de 2016-06-12), bien que les versions Git aient été créées le 2017-01-18 (dans le fuseau horaire États-Unis/Pacifique). Le code est disponible chez GitHub à 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) - ce sont tous marqués release/x.yz .

le code est encore principalement élaboré dans le cadre du SCR. Je travaille encore sur comment je veux utiliser sous-modules ou un mécanisme similaire pour traiter les fichiers de bibliothèque communs comme stderr.c et stderr.h (qui peut également être trouvé dans https://github.com/jleffler/soq ).

SCC version 6.60 tente de comprendre C++11, C++14 et c++17 constructions telles que les constantes binaires, la ponctuation numérique, les chaînes brutes, et les flotteurs hexadécimaux. Il fonctionne par défaut en mode C11. (Notez que le sens du drapeau -C - mentionné ci-dessus-s'est inversé entre la version 4.0 x décrit dans le corps de la réponse et la version 6.60 qui est actuellement la dernière version.)

11
répondu Jonathan Leffler 2017-01-19 06:14:56

gcc-fpreprocessed -dD-E n'a pas de travail pour moi, mais ce programme, il 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
répondu lhf 2010-03-07 03:14:47

il y a un programme stripcmt qui peut faire ceci:

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

(par hlovdal 's réponse à: question sur le code Python pour ce )

6
répondu che 2017-05-23 12:18:07

C'est un script perl permettant de supprimer //une ligne et /* multi-ligne */ commentaires

  #!/usr/bin/perl

  undef $/;
  $text = <>;

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

  print $text;

il nécessite votre fichier source comme argument de ligne de commande. Enregistrez le script dans un fichier, disons remove_comments.pl et l'appeler en utilisant la commande suivante: perl-w remove_comments.pl [votre fichier source]

l'Espoir qu'il sera utile

4
répondu Vladimir 2012-08-15 13:03:16

j'ai eu ce problème aussi. J'ai trouvé cet outil ( Cpp-Decomment ) , qui a fonctionné pour moi. Cependant il ignore si la ligne de commentaire s'étend à la ligne suivante. Par exemple:

// this is my comment \
comment continues ...

dans ce cas, je n'ai pas pu trouver un moyen dans le programme alors j'ai juste cherché des lignes ignorées et corrigé manuellement. Je pense qu'il y aurait une option pour ça ou peut-être que vous pourriez changer le fichier source du programme pour le faire.

2
répondu Halil Kaskavalci 2012-09-25 20:32:28

je crois que si vous utilisez une déclaration, vous pouvez facilement supprimer les commentaires de C

perl -i -pe ‘s/\\*(.*)/g’ file.c This command Use for removing * C style comments 
perl -i -pe 's/\\(.*)/g' file.cpp This command Use for removing \ C++ Style Comments

seul problème avec cette commande il ne peut supprimer les commentaires qui contiennent plus d'une ligne.mais en utilisant ce regEx vous pouvez facilement mettre en œuvre la logique pour Multiline supprimer les commentaires

0
répondu Poseidon_Geek 2012-08-08 18:38:23

récemment, j'ai écrit un code Ruby pour résoudre ce problème. J'ai considéré les exceptions suivantes:

  • commentaire dans les chaînes
  • commentaire de ligne multiple sur une ligne, Correction match gourmand.
  • lignes multiples sur lignes multiples

voici le code: Github, supprimer les commentaires

il utilise le code suivant pour pré-traiter chaque ligne au cas où ces commentaires apparaissent dans les chaînes. Si ça apparaît dans votre code, euh, pas de chance. Vous pouvez le remplacer par des chaînes plus complexes.

  • MUL_REPLACE_LEFT = " MUL_REPLACE_LEFT
  • MUL_REPLACE_RIGHT = MUL_REPLACE_RIGHT
  • SIG_REPLACE = " SIG_REPLACE

Usage: ruby-w inputfile outputfile

0
répondu chunyang.wen 2014-04-24 01:25:10

parce que vous utilisez C, vous pourriez vouloir utiliser quelque chose qui est" naturel " à C. Vous pouvez utiliser le préprocesseur C pour simplement supprimer les commentaires. Les exemples ci-dessous fonctionnent avec le préprocesseur C de GCC. Ils devraient fonctionner de la même manière ou de manière similaire avec d'autres processeurs de processeur.

pour C, utiliser

cpp -dD -fpreprocessed -o output.c input.c

il fonctionne également pour supprimer les commentaires de JSON, par exemple comme ceci:

cpp -P -o - - <input.json >output.json

au cas où votre le préprocesseur n'est pas directement accessible, vous pouvez essayer de remplacer cpp par cc -E , qui appelle le compilateur C lui disant de s'arrêter après l'étape du préprocesseur. Si votre binaire de compilateur C n'est pas cc , vous pouvez remplacer cc par le nom de votre binaire de compilateur C, par exemple clang . Notez que tous les préprocesseurs ne supportent pas -fpreprocessed .

0
répondu Christian Hujer 2017-05-08 11:35:17

je sais qu'il est tard, mais j'ai pensé partager mon code et ma première tentative d'écrire un compilateur.

Note: Ceci ne tient pas compte de "\*/" dans un commentaire multiligne.g /\*...."*/"...\* . Mais encore une fois, gcc 4.8.1 ne le fait pas non plus.

void function_removeComments(char *pchar_sourceFile, long long_sourceFileSize)
{
    long long_sourceFileIndex = 0;
    long long_logIndex = 0;

    int int_EOF = 0;

    for (long_sourceFileIndex=0; long_sourceFileIndex < long_sourceFileSize;long_sourceFileIndex++)
    {
        if (pchar_sourceFile[long_sourceFileIndex] == '/' && int_EOF == 0)
        {
            long_logIndex = long_sourceFileIndex;  // log "possible" start of comment

            if (long_sourceFileIndex+1 < long_sourceFileSize)  // array bounds check given we want to peek at the next character
            {
                if (pchar_sourceFile[long_sourceFileIndex+1] == '*') // multiline comment
                {
                    for (long_sourceFileIndex+=2;long_sourceFileIndex < long_sourceFileSize; long_sourceFileIndex++)
                    {
                        if (pchar_sourceFile[long_sourceFileIndex] == '*' && pchar_sourceFile[long_sourceFileIndex+1] == '/')
                        {
                            // since we've found the end of multiline comment
                            // we want to increment the pointer position two characters
                            // accounting for "*" and "/"
                            long_sourceFileIndex+=2;  

                            break;  // terminating sequence found
                        }
                    }

                    // didn't find terminating sequence so it must be eof.
                    // set file pointer position to initial comment start position
                    // so we can display file contents.
                    if (long_sourceFileIndex >= long_sourceFileSize)
                    {
                        long_sourceFileIndex = long_logIndex;

                        int_EOF = 1;
                    }
                }
                else if (pchar_sourceFile[long_sourceFileIndex+1] == '/')  // single line comment
                {
                    // since we know its a single line comment, increment file pointer
                    // until we encounter a new line or its the eof 
                    for (long_sourceFileIndex++; pchar_sourceFile[long_sourceFileIndex] != '\n' && pchar_sourceFile[long_sourceFileIndex] != '"151900920"'; long_sourceFileIndex++);
                }
            }
        }

        printf("%c",pchar_sourceFile[long_sourceFileIndex]);
     }
 }
-1
répondu johnny 2016-01-28 03:36:56
#include<stdio.h>
{        
        char c;
        char tmp = '"151900920"';
        int inside_comment = 0;  // A flag to check whether we are inside comment
        while((c = getchar()) != EOF) {
                if(tmp) {
                        if(c == '/') {
                                while((c = getchar()) !='\n');
                                tmp = '"151900920"';
                                putchar('\n');
                                continue;
                        }else if(c == '*') {
                                inside_comment = 1;
                                while(inside_comment) {
                                        while((c = getchar()) != '*');
                                        c = getchar();
                                        if(c == '/'){
                                                tmp = '"151900920"';
                                                inside_comment = 0;
                                        }
                                }
                                continue;
                        }else {
                                putchar(c);
                                tmp = '"151900920"';
                                continue;
                        }
                }
                if(c == '/') {
                        tmp = c;
                } else {
                        putchar(c);
                }
        }
        return 0;
}

ce programme fonctionne pour les deux conditions I. e / / and / ..... /

-3
répondu Vivek Patel 2013-07-02 10:57:59