It is often useful to pass the delimiters to use with strtok
as a parameter to the function to separate the string into tokens. You can also make use of a for
loop with strtok
to tidy up the code in certain circumstances.
Since the count of the number of pointers assigned to the resulting array can never be negative, a data type choice of size_t
or unsigned
can help the compiler point out if the variable is later used improperly.
Lastly, if using a static sized array of pointers to hold the pointers for each token, it is important to test the number of pointers assigned, to prevent writing beyond the end of your array. note: if you allocate pointers dynamically (with malloc
or calloc
), you can call realloc
when your initial limit is reached, and subsequently, as needed.
Putting the various pieces together, an alternative would be:
#include <stdio.h>
#include <string.h>
#define MAXP 100
void separate_words (char *a[], char *s, char *delim, size_t *n);
int main (void)
{
char str[] = "apple banana orange pineapple";
char *delim = " \t\n";
char *matrix[MAXP] = { NULL };
size_t how_many = 0;
size_t i;
separate_words (matrix, str, delim, &how_many);
for (i = 0; i < how_many; i++)
printf ("matrix[%zu] = %s\n", i, matrix[i]);
return 0;
}
/* separate 's' into tokens based on delimiters provided in 'delim'
* with pointers to each token saved in 'a' with 'n' updated to hold
* the number of pointers contained in 'a'.
*/
void separate_words (char *a[], char *s, char *delim, size_t *n)
{
*n = 0;
char *p = strtok (s, delim);
for (; p; p = strtok (NULL, delim)) {
a[(*n)++] = p;
if (*n == MAXP) {
fprintf (stderr, "warning: pointer limit reached.\n");
return;
}
}
}
Output
$ ./bin/strtok_static
matrix[0] = apple
matrix[1] = banana
matrix[2] = orange
matrix[3] = pineapple
Making Use of a Return
Additionally, you can make use of the function return to return the number of tokens in the string. This eliminates the need to pass a pointer variable as a parameter to the function:
#include <stdio.h>
#include <string.h>
#define MAXP 100
size_t separate_words (char *a[], char *s, char *delim);
int main (void)
{
char str[] = "apple banana orange pineapple";
char *delim = " \t\n";
char *matrix[MAXP] = { NULL };
size_t how_many = 0;
size_t i;
how_many = separate_words (matrix, str, delim);
for (i = 0; i < how_many; i++)
printf ("matrix[%zu] = %s\n", i, matrix[i]);
return 0;
}
/* separate 's' into tokens based on delimiters provided in 'delim'
* with pointers to each token saved in 'a'. The number of tokens is
* returned.
*/
size_t separate_words (char *a[], char *s, char *delim)
{
size_t n = 0;
char *p = strtok (s, delim);
for (; p; p = strtok (NULL, delim)) {
a[n++] = p;
if (n == MAXP) {
fprintf (stderr, "warning: pointer limit reached.\n");
break;
}
}
return n;
}