Программа для чтения кода и подсчета количества строк в нем, без учета комментариев и пустых строк
Я пытаюсь создать программу, которая, учитывая входной файл, возвращает счетчик всех строк кода во входном файле, исключая пустые строки и строки комментариев. Я написал следующий код, однако мне нужна помощь с тем, как исключить строки, содержащие комментарии и пустые строки.
#include<stdio.h>
int main()
{
int count;
char ch;
FILE *fptr;
clrscr();
fp=fopen("test.cpp","r");
if(fp==EOF)
{
perror("Error:");
}
else
{
while(ch!=EOF)
{
ch=fgetc(fptr);
if(ch=='\n')
count++;
if(ch=='\\')
count--;
if(ch=='\*')
{
while(ch!='*\')
{
ch=fgetc(fptr);
}
}
}
printf("the lines in the code are %d\n",count);
fclose (fptr)
}
getchar();
return 0;
}
Как я могу изменить приведенный выше код, чтобы пустые строки и строки комментариев не учитывались?
6 ответов
Если вы читаете входной файл символ за символом, у вас будет намного больше работы, чем если бы вы читали его построчно. Ведь ты считаешь строки...
psudocode
1. инициализировать счетчик строк до 0 2. прочитать строку 3. конец файла? да: перейти к 7 4. это хорошая линия? да: перейти к 5; нет: переход 2 5. увеличить количество строк 6. повторить с 2 7. количество выходных строк
Теперь вы спросите... что такое хорошая линия?
Для аппроксимации программы я предлагаю вам рассмотреть все строки, кроме линий, состоящих из 0 или более пробелов. Это приближение будет учитывать комментарии, но вы можете разработать свою программу отсюда.
Следующая версия игнорирует строки с // комментариями в пустой строке.
Версия 3 может игнорировать строки, содержащие оба /*
а также */
и версия 4 будет иметь дело с многострочными комментариями.
Прежде всего, получайте удовольствие!
С комментариями //
а также /* */
, В следующих строках ваша проблема:
if(ch=='\\')
count--;
if(ch=='\*')
while(ch!='*\')
ch=fgetc(fptr);
Другая проблема заключается в том, что нельзя сопоставить двухсимвольный разделитель комментариев, читая символ за раз без какого-либо конечного автомата.
Кроме того, ваш код должен учитывать тот случай, когда комментарии встраиваются в реальные строки кода. например.
x = 1; // Set value of x
Вам было бы намного лучше читать файл по очереди, проверять, является ли каждая строка пустой или комментарием, и увеличивать счетчик, если нет.
Вы имеете в виду //, /* и */ вместо \ * и *\
\ используется как escape-символ, который меняет "значение" символа после него.
\ n дает вам новую строку. с \\
вы получаете один \ и с \ "вы получаете то, что не закрывает отверстие"
Если вы замените эти символы комментария на правильные, вы должны получить код, который будет компилироваться. Но это не считается правильно.
Вообразите линию как это:
doSomething(); // foo
Помимо ваших проблем с символьными константами у вас есть ошибки в том, как вы справляетесь fputc
, fputc
возвращает int
, Может вернуть либо EOF
которая является отрицательной целочисленной константой, если для красного цвета не было оставшихся символов или произошла ошибка, или она может вернуть значение символа, считанного как unsigned char
и преобразован в int
,
Если вы конвертируете возвращаемое значение fputc
в char
прежде чем сравнивать его с EOF
тогда действительный символ может сравниваться как равный EOF
вызывая преждевременное прекращение вашего цикла.
Кроме того, не то, что while
цикл начинается до первого вызова fputc
так что вы используете неинициализированное значение ch
в первой итерации. Это может привести к чему угодно.
Идиоматический способ формирования цикла:
int ch;
while ((ch = fgetc()) != EOF)
{
/* ... */
}
В стороне цикла вы должны быть осторожны в сравнении возвращаемого значения в связи с тем, что ch
это unsigned char
преобразован в int
,
На большинстве платформ проще всего было бы создать переменную char для сравнения, хотя вы могли бы выставить константы вашего персонажа одинаковыми. unsigned char
в int
процедура преобразования.
Например
char c = ch;
if (c == '\n')
или же
if (ch == (unsigned char)'\n')
Другие указали на проблемы с литералами вашего персонажа.
Ну, отчасти проблема в том, что ваша переменная ch имеет длину только символ, но когда вы проверяете комментарии, такие как \\
а также \*
, это два символа длиной, и, следовательно, необходимо использовать сравнение строк.
Другая проблема заключается в том, что однострочные комментарии в C/C++ начинаются с //
и многострочные комментарии начинаются с /*
и заканчивается */
,
Вы можете написать что-то вроде этого на Python:
def goodline(l : str) -> int:
if l.lstrip().startswith("/*") and l.rstrip().endswith("*/"):
# single line
return 0
elif l.lstrip().startswith("/*") and not l.rstrip().endswith("*/"):
# multi line start
return 1
elif not l.lstrip().startswith("/*") and l.rstrip().endswith("*/"):
# multi line end
return 2
elif l.strip() == "":
# empty line
return 3
elif l.lstrip().startswith("//"):
# single line
return 0
else:
# good line
return 4
если возвращаемая выше функция равна 1, продолжайте повторять строки, пока возвращаемая величина не станет 2.