1

I was making a split function in C to use its return value in some programs. But when I checked its value using printf, I discovered that there are some errors but I was unable to fix them myself. I fixed most of the errors I could.

The code I wrote is:

#include <stdio.h>
#include <string.h>

char **split(char *token, char *delimiter, int *a[], int *size_of_a) {
    int i = 0;
    char **final_result;
    char *str = strtok(token, delimiter);
    
    while (str != NULL) {
        *a[i] = strlen(str); //maybe one of the errors but I don't know how to fix it
        //even after removing a[i] by backslash and changing it in loop and main, there is still no output received in main
        getch();
        for (int j = 0; j < *a[i]; j++) { 
            final_result[i][j] = str[j];
        }
        str = strtok(NULL, delimiter);
        i++;
    }
    *size_of_a = i;
    return final_result;
}

int main() {
    char *parameter_1;
    char *parameter_2;
    int *size_1;
    int size_2;
    
    printf("Enter the token: ");
    scanf("%s", &parameter_1);
    printf("\nEnter the delimiter: ");
    scanf("%s", &parameter_2);
    
    char **result_2 = split(parameter_1, parameter_2, &size_1, &size_2);
    
    printf("\nThe result is:");
    for (int x = 0; x < size_2; x++) {
        printf('\n');
        for (int y = 0; y < size_1[x]; y++) {
            printf("%c", result_2[x][y]);
        }
    }
    getch();
    return 0;
}

How can I fix the output error?

4
  • You can't just define a pointer (char **final_result;) and use it without reserving memory ... with malloc() and frineds. Commented May 29, 2022 at 9:33
  • @pmg I do not know how to use malloc. Can you please explain how can I use malloc here? Commented May 29, 2022 at 9:38
  • malloc explanation is too large to fit in this comment Commented May 29, 2022 at 9:41
  • @pmg Ok, if possible can you please tell it in answer. Commented May 29, 2022 at 9:46

1 Answer 1

1

There are multiple problems in the code:

  • You do not allocate space for the array of pointers: final_result is uninitialized, storing anything via dereferencing it has undefined behavior, most likely a segmentation fault.

    You should use strcpn() and strspn() to compute the number of tokens, allocate the array with or without an extra slot for a NULL terminator and perform a second phase splitting the tokens and storing the pointers to the array. You might want to store copies of the tokens to avoid modifying the original string that may be constant or go out of scope.

  • printf('\n'); is invalid: you must pass a string, not a character constant.

  • scanf("%s", &parameter_1); also has undefined behavior: you pass the address of a pointer instead of a pointer to an array of char.

Here is a modified version:

#ifdef _MSC_VER
#define _CRT_SECURE_NO_WARNINGS
#endif

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

#ifdef _MSC_VER
// define POSIX function strndup if not available
char *strndup(const char *s, size_t n) {
    size_t len;
    for (len = 0; len < n && s[len]; len++)
        continue;
    char *ptr = malloc(len + 1);
    if (ptr) {
        memcpy(ptr, s, len);
        ptr[len] = '\0';
    }
    return ptr;
}
#endif

char **split(const char *str, const char *delimiters, int **a, int *size_of_a) {
    int i, count, len;
    char **final_result;
    const char *p;

    // phase 1: count the number of tokens
    p = str + strspn(str, delimiters);
    for (count = 0; *p; count++) {
        p += strcspn(p, delimiters);
        p += strspn(p, delimiters);
    }

    // phase 2: allocate the arrays
    final_result = calloc(sizeof(*final_result), count + 1);
    if (a) {
        *a = calloc(sizeof(**a), count);
    }
    if (size_of_a) {
        *size_of_a = count;
    }

    // phase 3: copy the tokens
    p = str;
    for (i = 0; i < count; i++) {
        p += strspn(p, delimiters);    // skip the delimiters
        len = strcspn(p, delimiters);  // count the token length
        if (a) {
            (*a)[i] = len;
        }
        final_result[i] = strndup(p, len); // duplicate the token
        p += len;
    }
    final_result[count] = 0;
    return final_result;
}

// read and discard the rest of the user input line
int flush_input(void) {
    int c;
    while ((c = getchar()) != EOF && c != '\n')
        continue;
    return c;
}

int main() {
    char buf[256];
    char delimiters[20];
    
    printf("Enter the string: ");
    if (scanf("%255[^\n]", buf) != 1)
        return 1;
    flush_input();
    printf("\nEnter the delimiters: ");
    if (scanf("%19[^\n]", delimiters) != 1)
        return 1;
    flush_input();
    
    int *sizes;
    int count;
    char **array = split(buf, delimiters, &sizes, &count);
    
    printf("\nThe result is:\n");
    for (int x = 0; x < count; x++) {
        for (int y = 0; y < sizes[x]; y++) {
            putchar(array[x][y]);
        }
        printf("\n");
    }
    getchar();
    return 0;
}
Sign up to request clarification or add additional context in comments.

4 Comments

Thank you. Can you please also explain with a solution, how to allocate space for the array of pointers and how to fix scanf problem?
On compiling, I am not getting any application file (exe). It says "error LNK2019: unresolved external symbol _strndup referenced in function _split" for obj file, and "fatal error LNK1120: 1 unresolved externals" for exe file.
@HimanshuBansal: strndup() is not available on your Windows system, it will be part of the next C Standard and has been available on all POSIX compliant systems for decades. I added a definition in the answer.
@HimanshuBansal: I fixed the answer. The second error was due to strndup() being defined after use in function split() where the compiler inferred a prototype of int strndup(); Move the definition of strndup() before the definition of function split() to correct this.

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.