1

I'm trying to use C to read a CSV file, iterate line by line (until EOF), and delimit/split each line by the comma. Then I wish to separate each column into "bins" and put add them to a struct (which isn't shown here; I defined it in a helper file) based on type.

For example, if I have 1,Bob, I'd like to split 1 and Bob into two variables. Here's what I've written so far.

void readFile(char file[25]) {
    FILE *fp;
    char line[1000];

    fp = fopen(file, "r"))

    while(fgets(line, 1000, fp)) {
        char* tmp = strdup(line);
        char* token;

        while((token = strsep(&tmp, ","))) {
            printf("%s\n", token);  // I want to split token[0] and token[1]
        }
    }
    fclose(fp);
}

T he above code does compile and run. I just don't know how to access each split of the token, like token[0] or token[1]. In python, this would be simple enough. I could just access 1 using token[0] and Bob using token[1] for each line. But here in C, I can't do that.

For testing purposes, all I'm doing right now is printing each line (in the second while loop), just to see how each split looks. I haven't implemented the code where I put each split line into its respective struct member.

I've searched Stack Overflow and found a multitude of threads on this topic. None of them seemed to help me except for this one, which I have drawn from. But I wasn't able to get the storing of split columns working.

5
  • 1
    If nothing else, you have a memory leak in your code. Don't forget that strdup allocates memory which you need to free. Commented Feb 21, 2019 at 6:46
  • I would look into strtok. It's how I did it before. Commented Feb 21, 2019 at 6:47
  • Also note that strsep is not a standard C function. And that you probably need to read its documentation a little closer (if you still want to use it instead of the standard C strtok function). Commented Feb 21, 2019 at 6:48
  • What would I change in my code to get it to work with strtok? From reading some documentation, it looks like it has largely the same format as strsep. Can I also get the second chunk of text, or does it only give one chunk of text (or token) at a time? Commented Feb 21, 2019 at 7:12
  • Additionally there is no law or decree that says a CSV row must be less than 1000 characters long... If you're on POSIX consider using getline instead! And you probably don't need to strdup the line either if you duplicate each of the fields or parse them in place there... Commented Feb 21, 2019 at 7:53

1 Answer 1

1

In python, this would be simple enough. I could just access 1 using token[0] and Bob using token[1] for each line. But here in C, I can't do that.

Yes, you can, if only you define the array.

    while (fgets(line, sizeof line, fp))
    {
        char *tmp = strchr(line, '\n');
        if (tmp) *tmp = '\0';   // remove the '\n'
        tmp = strdup(line);
        #define MAXCOLUMNS  2
        char *token[MAXCOLUMNS];
        int c = 0;
        while (tmp)
        {
            if (c == MAXCOLUMNS) puts("too many columns"), exit(1);
            token[c++] = strsep(&tmp, ",");
        }
        if (1 <= c) printf("column 1: %s\n", token[0]);
        if (2 <= c) printf("column 2: %s\n", token[1]);
        // ONLY if the line's tokens are no longer needed:
        free(*token);
    }
Sign up to request clarification or add additional context in comments.

2 Comments

This is useful to know, thanks. But I don't know what char *token[MAXCOLUMNS] does. It looks like you're defining a new character array, token, that's of length MAXCOLUMNS. But why do you use a *? Wouldn't just char token[MAXCOLUMNS] do the same thing?
@WaterGuy - char *token[MAXCOLUMNS] (with MAXCOLUMNS 2) declares an array of 2 pointers to char, i. e. a pointer array, not a character array. The first of those pointers, token[0], is later set to the beginning of the (strdup-licated) line and the first column, and the second of those pointers, token[1], is set to the second column.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.