我有一个文件data.csv
,其中包含float
类型数据:
0.22,0.33,0.44
0.222,0.333,0.444
我需要将此文件读入二维动态数组。但是我无法阅读fgets
的全部内容。不确定为什么?
这是我在Ubuntu上使用的C代码:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main(int argc, char *argv[]) {
FILE *fp;
float **data;
int i,j,rows=2,cols=3;
char * token;
fp=fopen("data.csv","r");
if(fp==NULL) {
fprintf(stderr,"Can't open input file");
exit(1);
}
data= malloc(rows * sizeof(float*));
char *rowbuffer=malloc( cols * ( sizeof(float)+sizeof(char) ) );
i=0;
while(fgets(rowbuffer,sizeof(rowbuffer),fp) !=NULL) {
data[i] = malloc(cols * sizeof(float));
j=0;
printf("\n %s",rowbuffer);
for (token = strtok(rowbuffer,","); token != NULL; token = strtok(NULL, ",")) {
data[i][j++] = atof(token);
/*printf("%s",token);*/
}
i++;
}
free(rowbuffer);
for(i = 0; i < rows; i++)
free(data[i]);
free(data);
fclose(fp);
}
输出如下:
0.22,0。
33,0.44
0.222,0
��
444
`./test'错误:双重免费或损坏(输出):0x0000000000adf270
中止(核心倾销)
任何人都可以告诉为什么会出现这个错误? :( 或者有更好的方法来阅读这种数据文件吗?
答案 0 :(得分:4)
这里有一个问题:
char *rowbuffer=malloc( cols * ( sizeof(float)+sizeof(char) ) );
sizeof(float)
是float在内存中使用的大小,而不是其文本表示形式。从文件中读取时,应分配一个缓冲区以包含整行的文本格式。在你的情况下,一个好的赌注可能是以下:
int bufsize = cols * (3 + DBL_MANT_DIG - DBL_MIN_EXP + 1) + 1;
(请参阅此内容,了解该值以及#include
所需的内容:What is the maximum length in chars needed to represent any double value?。尾随+ 1
将考虑换行符,fgets()
确实读取了并包含在缓冲区中。)
但是假设输入文件中没有格式错误,因此您可能希望为该值添加一些额外的松弛。
获得该值后,请在malloc()
和fgets()
中使用它:
char *rowbuffer=malloc(bufsize);
i=0;
while(fgets(rowbuffer,bufsize,fp) !=NULL) {
...
另外,您的输入文件似乎可以使用scanf()
更好地阅读。
答案 1 :(得分:2)
您的编码问题出在:
fgets(rowbuffer,sizeof(rowbuffer),fp)
sizeof(rowbuffer)
将只给出指针的大小,而不是指定给指针的内存大小。
要解决此问题,您需要将已分配内存[cols * ( sizeof(float)+sizeof(char)
]的正确大小提供给fgets()
。
逻辑问题出在:
您认为float
值的打印的represntation 将占用与float
变量相同的内存量。不,那不是真的。在打印的表示中,每个数字(包括小数点以及小数点后的任何前导或尾随0
)将消耗每个字节一个字节。在为目标缓冲区分配内存时,应该记住这一点。