2

I would like break up a string sequence by " " and stick it into an array. This is the code that I have but does not work:

int main(void) {
    char s[] = "this is a string";
    char* x = NULL;
    unsigned int i = 0; 
    for (char *p = strtok(s," "); p != NULL; p = strtok(NULL, " ")) {
       x[i] = *p;
       puts(x[i]);
       i++;
    }
    return 0;
}

It gives me the following error: error:

array initializer must be an initializer list

I am at a loss on how to accomplish this in C. So I would like x[0] = "this", x[1] = "is" and so on. Any help would be appreciated, I have searched for the answer and read tutorials but still cant come up with the right answer. Any help would be greatly appreciated. Thanks!

3
  • 2
    Indexing a NULL pointer is not the best idea... Commented Aug 7, 2015 at 19:24
  • @od122 Show the exact error message. It is interesting. Commented Aug 7, 2015 at 19:29
  • If that is your whole code, you got warnings too. I suppose you included the appropriate headers, or do we have to ask about this incomplete code? Since if not strtok will be assumed to return int. MCVE, again and again, so we don't have to ask basic questions Commented Aug 7, 2015 at 19:32

1 Answer 1

6

There are two problems with your code:

  • You are trying to grow your array as you go. This is not possible in C without using dynamic allocation with realloc, or pre-allocating sufficient space, and using some of it.
  • You are trying to store the results of strtok for future use. In general, this is not safe, because tokens point to the original string. It is safer to copy each token into separate space.

Here is how your code would look with pre-allocated space for 100 tokens:

int main(void) {
    char s[] = "this is a string";
    char* x[100];
    unsigned int i = 0; 
    for (char *p = strtok(s," "); i != 100 && p != NULL; p = strtok(NULL, " ")) {
       x[i] = malloc(strlen(p)+1);
       strcpy(x[i], p);
       puts(x[i]);
       i++;
    }
    // Now you need to free the strings
    for (unsigned int j = 0 ; j != i ; j++) {
        free(x[j]);
    }
    return 0;
}

Demo.

If you are certain that there would be no modifications done to s, you could store tokens directly, too:

int main(void) {
    char s[] = "this is a string";
    char* x[100];
    unsigned int i = 0; 
    for (char *p = strtok(s," "); i != 100 && p != NULL; p = strtok(NULL, " ")) {
       x[i] = p;
       puts(x[i]);
       i++;
    }
    return 0;
}
Sign up to request clarification or add additional context in comments.

5 Comments

thank you very much, that worked. There is no way to do this without malloc? I wanted to stay away from the heap if possible.
@rod122 You can do this without malloc by limiting the size of each token, i.e. char x[100][100]. Copying would become slightly more complicated, too, because you would have to check if the string is too long for the place to which you are trying to copy it.
The tokens returned by strtok() are stable — they point to locations in the (mangled) original string. As long as the string being parsed doesn't change, the pointers returned by strtok() are usable safely. In this context, it would be OK to keep the x[i] as simple copies of the pointer returned by strtok(). Of course, the code in the question doesn't use the x[i] values after the loop, so there was no point in preserving them in the first place. (I used mangled to remind people that strtok() modifies the input string, zapping delimiter characters in the string.)
@JonathanLeffler Thanks for the comment!
oops it looks like you already had my solution in your answer, all good i'v deleted it already.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.