Magnarok Magnarok - 2 months ago 21
C Question

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;
}

Answer

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;
}