Показанная вами функция countLines()
входит в несколько ловушек.
fgetc()
возвращает намеренно int
, а не char
. Это делается для того, чтобы иметь возможность возвращать состояние конца файла, помимо всех других возможных значений символов. Простой char
не может этого сделать.
Использование feof()
для определения конца файла завершается неудачно, так как индикатор EOF устанавливается только после того, как последнее чтение достигло концафайла был завершен. Таким образом, цикл, управляемый с помощью feof()
, обычно повторяется один раз и часто.
Подробное обсуждение этого вопроса здесь .
Последняя строка текстового файла не обязательно содержит индикатор конца файла, но выСкорее всего, еще хочу посчитать эту строку. Для этого случая необходимо применить специальную логику.
Возможная реализация функции, решающей все упомянутые выше проблемы, может выглядеть следующим образом:
#include <stdio.h>
/* Returns the number of lines inside the file named file_name
or -1 on error. */
long count_lines(const char * file_name)
{
long lines = 0;
FILE * fp = fopen(file_name, "r"); /* Open file to read in text mode. */
if (NULL == fp)
{
lines = -1;
}
else
{
int previous = EOF;
for (int current; (EOF != (current = fgetc(fp)));)
{
if ('\n' == current)
{
++lines;
}
previous = current;
}
if (ferror(fp)) /* fgetc() returns EOF as well if an error occurred.
This call identifies that case. */
{
lines = -1;
}
else if (EOF != previous && '\n' != previous)
{
++lines; /* Last line missed trailing new-line! */
}
fclose(fp);
}
return lines;
}
Что касается обсуждения различных индикаторов конца строки в разделе комментариев к вопросу:
Индикатор конца строки для текстовых файлов реализован по-разному на разных платформах (UNIX: '\n'
по сравнению с Windows:\r\n
vs. ... (https://en.wikipedia.org/wiki/Newline)).
Чтобы маневрировать вокруг этого, функция библиотеки C fopen()
по умолчанию открывает файл в так называемом «текстовом режиме». Еслитаким образом, реализация C заботится о том, чтобы конец каждой строки возвращался в виде одного символа '\n'
, так называемого символа «новой строки». Обратите внимание (как упомянуто выше в разделе 3.), что для последней строки может бытьИндикатор конца строки отсутствует.