Чтение файлов с одинаковым расширением в каталоге и подсчет их строк - PullRequest
0 голосов
/ 13 октября 2019

У меня проблема с моим кодом. Я пытался открыть файлы с одинаковым расширением и прочитать количество строк в файле, который находится в каталоге. Итак, вот что я сделал:

    #include <stdio.h>
#include <stdlib.h>
#include <dirent.h>
#include <math.h>
#include <string.h>
#include <ctype.h>
int countLines(char name[]);
int main()
{
    struct dirent *de;
    DIR *dr=opendir(".");
    char check[16]=".nkt";
    int i;
    char name[64];
    int count=0;

    if(dr==NULL)
    {
        printf("Didn't open!");
        return 0;
    }

    while((de=readdir(dr))!=NULL)
    {
        if((strstr(de->d_name, check))!=NULL)
        {
            strcpy(name, de->d_name);
            countLines(name);
        }
    }

    closedir(dr);

    return 0;
}

int countLines(char name[])
{
    FILE *fp;
    fp=fopen(name,"r");
    char ch;
    int lines=0;
    while(!feof(fp))
    {
        ch=fgetc(fp);
        if(ch=='\n')
        {
            lines++;
        }
    }

    fclose(fp);

    printf("%d\n", lines);
}

и результат, который я получаю, всегда выглядит так:

2
2
2

Даже если в каждом файле есть 54 строки. Был бы рад получить помощь. PS. Расширение .nkt

1 Ответ

1 голос
/ 13 октября 2019

Показанная вами функция countLines() входит в несколько ловушек.

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

  2. Использование feof() для определения конца файла завершается неудачно, так как индикатор EOF устанавливается только после того, как последнее чтение достигло концафайла был завершен. Таким образом, цикл, управляемый с помощью feof(), обычно повторяется один раз и часто.

    Подробное обсуждение этого вопроса здесь .

  3. Последняя строка текстового файла не обязательно содержит индикатор конца файла, но выСкорее всего, еще хочу посчитать эту строку. Для этого случая необходимо применить специальную логику.

Возможная реализация функции, решающей все упомянутые выше проблемы, может выглядеть следующим образом:

#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.), что для последней строки может бытьИндикатор конца строки отсутствует.

...