C /文字列を解析する、最も簡単な方法は何ですか

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

";"で区切られています。各セクションには、5 = 1などのような1つ以上のキーと値のペアを持つことができます。 私は純粋なCでそれを解析したいと思いますし、私はここでコードで示しているように strtok

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;

最も便利な方法を示す方法がありますか?

0
私はあなたが正しい選択をしたと思うstrtok()と行くつもりです。これはLex/Yaccのようなものに行きたいと思うような(私には、私には)見えません(しかし、もしそうなら、Antlr antlr.org 私はグラフィックデバッガが本当に好きです)
追加された 著者 Mawg,
あなたのケースでは「最高」を定義するか、節を削除してください。
追加された 著者 Grant Thomas,
私は言う:分割し、征服する。まず、行を3つのセクションに分割し、 ';'で区切ります。別のセクションを扱うよりも、おそらくサブ関数内にあるかもしれません。サブ関数は空のセグメントも扱うことができます。
追加された 著者 wildplasser,
本当。 「最も簡単に」に変更されました:)
追加された 著者 nyyrikki,

2 答え

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.

2
追加された

strcspn()の使用。固定バッファー、結果はグローバル変数に入ります。 data []バッファが変更されています(書き込み可能である必要があります)。 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 
#include 
#include 

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;
}
1
追加された