# Need some advice on my Implementation of strsplit() using C

**URL:** <https://community.unix.com/t/need-some-advice-on-my-implementation-of-strsplit-using-c/288230>\
**Category:** Programming\
**Created:** [May 18, 2011, 7:26am UTC](https://community.unix.com/t/need-some-advice-on-my-implementation-of-strsplit-using-c/288230 "2011-05-18T07:26:38Z")\
**Posts on this page:** 4\
**Page:** 1

<div class="post-metadata">

**Author:** ![vistastar](https://community.unix.com/user_avatar/community.unix.com/vistastar/32/2003_2.png) [@vistastar](https://community.unix.com/u/vistastar)\
**Post date:** [May 18, 2011, 7:26am UTC](https://community.unix.com/t/need-some-advice-on-my-implementation-of-strsplit-using-c/288230/1 "2011-05-18T07:26:38Z")

</div>

I write a strsplit function which converts a string separated by a delimeter to a sub-string array.

If anyone can give some advice to optimize it, or raise some new thought about this implementation? Tkx.

```nohighlight
#include<stdio.h>
#include<stdlib.h>
#include<string.h>

char * const *strsplit(char *p, char sep)
{

        if (p == NULL)
                return NULL;

        int num = 0;
        int i = 0;
        char **arry = NULL;
        char **newarrybuff;
        char *strcur;
        char *tmpstr = malloc(strlen(p) + 1);

        if (!tmpstr)
                return NULL;
        strcur = tmpstr;
        strcpy(tmpstr, p);

        while (strcur) {
                if (*strcur == sep) {
                        strcur++;
                        continue;
                }
                newarrybuff = realloc(arry, sizeof(char*) * (i+1));
                if (!newarrybuff) {
                        free(arry);
                        return NULL;
                }
                arry = newarrybuff;
                arry[i++] = strcur;
             
                strcur = strchr(strcur, sep);
                if(strcur)
                        *strcur++ = '\0';
        }
         newarrybuff = realloc(arry, sizeof(char*) * (i+1));
         if (!newarrybuff) {
                 free(arry);
                 return NULL;
         }
         arry = newarrybuff;
         arry[i++] = NULL;

         newarrybuff = realloc(arry, sizeof(char*) * (i+1));
         if (!newarrybuff) {
                 free(arry);
                 return NULL;
         }
         arry = newarrybuff;
         arry[i++] = tmpstr;

         return arry;
}

void strsplitfree(char * const *p)
{
        if (!p) return;

        char * const *tmp = p;
        while (*tmp++);
        free(*tmp);
        free((void*)p);
}

int main(int argc, char **argv)
{
        char str[] = "::::hello::wold:";
        char * const *s = strsplit(str, ':');
        int j=0;
        if (s == NULL)
                return 1;
        for (j = 0; s[j] != NULL; j++) {
                printf("%s\n", s[j]);
        }

        strsplitfree(s);
        return 0;
}

```

---

<div class="post-metadata">

**Author:** ![achenle](https://community.unix.com/letter_avatar/achenle/32/5_5575768a8748004e209b776fc1b2916d.png) [@achenle](https://community.unix.com/u/achenle)\
**Post date:** [May 18, 2011, 9:51am UTC](https://community.unix.com/t/need-some-advice-on-my-implementation-of-strsplit-using-c/288230/2 "2011-05-18T09:51:43Z")

</div>

First, use strdup() to duplicate a string on the heap.

Second, don't duplicate each and every substring - duplicate the entire string and just split it by replacing the separators with NULs, filling in your pointer array as you go. (Yes, it's spelled "NUL". That's the '\0' character.)

Something like this:

```nohighlight
#include <string.h>
#include <strings.h>
#include <stdio.h>
#include <stdlib.h>

char **strsplit( const char *str, char sep )
{
    char *pp;
    char *qq;
    unsigned int sepCount;

    char *newStr = strdup( str );

    // count the separators
    for ( pp = newStr, sepCount = 0; *pp; pp++ )
    {
         if ( sep == *pp ) sepCount++;
    }

    // N separators means N + 1 strings, plus we need
    // a NULL terminator at the end of the pointer array
    char **result = calloc( 2 + sepCount, sizeof( *result ) );

    // first result is the start of the original string
    result[0] = newStr;

    // now split the string by inserting NUL characters
    // in place of separators, and filling in the pointer
    // array as we go
    pp = newStr;
    sepCount = 1;
    for ( ;; )
    {
        // find the next separator
        qq = strchr( pp, sep );
        if ( NULL == qq ) break;

        // replace it to split the string
        *qq = '\0';

        // point at the start of the next sting
        pp = qq + 1;

        // fill in the array with the next string
        result[sepCount] = pp;

        sepCount++;
    }

    return( result );
}

void freesplit( char **split )
{
    free( split[0] );
    free( split );
}

int main( int argc, char **argv )
{
    char **split;

    int ii;
    int jj;

    for ( ii = 1; ii < argc; ii++ )
    {
        split = strsplit( argv[ii], ':' );
        for ( jj = 0; split[jj]; jj++ )
        {
            printf( "string[%d] = '%s'\n", jj, split[jj] );
        }

        freesplit( split );
    }

    return( 0 );
}

```

---

<div class="post-metadata">

**Author:** ![jim\_mcnamara](https://community.unix.com/letter_avatar/jim_mcnamara/32/5_5575768a8748004e209b776fc1b2916d.png) [@jim\_mcnamara](https://community.unix.com/u/jim_mcnamara)\
**Post date:** [May 18, 2011, 4:58pm UTC](https://community.unix.com/t/need-some-advice-on-my-implementation-of-strsplit-using-c/288230/3 "2011-05-18T16:58:53Z")

</div>

Here is an old utility. It splits string from the command line, it also has extra stuff you should probably ignore: parsing options, formatting output.  
There are two files:

ssplit.c  
classes.c

make:

```nohighlight
[g]cc classes.c ssplit.c -o ssplit

```

---

<div class="post-metadata">

**Author:** ![vistastar](https://community.unix.com/user_avatar/community.unix.com/vistastar/32/2003_2.png) [@vistastar](https://community.unix.com/u/vistastar)\
**Post date:** [May 19, 2011, 1:47am UTC](https://community.unix.com/t/need-some-advice-on-my-implementation-of-strsplit-using-c/288230/4 "2011-05-19T01:47:35Z")

</div>

1, Why must use strdup but malloc and strcpy?  
2, Indeed I duplicate the entire string.  
3, Is calloc better than malloc?
