Splitting C string without modifying input
token_add()


do not change the struct members before you know that your call will succeed, otherwise you'll end up with inconsistent state (e.g. you're overwriting tokens-&gt;array if realloc fails). That means keep the increment of count and the assignment of array until the end of the function.
Note that strdup is not a C standard function. 


split_string()


you're creating a temporary copy in the local variables token. If you'd pass the pointer and the length to token_add and you could safe the program a string copy.
there is no need to have delimpos in string_split being const. Same goes for the parameter count and charcount. As a rule of thumb, dont use const for integer types, booleans and floating points.
Note: your comment in test.c states that values less than 0 mean unlimited matching, but your code doesn't contribute to that statement. If you have enough matches you'll eventually increment delimcount to match -1.
Separate the increment of delimcount from the comparison with count. Some will ask himself if this is correct and right now, I couldn't tell ;-)
Why don't you use tokens-&gt;count?
If a call to tokens_add failes, you're returning NULL from split_string without freeing the Tokens struct allocated before, leaking its memory.


misc


Provide more test cases. One test case for handling unlimited matching, one for restricted matching, one for empty delimiters. Best is to write down what your API supports and then add a test for every special case.


For instance, if I test the following:

    struct Tokens *tokens = string_split("Hello;world;!;", ";", 2);

    assert(tokens-&gt;count == 2);
    assert(strcmp("Hello", tokens-&gt;array[0]) == 0);
    assert(strcmp("world!", tokens-&gt;array[1]) == 0);


I receive: test: test.c:22: test_2: Assertion 'tokens-&gt;count == 2' failed.


you don't need the include in tokens.h, it's sufficient if you add it to tokens.c