Reputation: 251
I'm trying to write a C function that is similar to split
in Java. When I do what I do at main, instead of add function, it works perfectly. But I couldn't understand why it does not work with add function.
#include <stdio.h>
#include <string.h>
char *words[50] = { NULL };
void add(const char *word) {
static int i = 0;
words[i] = word;
i++;
}
int main( void )
{
char string[65];
char *tokenPtr;
fgets(string, 65, stdin);
tokenPtr = strtok( string, " " );
add(tokenPtr);
int i = 0;
while ( tokenPtr != NULL ) {
add(tokenPtr);
tokenPtr = strtok( NULL, " " );
}
int i;
for(i = 0; words[i] != NULL; i++)
puts(words[i]);
return 0;
}
This is just a little piece of my actual code, there are some reasons why I need to do it in another function.
Upvotes: 1
Views: 189
Reputation: 84569
In addition to removing the first call to add
and the duplicate declaration of i
, there are a couple of other considerations. While there is nothing wrong with using while
to parse the tokens, with strtok
in particular, a for
loop nicely handles both the initial call, and each subsequent call with NULL
.
Similarly, while there is nothing wrong with the static
declaration for i
in add
, passing the index as a parameter to the function can provide access to the count in main()
. This adds a definite count of the tokens as well as flexibility should you later decide to allocate/reallocate words
dynamically.
While there is nothing wrong with using a for
loop to iterate indefinitely while relying on a NULL
test on the pointer, if you did pass the token index as a parameter to add
, you could iterate over the definite range 0 < i < token index
and insure you do not attempt a read beyond the end of words
in the event that you have 49
tokens. (which a test for could be added)
Finally, (and this is just a nit), when declaring variables to use as positive counters, indexes, etc, consider using size_t
instead of int
.
There are many approaches to this problem, no one more right than the other, as long as correct. With all the considerations, a slight revision to the code might look like:
#include <stdio.h>
#include <string.h>
char *words[50] = { NULL };
void add (const char *word, size_t idx) {
words[idx] = word;
}
int main( void )
{
char string[65];
char *tokenPtr;
size_t tokIdx = 0; /* token index */
size_t i = 0; /* use size_t if non-negative counter */
fgets(string, 65, stdin);
for (tokenPtr = strtok (string, " "); tokenPtr && *tokenPtr; tokenPtr = strtok (NULL, " "))
add (tokenPtr, tokIdx++);
for (i = 0; i < tokIdx; i++)
printf (" words[%zu] %s\n", i, words[i]);
return 0;
}
Output
$ echo "how many tokens are in this line eight?" | ./bin/strtokadd
words[0] how
words[1] many
words[2] tokens
words[3] are
words[4] in
words[5] this
words[6] line
words[7] eight?
Upvotes: 1
Reputation: 10417
Remove the first add
calling.
fgets(string, 65, stdin);
tokenPtr = strtok( string, " " );
// add(tokenPtr); // remove
Since you'll add the first token in the next while
loop.
Also, you should remove duplication of int i
.
// int i; // <-- why is it there?
for(i = 0; words[i] != NULL; i++)
puts(words[i]);
Upvotes: 4