nyyrikki
nyyrikki

Reputation: 1486

C / parse string, what is the easiest way

I have a string like that: 4;4=3;1=0,2=2,3=1,4=1,5=1;0003013340f59bce000002aaf01620e620198b2240002710;

It is separated into sections by ";" and each section can have one or more key/value pairs like 5=1 and so on, as you can see. I want to parse it in pure C and I started working with strtok as I am showing in code here:

const wuint8 section_delimiter[] = ";";
const wuint8 field_delimiter[] = ",";
const wuint8 value_delimiter[] = "=";

printf("%s\n",data->msg);

token = strtok(data->msg,section_delimiter);

while(token != NULL) {
    indicator = atoi(token);
    printf("indicator: %d\n", indicator);
    switch(indicator) {
        case TYPE_1: {
            printf("type: %d\n",TYPE_1);
            wuint16 i, headerType, headerSubType;

            for(i = 1; i < TP_MAX; i++) {
                if(i == atoi(token)) {
                    token = strtok(NULL,value_delimiter);
                    headerType = i;
                    headerSubType = atoi(token);
                    break;
                }
            }
            break;
        }
        case TYPE_2: {
            printf("type: %d\n",TYPE_3);
            break;
        }
        case TYPE_3: {
            printf("type: %d\n",TYPE_3);
            break;
        }
        case TYPE_4: {
            printf("type: %d\n",TYPE_4);
            break;
        }

I am not sure how to do that correctly. It also gets complicated, because not every string has the same structure, sometimes only one or two sections can be present. E.g.: 3;4=3;1=0,2=2,3=1,4=1,5=1;

Is there a how to do that showing the best and most convenient way?

Upvotes: 0

Views: 1286

Answers (2)

wildplasser
wildplasser

Reputation: 44250

Using strcspn(). Fixed buffers, results go into global variables. data[] buffer is altered (and thus needs to be writable). YMMV

/*
It is separated into sections by ";" and each section can have one or more 
key/value pairs like 5=1 and so on, as you can see. I want to parse it in 
pure C and I started working with strtok as I am showing in code here:
*/
char data[] = "4;4=3;1=0,2=2,3=1,4=1,5=1;0003013340f59bce000002aaf01620e620198b2240002710;" ;

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

struct header {
    int l;
    int r;
    } headers[123];

unsigned nheader;
int indicator;
char rest [123];

int tokenise(char * buff);
unsigned tokenise2(struct header *dst, char * buff);

/****************/
int tokenise(char * buff)
{
char *ptrs[14];
unsigned nptr;
unsigned len, pos;

ptrs[nptr=0] = NULL;

for (len = pos=0;  buff[pos]; pos += len ) {
    len = strcspn(buff+pos, ";");
    ptrs[nptr++] = buff+pos;
    ptrs[nptr] = NULL;
        if (!buff[pos+len] ) break;
        buff[pos+len] = 0;
    len +=1;
    }

if ( nptr> 0 && ptrs[0]) indicator = atoi(ptrs[0]); else indicator = -1;
if ( nptr> 1 && ptrs[1]) nheader = tokenise2 (headers, ptrs[1] ); else nheader = 0;
if ( nptr> 2 && ptrs[2]) nheader += tokenise2 (headers+nheader, ptrs[2] ); else nheader += 0;
if ( nptr> 3 && ptrs[3]) strcpy (rest, ptrs[3]); else rest[0] = 0;

return 0; /* or something useful ... */
}
unsigned tokenise2(struct header *target, char * buff)
{
char *ptrs[123];
unsigned nptr, iptr;
unsigned len, pos;

ptrs[nptr=0] = NULL;

for (len = pos=0;  buff[pos]; pos += len ) {
    len = strcspn(buff+pos, "," );
    ptrs[nptr++] = buff+pos;
    ptrs[nptr] = NULL;
    if (!buff[pos+len] ) break;
    buff[pos+len] = 0;
    len +=1;
    }

for ( iptr=0; iptr < nptr; iptr++) {
    if (! ptrs[iptr] ) break;
    len = strcspn(ptrs[iptr], "=" );
    if (!len) break;
    target[iptr].l = atoi (ptrs[iptr] );
    target[iptr].r = atoi (ptrs[iptr]+len+1 );
    }

return iptr; /* something useful ... */
}

int main(void)
{
int rc;
unsigned idx;

fprintf(stderr, "Org=[%s]\n", data );
rc = tokenise(data);

printf("Indicator=%d\n", indicator );
for (idx=0; idx < nheader; idx++) {
    printf("%u: %d=%d\n", idx, headers[idx].l , headers[idx].r );
    }

printf("Rest=%s\n", rest );

return 0;
}

Upvotes: 1

AKX
AKX

Reputation: 169378

strtok can't, AFAICR, be used in nested loops like this due to the global state it manages itself. I suggest parsing each semicolon-delimited part out first, then handling them sequentially - or just implement something akin to strtok for your semicolon case yourself, then happily use strtok in the inner loop.

Upvotes: 2

Related Questions