读取cvs文件并存储在缓冲区时出现问题

读取cvs文件并存储在缓冲区时出现问题,c,string,file,csv,io,C,String,File,Csv,Io,我有一个csv文件,其中包含double值(20行4列),我希望读取这些值并将其存储在缓冲区中以执行某些操作。下面的实现为我提供了屏幕上的一些字符。我试图找出问题出在哪里,但我不知道问题出在哪里: #include<stdio.h> #include <stdlib.h> #include<String.h> int main() { char buff[80]; double buffer[80]; char *token = N

我有一个
csv
文件,其中包含
double
值(20行4列),我希望读取这些值并将其存储在缓冲区中以执行某些操作。下面的实现为我提供了屏幕上的一些字符。我试图找出问题出在哪里,但我不知道问题出在哪里:

#include<stdio.h>
#include <stdlib.h>
#include<String.h>


int main()
{
    char buff[80];
    double buffer[80];
    char *token = NULL;

    FILE *fp = fopen("dataset.csv","r");
    if(fp == NULL){
        printf("File Reading ERROR!");
        exit(0);
    }

    int c = 0;
    do
    {
        fgets(buff, 80, fp);
        token = strtok(buff,",");

        while( token != NULL )
        {
            buffer[c] = (char) token;
            token = strtok(NULL,",");
            c++;
        }
    }while((getc(fp))!=EOF);

    for(int i=1; i<=80; ++i){
        printf("%c ", buff[i]);
        if(i%4 == 0) printf("\n");
    }

}
#包括
#包括
#包括
int main()
{
字符buff[80];
双缓冲器[80];
char*token=NULL;
文件*fp=fopen(“dataset.csv”,“r”);
如果(fp==NULL){
printf(“文件读取错误!”);
出口(0);
}
int c=0;
做
{
fgets(浅黄色,80,fp);
令牌=strtok(buff,“,”);
while(令牌!=NULL)
{
缓冲区[c]=(字符)令牌;
令牌=strtok(空,“”,“”);
C++;
}
}而((getc(fp))!=EOF);
对于(int i=1;i
  • 您正在将
    标记
    键入
    (字符)
    token
    是一个字符指针-基本上是一个指向包含下一个
    分隔标记的字符串的指针。您需要将该字符串中包含的浮点数解析为一个
    双精度
    值,而不是将字符串指针本身键入一个
    char
    值。请尝试
    sscanf()
    用于此
  • 当您输出值时,您是从最后一个输入缓冲区输出字符,而不是从输入中(尝试)解析出的双值。将
    printf
    命令更改为输出双值(例如
    %f
    %g
    )并将值从您的
    缓冲区
    双精度数组中传递给它,而不是
    buff
    字符数组

  • 很好的尝试,稍微修改一下,如下所示:

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h> // not String.h
    
    int main(void)
    {
        char buff[80];
        double buffer[80] = {0}; // I like initialization my arrays. Could do for 'buff' too
        char *token = NULL;
    
        FILE *fp = fopen("dataset.csv","r");
        if(fp == NULL){
            printf("File Reading ERROR!");
            exit(0);
        }
    
        int c = 0;
        while(fgets(buff, 80, fp) != NULL) // do not use 'getc()' to control the loop, use 'fgets()'
        {
            // eat the trailing newline
            buff[strlen(buff) - 1] = '\0';
    
            token = strtok(buff, ",");
    
            while( token != NULL )
            {
                // use 'atof()' to parse from string to double
                buffer[c] = atof(token);
                token = strtok(NULL,",");
                c++;
            }
        }
    
        // print as many numbers as you read, i.e. 'c' - 1
        for(int i=1; i<=c - 1; ++i) // be consistent on where you place opening brackets!
        {
            printf("%f\n", buffer[i]);
        }
    
        // Usually, we return something at the end of main()
        return 0;
    }
    
    注:

  • 习惯于 从字符串解析为双精度输入
  • 我们通常更喜欢

  • 这不是将CSV中的
    double
    值(应该是纯文本)读入
    double
    缓冲区的方法。方法是使用
    fgets
    的返回值来控制循环。目前,您在确定输入是否有效之前处理输入(错误,请参见答案)。惯用方法是
    while(fgets(buff,80,fp)!=NULL{…}
    。这样就不需要对
    getc
    进行任何篡改。还应该在
    strtok
    分隔符中包含换行符
    \n
    ,甚至
    \r\n
    来覆盖各种操作系统行结尾。从使用
    getc
    的方式来看,您似乎没有意识到
    fgets
    保留了
    换行符
    从输入中。这样您就可以知道输入行是否由于长度限制而中断,将在下一次调用
    fgets
    时继续-这不会“忘记”输入行的其余部分。感谢您的帮助和评论。我实际上是C初学者
    C02QT2UBFVH6-lm:~ gsamaras$ cat dataset.csv 
    3.13,3.14,3.15,3.16
    2.13,2.14,2.15,2.16
    
    C02QT2UBFVH6-lm:~ gsamaras$ ./a.out
    3.140000
    3.150000
    3.160000
    2.130000
    2.140000
    2.150000
    2.160000