-1

I have a csv file of double values ( 20 rows and 4 columns) that I want to read and store the values in a buffer to perform some operations. My following implementation gives me some characters on the screen. I tried to see where is the problem but I don't know where:

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

}

Any help is appreciated.

gsamaras
  • 71,951
  • 46
  • 188
  • 305
Alli
  • 53
  • 1
  • 2
  • 6
  • That is not how to read `double` values in a CSV (which ought to be plain text) into a `double` buffer. – Jongware Sep 03 '16 at 18:17
  • The way to go is to use the return value from `fgets` to control the loop. As it stands, you process (wrongly, see answers) the input before finding out whether it was valid. The idiomatic way is `while(fgets(buff, 80, fp) != NULL) { ... }`. You then don't need any monkeying with `getc`. – Weather Vane Sep 03 '16 at 18:23
  • You should also include the newline `\n` in the `strtok` delimiters or even `\r\n` to cover various OS line endings. From the way you are using that `getc` you don't seem to be aware that `fgets` retains the `newline` from the input. This is so that you can figure out if the input line was broken due to the length constraint, to be continued in the next call to `fgets` - which does not "forget" the rest of the input line. – Weather Vane Sep 03 '16 at 18:34

2 Answers2

1
  1. You are typecasting token to (char). token is a character pointer - basically, a pointer to the string containing the next ,-delimited token. You need to parse the floating point number contained within that string to a double value, not typecast the string pointer itself to a char value. Try sscanf() for this.
  2. When you output your values, you are outputting characters from the last input buffer, not the double values that you (attempt to) parse out of the input. Change your printf command to output double values (e.g. %f or %g) and pass it the values out of your buffer array of doubles, not the buff character array.
J Earls
  • 1,792
  • 8
  • 12
1

Nice attempt, modify it a bit, like this:

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

Sample run:

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

Notes:

  1. Use atof() to parse from string to double in .
  2. We usually prefer fgets() over getc().
Community
  • 1
  • 1
gsamaras
  • 71,951
  • 46
  • 188
  • 305