Неожиданное поведение при удалении встроенных комментариев в C - PullRequest
0 голосов
/ 27 февраля 2019

переполнение стека!Я нахожусь на моем процессе обучения с технологией C.У меня есть функция, которая получает входной файл, просматривает файл и записывает содержимое в выходной файл без комментариев.Функция работает, но в некоторых случаях она также тормозит.Моя функция:

    void removeComments(char* input, char* output)
{
    FILE* in = fopen(input,"r");
    FILE* out = fopen(ouput,"w");
    char c;
    while((c = fgetc(in)) != EOF)
    {
       if(c == '/')
       {

          c = fgetc(in);
          if(c == '/')
          {
           while((c = fgetc(in)) != '\n');
          }
          else
          {
            fputc('/', out);
          }
       }
       else
       {
           fputc(c,out);
       }
    }
    fclose(in);
    fclose(out);
}

Но когда я даю такой файл в качестве ввода:

// Parameters: a, the first integer; b the second integer.
// Returns: the sum.
int add(int a, int b) 
{
    return a + b; // An inline comment.
}
int sample = sample;

При удалении встроенного комментария он по какой-то причине не достигает '\ n' иэто дает вывод:

int add(int a, int b) 
{
    return a + b; }
int sample = sample;

[РЕДАКТИРОВАТЬ] Спасибо за помощь мне!Это работает с делом, которое я отправил, но это тормозит в другом.Текущий код:

FILE* in = fopen(input,"r");
FILE* out = fopen(output,"w");

if (in == NULL) {
  printf("cannot read %s\n", input);
  return; /* change signature to return 0 ? */
}
if (out == NULL) {
  printf("cannot write in %s\n", output);
  return; /* change signature to return 0 ? */
}

int c;
int startline = 1;

while((c = fgetc(in)) != EOF)
{
   if(c == '/')
   {
      c = fgetc(in);

      if(c == '/')
      {
        while((c = fgetc(in)) != '\n')
        {
          if (c == EOF) {
            fclose(in);
            fclose(out);
            return; /* change signature to return 1 ? */
          }
        }
        if (! startline)
          fputc('\n', out);
        startline = 1;
      }
      else if (c == EOF)
        break;
      else {
        fputc('/', out);
        startline = 0;
      }
   }
   else
   {
     fputc(c,out);
     startline = (c == '\n');
   }
}

fclose(in);
fclose(out);

Когда файл содержит разделение, вторая переменная исчезает.Пример:

int divide(int a, int b) 
    {
        return a/b; 
    }

Возвращает:

int divide(int a, int b) 
    {
        return a/; 
    }

Ответы [ 2 ]

0 голосов
/ 27 февраля 2019

При удалении встроенного комментария он по какой-то причине не может достичь '\ n'

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

Рассмотрим код, принимающий комментарии:

           while((c = fgetc(in)) != '\n');

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

Дополнительные примечания:

  1. fgetc возвращает int, а не char, и вам необходимо обращаться с ним как таковым, чтобы иметь возможность правильно определять конец файла.

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

0 голосов
/ 27 февраля 2019

после

while((c = fgetc(in)) != '\n');

вам нужно fputc('\n', out);

Дополнительные замечания:

В

char c;
while((c = fgetc(in)) != EOF)

c должен быть int для управления EOF

Просто опечатка: ouput должен быть output для компиляции

Вы делаетеплохо управляет EOF после прочтения '/'

Вы пропустили проверку результата fopen


Предложение:

#include <stdio.h>

void removeComments(char* input, char* output)
{
    FILE* in = fopen(input,"r");
    FILE* out = fopen(output,"w");

    if (in == NULL) {
      printf("cannot read %s\n", input);
      return; /* change signature to return 0 ? */
    }
    if (out == NULL) {
      printf("cannot write in %s\n", output);
      return; /* change signature to return 0 ? */
    }

    int c;

    while((c = fgetc(in)) != EOF)
    {
       if(c == '/')
       {
          c = fgetc(in);

          if(c == '/')
          {
            while((c = fgetc(in)) != '\n')
            {
              if (c == EOF) {
                fclose(in);
                fclose(out);
                return; /* change signature to return 1 ? */
              }
            }
            fputc('\n', out);
          }
          else if (c == EOF) {
            fputc('/', out);
            break;
          }
          else
            fputc('/', out);
            fputc(c, out);
       }
       else
       {
         fputc(c,out);
       }
    }

    fclose(in);
    fclose(out);
     /* change signature to return 1 ? */
}

int main(int argc, char ** argv)
{
  removeComments(argv[1], argv[2]);
}

Как говорит Тормунд Джайентсбэйн в своем замечании, лучше полностью удалить строку, содержащую только комментарий (комментарий, начинающийся с первого столбца), это новое предложение:

#include <stdio.h>

void removeComments(char* input, char* output)
{
    FILE* in = fopen(input,"r");
    FILE* out = fopen(output,"w");

    if (in == NULL) {
      printf("cannot read %s\n", input);
      return; /* change signature to return 0 ? */
    }
    if (out == NULL) {
      printf("cannot write in %s\n", output);
      return; /* change signature to return 0 ? */
    }

    int c;
    int startline = 1;

    while((c = fgetc(in)) != EOF)
    {
       if(c == '/')
       {
          c = fgetc(in);

          if(c == '/')
          {
            while((c = fgetc(in)) != '\n')
            {
              if (c == EOF) {
                fclose(in);
                fclose(out);
                return; /* change signature to return 1 ? */
              }
            }
            if (! startline)
              fputc('\n', out);
            startline = 1;
          }
          else if (c == EOF) {
            fputc('/', out);
            break;
          }
          else {
            fputc('/', out);
            fputc(c, out);
            startline = 0;
          }
       }
       else
       {
         fputc(c,out);
         startline = (c == '\n');
       }
    }

    fclose(in);
    fclose(out);
     /* change signature to return 1 ? */
}

int main(int argc, char ** argv)
{
  removeComments(argv[1], argv[2]);
}

Компиляция и исполнение:

pi@raspberrypi:/tmp $ gcc -pedantic -Wextra -g r.c
pi@raspberrypi:/tmp $ cat i
// Parameters: a, the first integer; b the second integer.
// Returns: the sum.
int add(int a, int b) 
{
    return a + b/c; // An inline comment.
}
int sample = sample;
pi@raspberrypi:/tmp $ ./a.out i o
pi@raspberrypi:/tmp $ cat o
int add(int a, int b) 
{
    return a + b/c; 
}
int sample = sample;

Как сказал DavidC.в примечании, если // помещен в строку, результат не будет ожидаемым, это также имеет место в символе, даже недопустимом (я имею в виду, что «//» не должен быть изменен), как насчет комментариев C (/* .. // ... * /) и т. д.

...