0

I am quite new to C and right now I try to read my first CSV files. But somehow I just cant read the MS-DOS formatted files. On top of that (and what confuses me the most) is, that my program reads the Macintosh-formatted files with only CR on the end just fine, while my code contains CR LR (/r /n). But this wont work for the MS-DOS files, which exactly includes CR LF. What am I missing? It a

Tried to change /r /n to /r and /n. Nothing happend for both formats, Macintosh was read fine, while MS-Dos wont. It always stops after the first line of the CSV file (the row "titles") and the crashes with return value -1.073.741.819 for the MS-DOS format.

My CSV:

Category1;Category2;Category3;Category4;;
Snabb;23;1;34;;
Snibb;32;2;15;;
Snobb;12;3;9;;

My Code:

int calculator()
{
    FILE *fp;
    char data [1500];
    fp = fopen("data.csv","r");
    char *token;

    int nummer = 1;
    int counterCat = 1; //counter-values for reading the first line (the categories)
    int maxCat = 4;

    float buffer_tf = 0;
    float buffer_mf = 0; // buffers for the values the are read-in
    float buffer_na= 0;
    float buffer_dh = 0;

    fgets(data,1500,fp);         
    printf("\n\n All data:%s",data); // show all data

    token = strtok(data,";"); // set the first token
    printf("\n%i. %s",nummer,token);// print the first category of the CSV table

    while (counterCat != maxCat){ //print all left categories of the CSV table
        token = strtok(NULL,";");
        nummer ++;
        printf("\n%i. %s",nummer, token);
        counterCat++;
    }

        token = strtok(NULL,"\r\n"); //jump to the next token where the data lies
        token = strtok(NULL,"\r\n");
        nummer = 1;

        while (feof(fp) != true){

        if (token != NULL)
            {
            printf("\n\n\n starting run");
            printf("\n\n%i. dataset:\n\n",nummer); //dataset counter
            nummer ++;
            token = strtok(NULL,";"); //read first row of data
            printf("%s\n",token);

            token = strtok(NULL,";"); //read second row of data
            printf("%s\n",token);
            buffer_tf = atof(token);
            printf("bt=%f\n",buffer_tf);

            token = strtok(NULL,";"); //read third row of data
            buffer_na = atof(token);
            printf("%s\n",token);
            printf("bt=%f\n",buffer_na);

            token = strtok(NULL,";"); //read fourth row of data
            buffer_dh = atof(token);
            printf("bt=%f\n",buffer_dh);

            token = strtok(NULL,"\r\n");/ /jump to the next row for the next run 
            printf("\n\n run end");
            }
    }

    return 0;
}


Jabberwocky
  • 48,281
  • 17
  • 65
  • 115
  • 2
    You need to check your `fgets` implementation. Does it stop at newline, at carriage-return, or the carriage-return newline pair? – Some programmer dude Jul 11 '23 at 07:55
  • 1
    On a different (and unrelated) note, please don't use leading newlines in `printf`. When `stdout` (which is where `printf` writes) is connected to an interactive terminal, it is *line buffered*. That means output is actually written to the terminal on newline. So with a leading newline you flush and write the *previous* line, not the one in the current `printf` call. Please make it a habit to use *trailing* newlines with `printf`. – Some programmer dude Jul 11 '23 at 07:56
  • 2
    Also please note that `strtok` can't handle "empty" tokens. If you have e.g. `a;;c` then the middle empty value will be lost, as `strtok` skips over it. And your code will of course not be able to handle data with embedded semicolons, like `a;"b;c";d` or `a;b\;c;d` which both are three-element records. CSV only *seems* trivial, but have a lot of corner cases like that to make it non-trivial to parse. Please try to find an existing library to parse CSV files. It will save you countless hours. – Some programmer dude Jul 11 '23 at 07:59
  • Okay, I will change the newline positions. Thanks! I guess the problem is, that fgets stops at the newline charakter and therefore no data is left to read. How do I solve that? :D – nicht hier 8D Jul 11 '23 at 08:31
  • 1
    The `fgets` function shouldn't stop at "newline", but read the newline and *then* stop. But if the file it reads from is still valid then the next call should continue with the next line. The problem is how `fgets` recognize a "newline". Does it specifically check for the systems native "newline", or does it let the underlying stream do newline translation and only check for the actual newline character `'\n'`? – Some programmer dude Jul 11 '23 at 08:38
  • 1
    Write a [simpler](https://ericlippert.com/2014/03/21/find-a-simpler-problem/) test program that only reads lines with `fgets` and then prints them. Check the return value of `fgets` and act accordingly. Use your debugger. Tell us what you've found out. – Jabberwocky Jul 11 '23 at 08:49
  • 1
    Thx both of you! I think I got it now. I added fgets to the while loop instead of tokenizing all new lines. As far as I understood, fgets only reads data until after a newline. So there was only the first line in the input buffer and therefore it crashed into void when trying to read more out of it or tokenizing the void (I guess, correct me if wrong :) ) – nicht hier 8D Jul 11 '23 at 09:16
  • BTW `-1073741819` or better known as 0xc0000005 is the error code for "Access Violation". It most likely is the results of wrong usage of `strtok`. Your debugger will tell you more. – Jabberwocky Jul 11 '23 at 09:36
  • 2
    I think your code works for Macintosh-formatted files only because the file is small enough to fit in your buffer. If you were processing a bigger file, I think you’d have problems. – Jonathan Leffler Jul 11 '23 at 10:09
  • 1
    By the way, please read [Why is “while( !feof(file) )” always wrong?](https://stackoverflow.com/questions/5431941/why-is-while-feoffile-always-wrong) – Some programmer dude Jul 11 '23 at 10:28

0 Answers0