简体   繁体   中英

Implementing a C function that splits a string on a given character and returns an array of strings after the split (along with length of array)

I'm trying to implement a C function that takes a string and then breaks that string on a certain character and returns back an array of strings after the split along with the size of that array. I'm using a data structure for this since returning a 2D array (the array of strings after the split) and its length is not possible. My code is given below:

struct charArr {
    char *arr[10000];
    int size;
};    

struct charArr *stringSplitter(char *str, char c) {
    struct charArr *splitString = (struct charArr *)malloc(sizeof(struct charArr));
    if (splitString == NULL) {
        fprintf(stderr, "malloc failed\n");
        exit(1);
    }
    splitString->size = 0;
    int i = 0;
    int j = 0;

    while (str[i] != '\0') {
        if (str[i] == c) {
            splitString->arr[splitString->size][j] = '\0';

            (splitString->size)++;
            j = 0;
            i++;

            while (str[i] == c) {    /* this loop is to ignore continuous occurrences of the character c */
                i++;
            }
        } else {
            splitString->arr[splitString->size][j] = str[i];
            i++;
            j++;
        }
    }
    splitString->arr[splitString->size][j] = '\0';
    return splitString;
}

int main(int argc, char *argv[]) {

    // take input from command line
    if (argc == 1) {
        //buffer to store lines
        size_t buffer_size = 128;
        char *buffer = malloc(buffer_size * sizeof(char));
        if (buffer == NULL) {
            fprintf(stderr, "malloc failed\n");
            exit(1);
        }

        // loop continuously till user exits by ctrl+c
        while (1) {
            printf("Enter Input> ");
            getline(&buffer, &buffer_size, stdin);

            char *str = strdup(buffer);

            struct charArr *splitString = stringSplitter(str, '&');

            for (int i = 0; i<splitString->size; i++) {
                printf("%s ", splitString->arr[i]);
            }
        }
    }
    return 0;
}

On running the code on a simple input like (the input is continuously taken from the command line):

Enter Input> this & that

I expect the output to be:

this that

But, I'm getting the error:

Segmentation fault (core dumped)

If the input is as shown below (ie; continuous occurrences of the splitting character):

Enter Input> this &&& that

then also the output must be:

this that

Edit: I'm trying to extend this to split a string on multiple delimiters as well (in one go), so instead of char c in the above function, if char *c is passed which is a string of delimiters (example c = " \\t\\n" to remove all white spaces from given string), then also it should work as expected and return an array of strings after the split and length of array. For example, if input is (multiple spaces, tabs and newline):

Enter Input>      this                               that         

Then the array returned (which is a part of the returned structure) must be of size 2 and only contain the 2 strings - "this" and "that".

Here's a rewrite of your function with the corrections that you need for proper allocation of each found string using strdup():

You can find my modifications preceded with comments that start 'Previously':

struct charArr* stringSplitter(char *str, char c){
    struct charArr* splitString = (struct charArr*)malloc(sizeof(struct charArr));
    char buffer[ MAX_BUFF ] ;
    if(splitString == NULL){
        fprintf(stderr, "malloc failed\n");
        exit(1);
    }
    splitString->size = 0;
    int i=0;
    int j=0;

    while(str[i] != '\0'){

        if(str[i] == c){
            //Previously:  splitString->arr[splitString->size][j] = '\0';
            splitString->arr[splitString->size] = strndup( buffer , j ); 

            (splitString->size)++;
            j = 0;
            i++;

            while(str[i] == c){    /* this loop is to ignore continuous occurrences of the character c */
                i++;
            }
        } else {
            // Previously:  splitString->arr[splitString->size][j] = str[i];
            buffer[j] = str[i];
            i++;
            j++;
        }

    }
    //Previously:  splitString->arr[splitString->size][j] = '\0';
    splitString->arr[splitString->size++] = strndup( buffer , j ); 
    return splitString;
}

It's been a long time since I wrote any C so I thought this would be a challenge. Here's a rewrite of the stringSplitter function.

struct charArr* stringSplitter(char *str, char c){
    struct charArr* splitString = (struct charArr*)malloc(sizeof(struct charArr));
    if(splitString == NULL){
        fprintf(stderr, "malloc failed\n");
        exit(1);
    }
    splitString->size = 0;
    char sep[2];
    sep[0] = c;
    sep[1] = (char) 0;

    char* next;
    while( (next = strtok( str, sep )) )
    {
      str = NULL;
      splitString->arr[ splitString->size++ ] = next;
    }

    return splitString;
}

Above, I'm simply using strtok . Take a look at the manpage for strtok() to see it's nuances.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM