gpt4 book ai didi

c - 以与 C 语言中的 MATLAB 类似的方式从 .csv 文件加载的最佳方法

转载 作者:行者123 更新时间:2023-11-30 14:38:26 32 4
gpt4 key购买 nike

我正在尝试在不使用集成编码器的情况下将 MATLAB 模拟转换为 C 语言,以尝试自学 C 语言。在 MATLAB 中要导入和使用 Excel/csv 文件中的数据,您可以使用 GUI 手动将数据导入到您可以在其中另存为 .mat 文件并使用其中的变量,或者不推荐的方法是使用“csvread”。我正在尝试在 C 中执行类似的操作。

我可以使用下面的代码从 csv 文件(720 行 x 3 列)获取数据,但是我很难将数据从 load_PV 函数传递到 main() 函数的输出数据是一个多维数组。我的主要问题是这是否是最好的方法并追求它,或者我是否可以/应该创建一个函数,将每列单独加载为循环中的新变量并将其传递给 main() 函数

#include<stdio.h>
#include<string.h>
#include<stdint.h>
#include<stdlib.h>

float CA[720];
float P[720];
float V[720];
//~ static float ARRAY[720];

float load_PV(int r, int c, float DATA[720][3])
{
char buf[720];
//~ static float ARRAY[720];

FILE *fp = fopen("PV_Data.csv", "r");

if(!fp)
{
printf("Could Not Open File\n");
}
int i = 1;

while(fgets(buf, 720, fp))
{
CA[i] = atof(strtok(buf, ","));
P[i] = atof((strtok(NULL, ",")));
V[i] = atof((strtok(NULL, ",")));
DATA[i][1] = CA[i];
DATA[i][2] = P[i];
DATA[i][3] = V[i];
i++;
}

//~ printf("%f\n", ARRAY[540][3]);

return(DATA[720][3]);
}

int main()
{
int r = 720;
int c = 3;
float DATA[r][c];

float data = load_PV(r, c, DATA[720][3]);

printf("%f\n", data);

//~ int i = 1;

//~ for(i = 1; i<=720; i++);
//~ {
//~ printf("%f", data[i][1]);
//~ printf("\t");
//~ printf("%f", data[i][2]);
//~ printf("\t");
//~ printf("%f\n", data[i][3]);
//~ }
}

由于我对 C 不太熟悉(你能告诉我吗?:P),我预计输出只是一个 720x3 float 组,但是在编译时我收到以下错误消息;

gcc -Wall -o "Test2" "Test2.c" (in directory: C:\Users\Student\Dropbox\C Projects\MATLAB_to_C)
Test2.c: In function 'main':
Test2.c:47:29: error: incompatible type for argument 3 of 'load_PV'
float data = load_PV(r, c, DATA[720][3]);
^
Test2.c:11:8: note: expected 'float (*)[3]' but argument is of type 'float'
float load_PV(int r, int c, float DATA[720][3])
^
Compilation failed.

我对指针不太熟悉,因为它们是我正在尝试学习的 C 的方面之一,我已经看到你可以用它们来完成此任务,但我没有完全理解这些示例,所以还没有使用它们,因为我正在努力学习而不是复制。那么这种方法有效还是另一种更广泛使用的方法?

附注这不是一个家庭作业问题。我刚从大学毕业,看到更多的公司正在寻找 C 而不是 MATLAB,所以尝试学习以供将来发展。这是一项爱好/专业发展练习

最佳答案

在第一次迭代中,您可以编写如下内容:

#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) 关闭 FILE*

更加动态和稳健的解决方案

上面的代码是第一次迭代,但它可能不像您希望的那样动态和健壮,即使对于爱好练习项目也是如此。

那么应该/可以改进什么:

  • 维度(行数和列数)应该是动态的
  • 它应该处理文件中缺失的行
  • 它应该处理文件中缺失的列
  • 应返回读取的行数

那么第二次迭代中的代码可能如下所示:

#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 to float 的指针。该指针的地址与维度(行/列)一起传递给load_PV。在那里, float 的内存被动态分配并用零填充。为每行读取指定数量的 float 。如果数据丢失,则会向 stderr 写入一条消息。返回行数。然后将数据简单地输出到 main 中的控制台,同时考虑尺寸。最后,动态分配的数据被释放。

进一步迭代

代码可以进一步改进,例如文件名应该是函数参数。您应该检查浮点是否可以读取或是否存在转换错误。但这段代码仍然可能是一个很好的起点。

关于c - 以与 C 语言中的 MATLAB 类似的方式从 .csv 文件加载的最佳方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56618065/

32 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com