Home > Enterprise >  Converting a comma separated string to array
Converting a comma separated string to array

Time:11-06

I have been trying to convert a string in array of integers, floats and characters. While I could get it work for integers and floats, there is some problem for characters.

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

int main()
{
    char *s1;
    int k, no=5;
    char* variable = "R1,R2,R3,R4,R5";
    void* value;

    s1 = calloc(no,sizeof(char)*81);
    for (k=0; k<no; k  ) s1[k] = strdup(mchar);
    ListChar(variable, s1, no, ",");
    memcpy(value, s1, no*sizeof(char)*81);
    free(s1);

    int i;
    for (i = 0; i < no; i  )
        printf("%s", value[i]);
    printf("\n");
    return 0;
}

In the header file I have

#define mchar "A...(81times)" 

Implementation:

int ListChar(char *buf, char *list, int maxloop, char* delim)
{
    int n = 0;
    char *s,*t;
    s= strdup(buf);
    t= strtok(s,delim);
    while ( t && (n<maxloop))
    {
        if (list!=NULL) list[n] =strdup(t);
        n  ;
        t=strtok(NULL,delim);
    }
    free(s);
    return(n);
}

During the calloc memory assignment when I watch s1 its 0xsomeadress "" After the for loop s1 becomes 0xsomeadress "Garbage value 81 times" When s1 is assigned to list its still reads the same garbage value. And when list [n] = strdup(t) list[0] reads the first block of garbage value like -21 '\221 ṗ'.

t is getting delimited correctly. I even tried initializing char *s1[81] = {"something"} and looping it on j but it wont work, same problem, and I need to free s1 at the end because this function runs for number of times. I did it for integers and floats by list[n]=atoi(t) it works fine. Can anyone suggest me something?

CodePudding user response:

There seems to be a fundamental misunderstanding about how strings work. Your s1 clearly needs to be a char ** and the usage of strdup is incorrect. If s1 is of type char *, then s1[k] is of type char. But strdup returns a char *, so s1[k] = strdup ... is clearly an error which your compiler ought to warn you about. Perhaps you want something like:

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

void * xmalloc(size_t s);

void
ListChar(const char *buf, char **list, int maxloop, int delim)
{
    char set[] = {delim, 0};
    for( int n = 0; n < maxloop; n  = 1 ){
        size_t len = strcspn(buf, set);
        list[n] = xmalloc(len   1);
        memcpy(list[n], buf, len);
        buf  = len   1;
    }
}

int
main(int argc, char **argv)
{
    int delim = ',';
    (void)argc; /* Suppress compiler warning */
    while( *  argv ){
        char **s1;
        int k, num = 1;
        char *input = *argv;
        for( const char *p = input; *p; p  = 1 ){
            if( *p == delim ){
                num  = 1;
            }
        }
        s1 = xmalloc(num * sizeof *s1);
        ListChar(input, s1, num, delim);
        for( int i = 0; i < num; i  = 1 ){
            printf("%s\n", s1[i]);
        }
        free(s1);
    }
    return 0;
}


void *
xmalloc(size_t s)
{
    void *rv = malloc(s);
    if( rv == NULL ){
        perror("malloc");
        exit(EXIT_FAILURE);
    }
    return rv;
}

Note that the above code scans each string twice, which is not ideal. Rather than scanning the string to find the number of delimiters and then parsing the string, it would be better to do both in one pass. But for the purposes of demonstrating how to break up the string, that seems like unnecessary complexity. (Though it's actually simpler, IMO)

  • Related