strtok is okay as long as you don't have to worry about concurrency or nested calls. In those cases strtok will fail miserably. Some libraries have a strtok_r that is reentrant, but I've found that it's easier just to follow in the footsteps of argc and argv:
Code:
/* Warning: Ugly code follows. Sorry, written in haste. */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int makeargv(char *plist, char ***argv, char *delim)
{
char *pos = plist;
size_t dlen = strlen(delim);
int argc = 0;
int i;
/* Count args */
while ((pos = strstr(pos, delim)) != NULL) {
argc++;
pos += dlen;
}
if ((*argv = malloc((argc + 1) * sizeof **argv)) == NULL)
return -1;
for (i = 0, pos = plist; i < argc; i++, plist = pos + dlen) {
pos = strstr(plist, delim);
if (((*argv)[i] = calloc((pos - plist) + 1, sizeof (*argv)[i])) == NULL) {
while (--i >= 0)
free((*argv)[i]);
free(*argv);
return -1;
}
strncpy((*argv)[i], plist, pos - plist);
}
/* Last token */
if (((*argv)[i] = calloc(strlen(plist) + 1, sizeof (*argv)[i])) == NULL) {
while (--i >= 0)
free((*argv)[i]);
free(*argv);
return -1;
}
strcpy((*argv)[i++], plist);
(*argv)[i] = NULL;
return argc + 1;
}
int main(void)
{
char **argv;
char test[] = "Testing|1|2|3|4";
int argc;
int i;
/* Using makeargv */
if ((argc = makeargv(test, &argv, "|")) != -1) {
for (i = 0; i < argc; i++) {
puts(argv[i]);
free(argv[i]);
}
free(argv);
}
return 0;
}