Удалить комментарии на Си
Необходима функция для удаления комментариев из файла. Всё что между /* и */ включая эти символы. Вот написал что-то, но не пойму как удалять.
#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 */ как комментарий.
В принципе, если считать файл корректным (без вложенных комментариев, комментариев в строках, оборванных комментариев (типа, файл заканчивается /******* и все :)) или там символа \ в конце строки (так возможен переход комментария // на следующую строку) - то этого КА с головой:
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;
}
}
}
Если не нужна обработка комментариев типа // - можно упростить, если нужна обработка строк - усложнить...