Search code examples
arrayscsplitdelimitercalloc

What causes the crash while using strcat and and memset?


I am trying to implement a split funtion, which receives an array of chars and a delimiter that will decide what chars go to each array in the split array.
I have a problem with strcat and memset, can somone explain my mistakes to me?

        char** split(const char* str, char delimiter)
        {
            int ch=0;
            int word=0;
            const char * zero="\0";
            unsigned int size=num_items(str,delimiter);   

            /* get the size of split[][] */
    
            char** split= calloc(size+1,sizeof(char*));
            for(int i=0; i<strlen(str); i++) 
            {
                if(ch==0)
                { 
                    memset(split[word],'\0',1);

                    /* set the first value to '\0' */

                    ch++;
                }
                if(str[i]!=delimiter)
                {
                    /* adding char by char to the split */
                    strcat(split[word],&str[i]);
                    ch++;
                }else{
                    ch=0;
                    word++;
                }
            }
            return split;
        }

Solution

  • Memory needs to be allocated for the pointers and the strings they point to.
    For a single character, it can be assigned directly. No need for strcat and strcat expects pointers to zero terminated strings.

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    
    char** split(const char* str, char delimiter)
    {
        char** split= NULL;
        int ch=0;
        unsigned int size=0;
        size_t len = strlen ( str);
    
        for(int i=0; i<len; i++)
        {
            if(ch==0)
            {
                char** temp= realloc(split, sizeof *split * (size+2));//allocate pointer
                if ( ! temp) {
                    fprintf ( stderr, "problem malloc\n");
                    return split;
                }
                split = temp;
                split[size] = calloc ( 1, len + 1);//allocate for string
                if ( ! split[size]) {
                    fprintf ( stderr, "problem calloc\n");
                    return split;
                }
                split[size + 1] = NULL;//sentinel
            }
            if(str[i]!=delimiter)
            {
                split[size][ch] = str[i];//assign character
                ch++;
            }else{
                size_t length = strlen ( split[size]);
                char *tmp = realloc ( split[size], length + 1);//reallocate to exact size
                if ( ! tmp) {
                    fprintf ( stderr, "problem realloc\n");
                    return split;
                }
                ch=0;
                size++;
            }
        }
        return split;
    }
    
    int main ( void) {
        char **words = NULL;
        char *text = "a bc def ghij klmno pqr st u v  wzyx";
        char space = ' ';
    
        words = split ( text, space);
    
        int each = 0;
        while ( words && words[each]) {
            printf ( "%s\n", words[each]);
            ++each;
        }
        each = 0;
        while ( words && words[each]) {
            free ( words[each]);
            ++each;
        }
        free ( words);
    
        return 0;
    }