Удаление комментариев из кода C / C++



есть ли простой способ удалить комментарии из исходного файла C/C++ без предварительной обработки. (т. е., я думаю, вы можете использовать gcc-E, но это расширит макросы.) Я просто хочу, чтобы исходный код с комментариями был удален, больше ничего не нужно менять.



EDIT:



предпочтение по отношению к существующему инструменту. Я не хочу писать это сам с помощью регулярных выражений, я предвижу слишком много сюрпризов в коде.

1171   11  

11 ответов:

выполните следующую команду в исходном файле:

gcc -fpreprocessed -dD -E test.c

спасибо KennyTM за поиск правильных флагов. Вот результат для полноты картины:

это зависит от того, насколько извращенными являются ваши комментарии. У меня есть программа scc чтобы удалить комментарии C и c++. У меня также есть тестовый файл для него, и я попробовал GCC (4.2.1 на MacOS X) с параметрами в выбранном в данный момент ответе - и GCC, похоже, не делает идеальную работу над некоторыми ужасно вырезанными комментариями в тестовом случае.

NB: это не реальная проблема-люди не пишут такой ужасный код.

рассмотрим (подмножество - 36 из 135 строк) из тестовый случай:

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

на моем Mac, выход из GCC(GCC-fpreprocessed-DD-e подмножество.с):

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

выход из ' scc ' является:

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.

вывод из ' scc-C '(который распознает комментарии с двойной косой чертой):

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.

источник для SCC теперь доступен на GitHub

текущая версия SCC - 6.60 (датирована 2016-06-12), хотя версии Git были созданы в 2017-01-18 (в часовом поясе США/Тихого океана). Код доступен из GitHub по адресуhttps://github.com/jleffler/scc-snapshots вы также можете найти снимки предыдущих релизов (4.03, 4.04, 5.05) и двух предварительных релизов (6.16, 6.50)-все они помечены release/x.yz.

код по-прежнему в основном разрабатывается под RCS. Я все еще работаю над тем, как я хочу использовать субмодули или аналогичный механизм для обработки общих файлов библиотеки, таких как stderr.c и stderr.h (который также можно найти в https://github.com/jleffler/soq).

SCC версии 6.60 пытается понять C++11, C++14 и C++17 конструкции, такие как двоичные константы, числовые знаки препинания, необработанные строки и шестнадцатеричные поплавки. Он по умолчанию работает в режиме C11. (Обратите внимание, что значение -C флаг-упомянутый выше-перевернутый между версией 4.0 x, описанной в основном тексте ответа, и версией 6.60, которая в настоящее время является последней версией.)

gcc-fpreprocessed -dD-E не работает для меня, но эта программа делает это:

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

есть stripcmt программа, чем может это сделать:

StripCmt-это простая утилита, написанная на языке C для удаления комментариев из исходных файлов C, C++ и Java. В великой традиции программ обработки текста Unix он может функционировать либо как фильтр FIFO (First In - First Out), либо принимать аргументы в командной строке.

(за hlovdal ' s ответ на: вопрос о коде Python для этого)

это скрипт perl для удаления / / однострочных и / * многострочных * / комментариев

  #!/usr/bin/perl

  undef $/;
  $text = <>;

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

  print $text;

требуется исходный файл в качестве аргумента командной строки. Сохраните скрипт в файл, скажем remove_comments.pl и вызовите его с помощью следующей команды: perl-w remove_comments.pl [ваш исходный файл]

надеюсь, что это будет полезным

У меня тоже была эта проблема. Я нашел этот инструмент (Cpp-Decomment) , который работал для меня. Однако он игнорирует, если строка комментария распространяется на следующую строку. Например:

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

в этом случае я не мог найти способ в программе, поэтому просто искал игнорируемые строки и исправлял вручную. Я считаю, что для этого есть вариант или, возможно, вы можете изменить исходный файл программы для этого.

Я считаю, что если вы используете один оператор, вы можете легко удалить комментарии из 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

только проблема с этой командой он не может удалить комментарии, которые содержат более одной строки.но с помощью этого регулярного выражения вы можете легко реализовать логику для многострочного удаления комментариев

недавно я написал код Ruby, чтобы решить эту проблему. Я рассмотрел следующие исключения:

  • комментарии в строки
  • несколько строк комментарий на одной строке, исправить жадный матч.
  • несколько строк в несколько строк

вот код:Github, удалить комментарии

Он использует следующий код для обработки каждой строки в случае, если эти комментарии отображаются в строках. Если он появится в вашем коде, ЭМ, плохо удача. Вы можете заменить его более сложными строками.

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

использование: ruby-w inputfile outputfile

поскольку вы используете C, вы можете использовать что-то "естественное" для C. Вы можете использовать препроцессор C, чтобы просто удалить комментарии. Приведенные ниже примеры работают с препроцессором C из GCC. Они должны работать так же или аналогично с другими c-перпроцессорами.

для C, используйте

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

он также работает для удаления комментариев из JSON, например, так:

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

в случае, если ваш препроцессор C не доступен напрямую, вы можете попробовать заменить cpp С cc -E, который вызывает компилятор C, сообщающий ему остановиться после этапа препроцессора. В случае, если ваш двоичный код компилятора C не cc вы можете заменить cc С именем вашего двоичного кода компилятора C, например clang. Обратите внимание, что не все препроцессоры поддерживают -fpreprocessed.

Я знаю, что уже поздно, но я думал, что поделюсь своим кодом и моей первой попыткой написать компилятор.

Примечание: это не учитывает "\*/" внутри многострочного комментария, например /\*...."*/"...\*. Опять же, gcc 4.8.1 тоже не делает.

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] != ''; long_sourceFileIndex++);
                }
            }
        }

        printf("%c",pchar_sourceFile[long_sourceFileIndex]);
     }
 }
#include<stdio.h>
{        
        char c;
        char tmp = '';
        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 = '';
                                putchar('\n');
                                continue;
                        }else if(c == '*') {
                                inside_comment = 1;
                                while(inside_comment) {
                                        while((c = getchar()) != '*');
                                        c = getchar();
                                        if(c == '/'){
                                                tmp = '';
                                                inside_comment = 0;
                                        }
                                }
                                continue;
                        }else {
                                putchar(c);
                                tmp = '';
                                continue;
                        }
                }
                if(c == '/') {
                        tmp = c;
                } else {
                        putchar(c);
                }
        }
        return 0;
}

эта программа работает для обоих условий, т. е. / / и/...../

Comments

    Ничего не найдено.