-3

I tried this to parse data given in a csv file into ID, AGE, and GPA fields in a "data" file, but I don't think I'm doing this right (when I tried printing the data, its printing weird numbers). What am I doing wrong?

char data[1000];
FILE *x = fopen("database.csv","rt");
char NAME[300];
int ID[300],AGE[300],GPA[300];
int i,j;
i = 0;

while(!feof(x)) {

        fgets(data,999,x);

        for (j = 0; j < 300 && data[i] != ','; j++, i++) {
                ID[j] = data[i];
                i++;
        }

        for (j = 0; j < 300 && data[i] != ','; j++, i++) {
                NAME[j] = data[i];
                i++;
        }

        for (j = 0; j < 300 && ( data[i] != '\0' || data[i] != '\r' || data[i] != data[i] != '\n'); j++, i++) {

                GPA[j] = data[i];

        }

}
ggorlen
  • 44,755
  • 7
  • 76
  • 106
  • 3
    It's helpful to post some sample data. – caot Nov 09 '19 at 00:03
  • 1
    You're not null terminating the strings in `ID` or `NAME` or `GPA`. You're not reading anything into `AGE`. Also (style note) all upper-case names are traditionally macros — not variable names. – Jonathan Leffler Nov 09 '19 at 00:39
  • 1
    Also note that [`while (!feof(file))` is always wrong](https://stackoverflow.com/questions/5431941/why-is-while-feof-file-always-wrong). – Jonathan Leffler Nov 09 '19 at 00:41

1 Answers1

-1

First of all: for what you're doing, you probably want to look carefully at the function strtok and the atoi macro. But given the code you posted, that's perhaps still a bit too advanced, so I'm taking a longer way here.

Supposing that the line is something like

172,924,1182

then you need to parse those numbers. The number 172 is actually represented by two or four bytes in memory, in a very different format, and the byte "0" is nothing like the number 0. What you'll read is the ASCII code, which is 48 in decimal, or 0x30 in hex.

If you take the ASCII value of a single digit and subtract 48, you will get a number, because fortunately the numbers are stored in digit order, so "0" is 48, "1" is 49 and so on.

But you still have the problem of converting the three digits 1 7 2 into 172.

So once you have 'data': (I have added commented code to deal with a unquoted, unescaped text field inside the CSV, since in your question you mention an AGE field, but then you seem to want to use a NAME field. The case when the text field is quoted or escaped is another can of worms entirely)

size_t i   = 0;
int number = 0;
int c;
int field = 0; // Fields start at 0 (ID).
// size_t x = 0;

// A for loop that never ends until we issue a "break"
for(;;) {
    c = data[i++];
    // What character did we just read?
    if ((',' == c) || (0x0c == c) || (0x0a == c) || (0x00 == c)) {
        // We have completed read of a number field. Which field was it?
        switch(field) {
            case 0: ID[j] = number; break;
            case 1: AGE[j] = number; break;
            // case 1: NAME[j][x] = 0; break; // we have already read in NAME, but we need the ASCIIZ string terminator.
            case 2: GPA[j] = number; break;
        }
        // Are we at the end of line?
        if ((0x0a == c) || (0x0c == c)) {
            // Yes, break the cycle and read the next line
            break;
        }
        // Read the next field. Reinitialize number.
        field++;
        number = 0;
        // x = 0; // if we had another text field
        continue;
    }
    // Each time we get a digit, the old value of number is shifted one order of magnitude, and c gets added. This is called Horner's algorithm:
    // Number   Read    You get
    // 0        "1"     0*10+1 = 1
    // 1        "7"     1*10+7 = 17
    // 17       "2"     17*10+2 = 172
    // 172      ","     Finished. Store 172 in the appropriate place.
    if (c >= '0' && c <= '9') {
        number = number * 10 + (c - '0');
    }
    /*
       switch (field) {
           case 1:
               NAME[j][x++] = c; 
               break;
       }
    */
}
LSerni
  • 55,617
  • 10
  • 65
  • 107
  • Is there any way to just change my code a little bit to fix this issue? I feel like feof is being used incorrectly here – Hidden Dragon Nov 09 '19 at 13:42
  • That is an issue too, as Jonathan Leffler pointed out. I am afraid that you need to rewrite your code quite extensively, and I'd also suggest maybe restarting from something simpler and more basic. As you can see, even *answering* to such questions as these is somewhat frowned upon. – LSerni Nov 09 '19 at 14:24