user1119522
user1119522

Reputation: 21

Split string into dynamic array

I have a char array given to me by a user or an application "Hello,My,Name,Is,Test".

What I need to be able to do is split this on the comma store this in an dynamic array as I will never know the number of commas or the size of the string.

I need to store this so each item can be requested individually by another method like

GetItem(int index)
{   
   ... 
   return Array[index];
   ...
} 

Upvotes: 0

Views: 2615

Answers (2)

LSerni
LSerni

Reputation: 57418

If you don't know and have not even an upper limit to the numbers of commas in the string, you have to parse the string and dynamically reallocate the array. There are several strategies, and the one below isn't really optimal, being conducive to memory fragmentation, but it's simple to describe.

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

int main()
{
    char *str       = "This,is,a,comma,delimited,string,with,a,length,of,whatever";
    char **array    = NULL;
    char *p;
    size_t  items = 0, q;
    char *sepa      = ",";

    p = str;
    for (;;)
    {
            p += strspn(p, sepa);
            if (!(q = strcspn(p, sepa)))
                    break;
            if (q)
            {
                    array           = realloc(array, (items+1) * sizeof(char *));
                    array[items]    = malloc(q+1);
                    strncpy(array[items], p, q);
                    array[items][q] = 0;
                    items++;
                    p += q;
            }
    }
    for (q = 0; q < items; q++)
    {
            printf("(%s) ", array[q]);
    }
    printf("\n");

    /* Here we have a problem. How do we return to the caller the information
       about how many items do we have? A common solution is to return the number
       of items PLUS ONE, and that one is NULL */

    array           = realloc(array, (items+1) * sizeof(char *));
    array[items]    = NULL;

    /* So this code can work without needing to know the value of "items" */
    for (q = 0; array[q]; q++)
            printf("(%s) ", array[q]);
    printf("\n");
}

BTW, I have omitted to check whether realloc (or malloc) returns NULL, signifying a memory error.

An alternative allocation strategy is to use realloc in chunks, i.e., you keep two counters, items and really_allocated_items, and only realloc when the two are equal. When you do, you increment really_allocated_items by, say, 64, and realloc that number of items. This way, you only run one allocation every 64, and waste at most 63 pointers.

Other strategies exist, using an incrementing chunk size instead of the fixed 64, but they are only implemented when memory and performance constraints are really tight.

NOTE this implementation intentionally does not use strtok, because strtok modifies the original string and in some cases this might not be allowed (might even gain you a coredump).

Upvotes: 1

Omkant
Omkant

Reputation: 9214

Just simple implementation using strtok() of maximum word length of less than 10

You can do it in other way also, for this don't forget to #include<string.h>

char str[] = "Hello,My,Name,Is,Test";
char delims[] = ",";
char *result =NULL;
char final[10][10];
int i=0;
result = strtok( str, delims );
strcpy(final[i],result);
i++;
while( result != NULL ) {
    result = strtok( NULL, delims );
    strcpy(final[i],result);
    i++;
}

Footnote : Here first call to strtok() uses str as the first parameter but all subsequent calls has NULL

Upvotes: 0

Related Questions