2

I want to read from a csv file with C and then store every token in a 2D string array. It appears that the storing is OK, but when i try to print an element from this array, i get strange stuff. Here is the program :

#include <stdio.h>
#include <string.h>
#define BUFFER_SIZE 256

int main(){
    FILE *testFile = fopen("test.csv", "r");
    char buffer[BUFFER_SIZE];
    char *delim = ",";
    char *lastToken;
    char *holder[50][50];
    int i, i2;

    if(testFile == NULL){
        printf("Error!");
    } else {

    i = 0;
    while(fgets(buffer, BUFFER_SIZE, testFile) != NULL){
        i2 = 0;
        lastToken = strtok(buffer, delim);
        while(lastToken != NULL){
            holder[i][i2] = lastToken;
            printf("holder[%i][%i] - %s\n", i, i2, holder[i][i2]);
            lastToken = strtok(NULL, delim);
            i2++;
        }
        i++;
    }
    fclose(testFile);

    } //if file is opened (endif)

    printf("%s\n", holder[0][2]);

    return 0;
}

The text.csv contents :

1,Beer,first,30
2,Rakija,second,50
3,Whiskey,third,95

When i run the program, i get :

holder[0][0] - 1
holder[0][1] - Beer
holder[0][2] - first
holder[0][3] - 30

holder[1][0] - 2
holder[1][1] - Rakija
holder[1][2] - second
holder[1][3] - 50

holder[2][0] - 3
holder[2][1] - Whiskey
holder[2][2] - third
holder[2][3] - 95

ey

Before returning 0, i try to print holder[0][2]. I should get "first", but what i actually get is just "ey" (probably part from holder[2][1] - Whiskey)

dodov
  • 5,206
  • 3
  • 34
  • 65

1 Answers1

2

That's because strtok() modifies the original buffer and thus returns a pointer within the buffer variable. But the content of your buffer is modified everytime you read a new line with fgets() !

Use strdup() or _strdup() in combination with strtok() in order to get a duplicate of the token by allocating memory in the heap:

lastToken = _strdup(strtok(buffer, delim));

and

lastToken = _strdup(strtok(NULL, delim));

Don't forget that you'd also think about freeing the allocated memory on day or the other.

Christophe
  • 68,716
  • 7
  • 72
  • 138
  • Even after putting _strdup, the problem is still here -> holder[0][0], holder[1][0] and holder[2][0] all print "3" on the screen. It works perfect in any other case though. – dodov Jun 15 '14 at 13:15
  • 1
    I'm affraid that not. The problem is that you have a buffer of a couple of bytes, and potentially you could read huge files of thousands of lines. As c does not allocate himself, you'll have to do. You have however the choice to allocate either each line or each field. – Christophe Jun 15 '14 at 13:15
  • did you put the two _strdup(). Your symptom of persistance for the first field only makes me think you've forgotten the one just after the fgets() in the first loop. – Christophe Jun 15 '14 at 13:21
  • Nevermind. I'm retarded. I had this in the code "_strdup(lastToken = strtok(buffer, delim));"... – dodov Jun 15 '14 at 13:22