-1

I have a string like:

char string = " dog beans 1234 cat rice 0123 bird peanut 7777"

I would like split that in different variables like:

char animals[1000], food[1000], numbers[1000];

What I did until now:

int i;
while (string != NULL)  {
    for (i = 0, i < 1000, i++) {
        strcpy(animals[i], strtok(string, " ");
        strcpy(food[i], strtok(string, " ");
        strcpy(numbers[i], strtok(string, " ");
    }
}

The first loop is working fine, but the second one throws a segmentation fault.

chqrlie
  • 131,814
  • 10
  • 121
  • 189
  • 1
    Your code won't compile. The calls such as `strcpy(animals[i], strtok(string, " ");` are missing a `)` before the semicolon. (And `char string = "…";` doesn't compile either! Beware of making it `char *string` because then you're hacking a string literal — not good) Please don't post code that does not compile (unless you are seeking help for a compilation error) — it annoys people. – Jonathan Leffler Feb 18 '17 at 23:28
  • 1
    It would be helpful, too, if you showed what you wanted as output. If you want the `animals` array to hold `"dog cat bird"` and the `numbers` array to hold `"1234 0123 7777"`, you do things one way. If you want arrays of pointers, then you do things another way. It also helps if you create an MCVE ([MCVE]). Clearly, this is not a copy of the code you're running because it can't compile. – Jonathan Leffler Feb 18 '17 at 23:34

2 Answers2

2

First, you are treating animals, food, and numbers as an array of strings, but you declare them as arrays of characters. You need to declare them as arrays of char arrays, or as arrays of char pointers, in which case you would need to allocate the strings with malloc.

char animals[100][20];
char food[100][20];
char numbers[100][20];

Second, when you call strtok with the same non-null initial parameter, you will get the same value. You need to pass NULL in all invocations after the initial one:

strcpy(animals[i], strtok(string, " "));
strcpy(food[i], strtok(NULL, " "));
strcpy(numbers[i], strtok(NULL, " "));
Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
Sergey Kalinichenko
  • 714,442
  • 84
  • 1,110
  • 1,523
0

First, as you read up to 1000 animal names, you require 1000 elements of animal[99] (assuming a single animal name has a max length of 99) instead of "one animal name of size 1000 for all".

Second, your strtok will always start from the initial string, always yielding the same value dog. Use string only for the first call, and NULL for all the other ones.

Note further that strtok will return NULL if it cannot extract another token; this could happen also within the loop, such that, for example, a strcpy(food[i], strtok(...)) might crash. Hence, I'd suggest to check the return value of strtok before further usage:

char animals[1000][99];
char food[1000][99];
char numbers[1000][99];
int  i=0;
char *token = strtok(string, " ");
while (i < 1000 && token)
  strcpy (animals[i], token);
  token = strtok(NULL, " ");
  if (!token) 
    break;
  strcpy (food[i], token);
  token = strtok(NULL, " ");
  if (!token) 
    break;
  strcpy (numbers[i], token);
  token = strtok(NULL, " ");
  i++;
}
Stephan Lechner
  • 34,891
  • 4
  • 35
  • 58