Search code examples
carrayspointerssplitdouble-pointer

C - Split Slows Down My Computer


I'm trying to program a split that takes in a char-array with multiple words and separates each word into their own smaller char-array. All the pointers of the smaller char-arrays are kept in a pointer array so I can return a double pointer.

Can you take a look at my code and see if you see any errors. When I try to run my program my computer gets gradually slower, after 3-4 seconds I can't move my mouse or alt+f4 my editor. So something has to be seriously wrong!

Also I'm completely new to C-programming so I will most definitely have a silly mistake in there.

char **split(char *s) {

char **result;
int wrd_cnt = 2; //I'm adding NULL at the end of the pointer-array.


//Counts the number of words to allocate memory for the pointer-array.
for(int i = 0; i < strlen(s); i++) {
    if(s[i] == ' ') {
        wrd_cnt++;
    }
}
result = malloc(wrd_cnt * sizeof(char*));

//Counts letters in each word to allocate memory for every single small char-array with malloc.
for(int i = 0; i < strlen(s); i++) {
    for(int j = 0; j < (wrd_cnt); j++) {
        int char_cnt = 0;
        for(int k = 0; s[i] != ' ' || s[i] != '\0'; k++, i++) {
            char_cnt++;
            result[j] = malloc(char_cnt * sizeof(char));
        }
    }
}

//Puts each word into their own place in the pointer array.
for(int i = 0; i < strlen(s); i++) {
    for(int j = 0; j < (wrd_cnt); j++) {
        for(int k = 0; s[i] != ' ' || s[i] != '\0'; k++, i++) {
            result[j][k] = s[i];
        }
    }
}

result[wrd_cnt-1] = NULL;
return result;
}

Solution

  • In this situation the loops using j and k can be removed and instead increment and reset i, j and char_cnt based on the i loop as the s array is processed, similar to what you had done for wrd_cnt in the first loop

    #include <stdio.h>
    #include <string.h>
    #include <stdlib.h>
    
    char **split(char *s);
    
    int main ( void) {
        char **output = NULL;
        int each = 0;
    
        char line[99] = " string to   parse for words ";
        output = split ( line);
    
        each = 0;
        while ( output[each]) {
            printf ( "%s\n", output[each]);
            each++;
        }
        each = 0;
        while ( output[each]) {
            free ( output[each]);
            each++;
        }
        free ( output);
    
        exit ( 0);
    }
    
    char **split(char *s) {
    
        char **result;
        int wrd_cnt = 2; //I'm adding NULL at the end of the pointer-array.
        int char_cnt = 0;
        int i = 0;
        int j = 0;
        int k = 0;
    
        //Counts the number of words to allocate memory for the pointer-array.
        for(i = 0; i < strlen(s); i++) {
            if(s[i] == ' ') {
                wrd_cnt++;
            }
        }
        if ( ( result = malloc(wrd_cnt * sizeof(char*))) == NULL) {
            fprintf ( stderr, "malloc failure\n");
            exit ( 1);
        }
        //Counts letters in each word to allocate memory for every single small char-array with malloc.
        char_cnt = 1;
        j = 0;
        for( i = 0; i < strlen(s); i++) {
            if ( s[i] == ' ') {
                if ( ( result[j] = malloc(char_cnt * sizeof(char))) == NULL) {
                    fprintf ( stderr, "malloc failure\n");
                    exit ( 1);
                }
                j++;
                char_cnt = 1;
                continue;
            }
            char_cnt++;
        }
        if ( j == wrd_cnt - 2) {
            //allocate for last word
            if ( ( result[j] = malloc(char_cnt * sizeof(char))) == NULL) {
                fprintf ( stderr, "malloc failure\n");
                exit ( 1);
            }
            j++;
            result[j] = NULL;
        }
        result[wrd_cnt - 1] = NULL;//just to make sure the last pointer is null
    
        //Puts each word into their own place in the pointer array.
        j = 0;
        k = 0;
        for( i = 0; i < strlen(s); i++) {
            if ( s[i] == ' ') {
                result[j][k] = '\0';//for space only so [j][0] is '\0'
                k = 0;
                j++;
                continue;
            }
            result[j][k] = s[i];
            k++;
            result[j][k] = '\0';//for last word if there is no final space in s[]
        }
        return result;
    }