【问题标题】:Issue when reading cvs file and storing in buffer读取 csv 文件并存储在缓冲区中时出现问题
【发布时间】:2017-01-11 14:36:12
【问题描述】:

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

#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");
    }

}

感谢任何帮助。

【问题讨论】:

  • 这不是如何将 CSV(应该是纯文本)中的 double 值读入 double 缓冲区。
  • 方法是使用fgets的返回值来控制循环。就目前而言,您在确定输入是否有效之前处理(错误地,请参阅答案)输入。惯用的方式是while(fgets(buff, 80, fp) != NULL) { ... }。然后你就不需要对getc 进行任何胡闹了。
  • 您还应该在strtok 分隔符甚至\r\n 中包含换行符\n 以涵盖各种操作系统行结尾。从您使用getc 的方式来看,您似乎没有意识到fgets 保留了输入中的newline。这样您就可以确定输入行是否由于长度限制而中断,以便在下次调用 fgets 时继续进行 - 这不会“忘记”输入行的其余部分。

标签: c string file csv io


【解决方案1】:
  1. 您正在将token 类型转换为(char)token 是一个字符指针 - 基本上,一个指向包含下一个 , 分隔标记的字符串的指针。您需要将该字符串中包含的浮点数解析为double 值,而不是将字符串指针本身类型转换为char 值。试试sscanf()
  2. 当您输出您的值时,您输出的是最后一个输入缓冲区中的字符,而不是您(尝试)从输入中解析出来的双精度值。更改您的 printf 命令以输出双精度值(例如 %f%g)并将值从您的 buffer 双精度数组而不是 buff 字符数组中传递出来。

【讨论】:

    【解决方案2】:

    不错的尝试,稍微修改一下,像这样:

    #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;
    }
    

    示例运行:

    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
    

    注意事项:

    1. 使用atof() 中从字符串解析为双精度。
    2. 我们通常更喜欢fgets() over getc()

    【讨论】:

    • 感谢您的帮助和 cmets。我其实是一个 C 初学者
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-10-29
    • 2011-11-14
    • 2021-04-08
    • 2021-10-24
    • 2013-05-20
    • 2018-02-28
    • 1970-01-01
    相关资源
    最近更新 更多