Удалить комментарии на Си

Необходима функция для удаления комментариев из файла. Всё что между /* и */ включая эти символы. Вот написал что-то, но не пойму как удалять.

#include <stdlib.h>
#include <conio.h>
#include <stdio.h>
#include <math.h>
#include <locale.h>
#include <string.h>

int main()
{
    setlocale(LC_ALL, "rus");

    FILE *code;
    code = fopen_s("code.txt", "w+");

    if ((fopen_s("code.txt", "w+")) == NULL)
    {
        printf("Не удалось открыть файл");
        getchar();
        return 0;
    }
    else
    {
        printf("Файл открыт");
    }
    
    char stroka[100];
    char string1[30] = { "/*" };
    char string2[30] = { "*/" };

    while (feof(code) == 0)
    {
        
    }
    fclose(code);
    _getch();
    return 0;
}

Ответы (2 шт):

Автор решения: Павел Ериков

Вот пример кода с комментариями:

#include <stdlib.h>
#include <conio.h>
#include <stdio.h>
#include <math.h>
#include <locale.h>
#include <string.h>

int main()
{
    setlocale(LC_ALL, "rus");
    FILE* code;
    //Открываем основной файл
    code = fopen("code.txt", "r");
    FILE* temp;
    //Открываем временной файл
    temp = fopen("temp.txt", "w");

    //Если основной файл не был открыт 
    //возвращаем ошибку 1
    if (code == NULL) {
        printf("Не удалось открыть файл");
        getchar();
        return 1;
    }
    else {
        printf("Файл открыт");
    }

    char c;
    c = fgetc(code);
    //Кол-во /* если count == 0 то мы еще не нашли 
    //начало комментария если >= 1 то не записываем все
    //что между первым началом и последним концом комментария
    int count = 0;
    while (feof(code) == 0)
    {
        //Находим начало /* - / или */ - *
        while (feof(code) == 0 && c != '/' && c != '*') {
            //Если count == 0 то вносим символ во временной файл
            if(count == 0)
                fputc(c, temp);
            //Считываем очередной символ
            c = fgetc(code);
        }
        //Если мы нашли начало /*
        if (c == '/') {
            //и второй символ == *, увеличиваем кол-во комментариев
            if ((c = fgetc(code)) == '*')
                ++count;
            //если после / не идет * и count == 0 то заносим / и прочитанный символ
            //во временной файл
            else if(count == 0){
                fputc('/', temp);
                fputc(c, temp);
            }
        }
        //Если мы нашли начало */
        else if (c == '*') {
            //и второй символ == /, уменьшаем кол-во комментариев
            if ((c = fgetc(code)) == '/')
                --count;
            //если после * не идет / и count == 0 то заносим * и прочитанный символ
            //во временной файл
            else if(count == 0) {
                fputc('*', temp);
                fputc(c, temp);
            }
        }
        c = fgetc(code);
    }
    //Закрываем файлы
    fclose(code);
    fclose(temp);
    //Удаляем исходный файл
    remove("code.txt");
    //Переименовываем временной в название основного
    rename("temp.txt", "code.txt");
    _getch();
    return 0;
}

Мне просто понравилось условие задания, по этому решил просто сделать больше как пример для себя. Код возможно имеет ошибки т.к. писал в проекте на c++. Но я все расписал и думаю идея понятна, так что труда не составит пофиксить их :)

Так же не знаю, как будет вести себя код, если будут не правильно расставлены комментарии, так же если в коде есть комментарии // между которыми есть такие комментарии /* и */, то тоже не знаю, как поведет себя алгоритм. Так же если в коде будет строковый литерал по типу такого: "/* 123 */" кодом будет удалено /* 123 */ как комментарий.

→ Ссылка
Автор решения: Harry

В принципе, если считать файл корректным (без вложенных комментариев, комментариев в строках, оборванных комментариев (типа, файл заканчивается /******* и все :)) или там символа \ в конце строки (так возможен переход комментария // на следующую строку) - то этого КА с головой:

void delComm(FILE* in, FILE* out)
{
    for(int state = 0, c = fgetc(in); c != EOF; c = fgetc(in))
    {
        switch(state)
        {
        case 0: {
            if (c == '/') { state = 1; }
            else fputc(c,out);
        } break;
        case 1: {
            if (c == '/') { fputc('/',out); fputc('/',out);
                state = 2; }
            else if (c == '*') { state = 3; }
            else { fputc('/',out); state = 0; }
        } break;
        case 2: {
            fputc(c,out);
            if (c == '\n') state = 0;
        } break;
        case 3: {
            if (c == '*') { state = 4; }
        } break;
        case 4: {
            if (c == '/') { state = 0; }
            else state = 3;
        } break;
        }
    }
}

Если не нужна обработка комментариев типа // - можно упростить, если нужна обработка строк - усложнить...

→ Ссылка