1

I'm pretty new to C and can figure out why this function doesn't work consistently whatsoever:

char **splitString(char *string) {
    char *token = strtok(string, ","), **finalValue = NULL, **temp = NULL;
    size_t wordIndex = 0;
    while (token != NULL) {
        temp = realloc(finalValue, sizeof(char *));
        if (!temp) {
            freeArray(finalValue);
            finalValue = NULL;
            break;
        }
        temp[wordIndex] = malloc((strlen(token)+1)*sizeof(char));
        if (temp[wordIndex] == NULL) {
            freeArray(finalValue);
            finalValue = NULL;
            break;
        }
        strcpy(temp[wordIndex], token);
        printf("%s\n", temp[wordIndex]);
        finalValue = temp;
        printf("%s\n", finalValue[wordIndex]);
        wordIndex++;
        token = strtok(NULL, ",");
    }
    return finalValue;
}

It receives a string separated by commas and its supposed to split them into different strings, all of which were created via malloc/realloc.

2
  • 1
    temp = realloc(finalValue, sizeof(char*)); allocates memory for a single pointer. What’s the point? Commented Dec 18, 2021 at 17:50
  • idk how many strings I'll have to create from the original so with each iteration, I created a place for another string Commented Dec 18, 2021 at 17:55

1 Answer 1

1

The problem is here: temp = realloc(finalValue, sizeof(char *)); reallocates for a single pointer. You should write:

temp = realloc(finalValue, (wordIndex + 2) * sizeof(char *));

You should also set a NULL pointer at the end of the finalValue array to mark the end of this array as the number of entries is not returned by the function in any other way.

Also note that the allocated strings are not freed when realloc() or malloc() fails.

Furthermore, you should not use strtok() because it modifies the source string. An alternative approach with strspn(), strcspn() or manual testing and strndup() is recommended.

Finally, strtok() has another shortcoming which may be counterproductive: it considers any sequence of separators as a single separator and does not produce empty tokens. This is fine if you use whitespace as separator but probably incorrect for "," where you might expect "a,,c" to produce 3 tokens: "a", "" and "c".

Here is a modified version that can handle empty tokens:

char **splitString(const char *string) {
    const char *p0, *p0;
    size_t i = 0, n = 1;
    char **array;

    for (p = string; *p; p++) {
        if (*p == ',')
            n++;
    }
    array = calloc(sizeof(*array), n + 1);
    if (array != NULL) {
        array[n] = NULL; /* set a null pointer at the end of the array */
        for (p = p0 = string, i = 0; i < n;) {
            if (*p == ',' || *p == '\0') {
                if ((array[i++] = strndup(p0, p - p0)) == NULL) {
                    /* allocation failure: free allocated strings and array */
                    while (i --> 0)
                        free(array[i]);
                    free(array);
                    array = NULL;
                    break;
                }
                if (*p == ',')
                    p0 = ++p;
                else
                    p0 = p;
            } else {
                p++;
            }
        }
    }
    return array;
}

strndup() is a POSIX function available on many systems and that will be part of the next version of the C Standard. If it is not available on your target, here is a simple implementation:

char *strndup(const char *s, size_t n) {
    char *p;
    size_t i;
    for (i = 0; i < n && s[i]; i++)
        continue;
    p = malloc(i + 1);
    if (p) {
        memcpy(p, s, i);
        p[i] = '\0';
    }
    return p;
}
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.