На первой итерации вы могли бы написать что-то вроде:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct {
float CA;
float P;
float V;
} Entry;
#define ROWS 720
Entry *load_PV() {
char buf[1024];
FILE *fp;
if ((fp = fopen("PV_Data.csv", "r")) == NULL) {
printf("Could Not Open File\n");
exit(-1);
}
Entry *entries = malloc(sizeof(Entry) * ROWS);
for (int i = 0; i < ROWS && fgets(buf, sizeof(buf), fp); i++) {
entries[i].CA = atof(strtok(buf, ","));
entries[i].P = atof((strtok(NULL, ",")));
entries[i].V = atof((strtok(NULL, ",")));
}
fclose(fp);
return entries;
}
int main() {
Entry *entries = load_PV();
for (int i = 0; i < ROWS; i++) {
Entry entry = entries[i];
printf("%f %f %f\n", entry.CA, entry.P, entry.V);
}
free(entries);
return 0;
}
Изменения
- , поскольку каждая строка состоит из значений CA, P и V, мы могли бы использовать структуру
- определение определяет количество строк
- нам динамически выделяется память для количества строк
- ФАЙЛ * закрыт fclose (fp)
Более динамичное и надежное решение
Приведенный выше код является первой итерацией, но, вероятно, он не такой динамичный и надежный, как вы могли бы пожелать даже для проекта хобби.
Итак, что следует / можно улучшить:
- размеры (количество строк и столбцов) должны быть динамическими
- он должен обрабатывать пропущенные строки в файле
- он должен обрабатывать пропущенные столбцы в файле
- количество прочитанных строк должно быть возвращено
Тогда код может выглядеть следующим образом во второй итерации:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int load_PV(float **dataPtr, int r, int c) {
char buf[1024];
FILE *fp;
if ((fp = fopen("PV_Data.csv", "r")) == NULL) {
fprintf(stderr, "Could Not Open File\n");
exit(-1);
}
float *data = calloc(r * c, sizeof(float));
if (!data) {
*dataPtr = NULL;
return 0;
}
*dataPtr = data;
int row = 0;
for (row = 0; row < r && fgets(buf, sizeof(buf), fp); row++) {
char *token = strtok(buf, ",");
if(token) {
data[row * c] = strtof(token, NULL);
for (int col = 1; col < c; col++) {
token = strtok(NULL, ",");
if(token) {
data[row * c + col] = strtof(token, NULL);
} else {
fprintf(stderr, "missing value in row %d\n", row);
}
}
} else {
fprintf(stderr, "missing value in row %d\n", row);
}
}
fclose(fp);
return row;
}
int main() {
int r = 720;
int c = 3;
float *data;
int number_of_Rows = load_PV(&data, r, c);
for (int i = 0; i < number_of_Rows; i++) {
float *rowData = &data[i * c];
printf("[%d]: ", i);
for(int col = 0; col < c; col++) {
printf("%f ", rowData[col]);
}
printf("\n");
}
if(data) {
free(data);
}
return 0;
}
Так как это работает?
В main есть указатель с именем data для плавания. адрес этого указателя передается load_PV вместе с размерами (строками / столбцами). Там память для поплавков динамически распределяется и заполняется нулями. Указанное количество поплавков считывается для каждой строки. Если данные отсутствуют, сообщение записывается в stderr. Количество строк возвращается. Затем данные просто выводятся на консоль в главном, принимая во внимание размеры. Наконец, динамически назначенные данные освобождаются.
Дальнейшие итерации
Код может быть улучшен, например, имя файла должно быть параметром функции. Вы должны проверить, могут ли быть прочитаны числа с плавающей точкой, и есть ли ошибки преобразования. Но этот код все еще может быть хорошей отправной точкой.