简体   繁体   English

fgets无法读取C中的完整行

[英]fgets not reading complete line in C

I have a file data.csv which contains float type data: 我有一个文件data.csv ,其中包含float类型数据:


0.22,0.33,0.44 0.22,0.33,0.44

0.222,0.333,0.444 0.222,0.333,0.444


I need to read this file into a two dimensional dynamic array. 我需要将此文件读取为二维动态数组。 But I am not able to read the full line with fgets . 但是我无法阅读fgets Not sure why? 不知道为什么吗?

Here is my C code which I used on Ubuntu: 这是我在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);
}

The output is like: 输出如下:

0.22,0. 0.22,0。

33,0.44 33,0.44

0.222,0 0.222,0

444 444

Error in `./test': double free or corruption (out): 0x0000000000adf270 `./test'中的错误:两次释放或损坏(输出):0x0000000000adf270

Aborted (core dumped) 中止(核心已弃用)

Can anyone tell why is this error? 谁能说出这个错误的原因? :( Or is there a better way to read this kind of data file? :(还是有更好的方法来读取这种数据文件?

One issue is here: 一个问题在这里:

char *rowbuffer=malloc( cols * ( sizeof(float)+sizeof(char) ) );

sizeof(float) is the size that a float uses in memory, not in its text representation. sizeof(float)是float在内存中使用的大小,而不是其文本表示形式。 When reading from files, you should allocate a buffer to contain a whole line in text format . 从文件读取时,应分配一个缓冲区以包含文本格式的整行。 In your case a good bet could be the following: 在您的情况下,以下最佳选择:

int bufsize = cols * (3 + DBL_MANT_DIG - DBL_MIN_EXP + 1) + 1;

(See this for why that value and what you need to #include : What is the maximum length in chars needed to represent any double value? . The trailing + 1 is to account for the newline character, which fgets() does read and include in the buffer.) (有关该值的原因以及您需要#include内容,请参#include表示任何双精度值所需的最大字符长度是多少? 。尾随+ 1表示换行符, fgets()会读取并包含该字符在缓冲区中。)

But that assumes that there are no formatting errors in the input file, so you might want to add some extra slack to that value. 但这是假设输入文件中没有格式错误,因此您可能想要为该值添加一些额外的松弛。

Once you have that value, use it in both the malloc() and fgets() : 一旦有了该值,就可以在malloc()fgets()使用它:

char *rowbuffer=malloc(bufsize);
i=0;
while(fgets(rowbuffer,bufsize,fp) !=NULL) {
...

On a side note, your input file looks like it could be better read using scanf() . 附带一提,您的输入文件看起来可以使用scanf()更好地读取。

Your coding problem is in : 您的编码问题在:

fgets(rowbuffer,sizeof(rowbuffer),fp)

sizeof(rowbuffer) will give you only the size of the pointer, not the size of the memory allocated to the pointer. sizeof(rowbuffer)将只给您指针的大小,而不是分配给指针的内存的大小。

To resolve the issue, you need to supply the proper size of the allocated memory [ cols * ( sizeof(float)+sizeof(char) ] to fgets() . 要解决此问题,您需要为fgets()分配的内存的适当大小[ cols * ( sizeof(float)+sizeof(char) ]。

Your logical problem is in : 您的逻辑问题在:

You assumed that a printed represntation of a float value will take the same amount of memory as it takes for that of a float variable. 您假定float值的打印表示形式将占用与float变量相同的内存量。 No, that's not true. 不,那不是真的。 In the printed representation , each digit (including the decimal point and any leading or trailing 0 after the decimal) will consume one byte of memory each. 打印的表示形式中 ,每个数字(包括小数点和小数点后的任何前导或尾随0 )将各自占用一个字节的内存。 You should keep that in mind while allocating memory for the destination buffer. 在为目标缓冲区分配内存时,请记住这一点。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM