Как прочитать float из файла на C

#c

#c

Вопрос:

Предположим, что файл организован таким образом:

 1.2 # 3.4 # 4.0

2.3 # 2.3 # 1.2
  

Прочитайте файл на C и сохраните данные в виде массива. Между тем, вы должны судить, сколько там строк.

Моя проблема в том, что 1) Я не знаю, как объявить массив, поскольку я не знаю, сколько чисел существует в файле, поэтому должен ли я предварительно просмотреть файл и посчитать число?

2) Я не знаю, как определить номер строки, поскольку последний ‘ n’ в файле может существовать, а может и нет.

Комментарии:

1. Это домашнее задание? Вы должны пометить его как таковой, если это так.

2. Я чувствую вопрос о домашнем задании…

Ответ №1:

Ответ на 1) Как объявить массив, если вы заранее не знаете количество элементов, неразрешимо с примитивными векторами, вам придется создать свой собственный вектор, способный к росту.

 typedef struct {
    double * v;
    unsigned int size;
} Vector;
  

Эта структура является основой нового типа данных. Вам понадобится API, такой как:

 Vector createVector();

void addToVector(Vector *v, double x);
double getFromVector(Vector *v, unsigned int pos);
void modifyInVector(Vector *v, unsigned int pos, double x);
unsigned int sizeOfVector(Vector * v);

void destroyVector(Vector *v);
  

Ключевыми элементами API являются createVector, destroyVector и addToVector. Поскольку это, вероятно, домашнее задание, я не буду решать это за вас.

В createVector вам в основном нужно присвоить всем полям значение 0. В destroyVector вам нужно освободить () v; В addToVector вам придется изменить размер () зарезервированного пространства, чтобы поместился другой новый элемент:

 size_t newSize = ( v->size  1 ) * sizeof( double );
  

Теперь вам нужно вызвать realloc() с новым размером.

И это в основном все. Если вы хотите повысить производительность, вы можете также ввести емкость вектора, чтобы вам не приходилось увеличивать ее каждый раз, когда вы добавляете новое значение. Например, люди, которые создали STL на C , увеличивают класс vector до его удвоения каждый раз, когда емкость превышается. Но, в любом случае, это уже другая история.

Ответ №2:

atof (ascii для преобразования в float):

http://en.wikipedia.org/wiki/Atof

Ответ №3:

Используйте fscanf :

Функция fscanf() должна считывать данные из именованного входного потока. […] Каждая функция считывает байты, интерпретирует их в соответствии с форматом и сохраняет результаты в своих аргументах. Каждый ожидает в качестве аргументов формат управляющей строки, описанный ниже, и набор аргументов указателя, указывающий, где должны храниться преобразованные входные данные.

Ответ №4:

Следующий код считывает данные с stdin консоли, обрабатывает числа в указанном вами формате и распечатывает их снова, чтобы можно было проверить правильность.

 #include <stdio.h>

int main(int ac, char *av[])
{
    float a, b, c;
    scanf("%f # %f # %f", amp;a, amp;b, amp;c);
    printf("%f # %f # %f", a, b, c);
    printf("n");
}
  

Хотя этот код работает, он не очень надежный. Для этого требуется ТОЧНАЯ последовательность ' # ' символов между числами, и после последнего числа в строке допускается только перевод строки.

Для более надежного решения вам нужно было бы найти символьный индекс начала каждого числа и выполнить fscanf в этом местоположении.

Ответ №5:

С плавающей запятой теряется точность для десятичных дробей. Например, для точного представления простого числа, такого как «0.1», требуется бесконечное количество битов.

Для приведенных вами чисел (только одна цифра после запятой) лучшей идеей было бы умножить каждое число на 10, чтобы избежать потери точности, которую может вызвать плавающая точка. Это потребовало бы написания вашей собственной процедуры преобразования «ASCII в целое число», которая делает вид, что десятичная точка находится в одном месте справа от того, где она находится на самом деле. Это также сэкономило бы место, поскольку (для показанных вами чисел, где ни одно число не превышает 25,6) вы могли бы хранить их в массиве 8-разрядных целых чисел (chars).

Удачи с домашним заданием!