Как получить длину файла

Я пытаюсь запустить простую программу на C, которая берет файл случайных значений с плавающей запятой, автоматически определяет длину файла и использует эту длину для выполнения дальнейших вычислений. Однако мой компилятор либо зависает, либо я получаю ошибочные результаты. Вот мой код

      #include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <math.h>

int main() {
  FILE *fptr;
  int count = 0; // Line counter (result)
  char ch; // To store a character read from file

  if ((fptr = fopen("C:\\Users\\Evandovich\\Desktop\\White_Noise.txt", "r"))
      == NULL) {
    printf("Error! opening file");
    // Program exits if the file pointer returns NULL.
    exit(1);
  }

  // Extract characters from file and store in character ch
  for (ch = getc(fptr); ch != EOF; ch = getc(fptr)) {
    if (ch == '\n') // Increment count if this character is newline
      count = count + 1;
  }
  printf("The file has %d lines\n ", count);

  // use the value of "count" to be the length of the array.
  char arrayNum[count];
  char *eptr;
  double result, result1[count];

  for (int i = 0; i < count; i++) {
    fscanf(fptr, "%s", &arrayNum[i]);

    /* Convert the provided value to a double */
    result = strtod(&arrayNum[i], &eptr);
    result1[i] = pow(result, 2);
    printf("value %f\n", result1[i]);
  }

  fclose(fptr);
  return 0;
}

В чем конкретно ошибка? Ваш вклад высоко ценится.

ВХОДНОЙ файл (N.txt) содержит

      0.137726
0.390126
-0.883234
0.006154
-0.170388
-1.651212
0.510328

ВЫВОД В файле 7 файлов

      value 0.000000
value 0.000000
value 0.000000
value 0.000000
value 0.000000
value 0.000000
value 0.000000

Ожидается В файле 7 файлов

      value 0.018968
value 0.152198
value 0.780102
value 0.000038
value 0.029032
value 2.726501
value 0.260435

3 ответа

По крайней мере эти проблемы:

В конце файла

Код дает сбой при попытке прочитать текст с плавающей запятой из конца файла. @ЭрлингХааланд

После определения количества строк добавьте:

       rewind(fptr);

Запутанное чтение

Прочитайте строку сfgets(). Избегать"%s"без ограничения ширины - может переполниться. Используйте линейный буфер, основанный на максимальной длине строки, а не на количестве строк. Преобразовать вdoubleначиная с начала строки.

      #define LINE_SIZE 100
char arrayNum[LINE_SIZE];
if (fgets(arrayNum, sizeof arrayNum, fptr) == NULL) {
  break;
}
result = strtod(arrayNum, &eptr);

Проверить конверсию

      errno = 0;
result = strtod(arrayNum, &eptr);
if (arrayNum == eptr || errno) {
  break;
}

Слишком мелкий тип

int getc(FILE *)обычно возвращает 257 различных значений:EOFи [0...UCHAR_MAX]. Сохранение этого вcharтеряет информацию. Сохранить вint.

Количество линий под угрозой

Может отличаться на 1, так как последняя строка может не иметь'\n': @ Адриан Маккарти .

Вместо этого считайте начало строки .

      size_t count = 0;
int previous = '\n';
int ch;

while ((ch = getc(fptr) != EOF) {
  if (previous == '\n') {
    count++;
  }
  previous = ch;
}
printf("The file has %zu lines.\n ", count);

// Also
rewind(fptr);

Самый быстрый, эффективный и безопасный способ получить размер файла — запросить операционную систему черезstat():

      struct stat statbuf;
stat("C:\\Users\\Evandovich\\Desktop\\White_Noise.txt", &statbuf);
statbuf.st_size; /* The file size in bytes */

Пара проблем:

  1. getcвозвращает значение следующего какintили специальное значение. Поскольку ваша переменнаяchэтоchar,EOFзначение может быть не распознано, и в этом случае цикл подсчета строк может никогда не закончиться.

  2. Вы определяете массивы, размер которых определяется переменной времени выполнения. Я регулярно использую C++, но пишу на C уже очень давно. Когда я писал на C, размер массивов нужно было определять во время компиляции. Возможно, это новая функция C? Я бы проверил.Убедитесь, что у вас включены предупреждения компилятора.

  3. может быть короче одной строки, если последняя строка файла не заканчивается на '\n'. В системах Posix строка должна заканчиваться символом новой строки. В Windows последовательность новой строки (обычно CR+LF) обычно рассматривается как разделитель строк. Таким образом, файлы могут заканчиваться или не заканчиваться последовательностью новой строки в конце последней строки.

  4. arrayNumпредставляет собой массивcountсимволы, а не массив указателей на символьные строки.

Другие вопросы по тегам