C / parse string, какой самый простой способ - PullRequest
0 голосов
/ 28 октября 2011

У меня есть такая строка: 4;4=3;1=0,2=2,3=1,4=1,5=1;0003013340f59bce000002aaf01620e620198b2240002710;

Она разделена на разделы знаком ";"и каждый раздел может иметь одну или несколько пар ключ / значение, например 5 = 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;
        }

Я не уверен, как это сделать правильно.Это также усложняется тем, что не каждая строка имеет одинаковую структуру, иногда могут присутствовать только один или два раздела.Например: 3;4=3;1=0,2=2,3=1,4=1,5=1;

Есть ли how to, показывающий лучший и наиболее удобный способ?

Ответы [ 2 ]

2 голосов
/ 28 октября 2011

strtok нельзя, AFAICR, использовать во вложенных циклах, подобных этому, из-за глобального состояния, которым он управляет сам.Я предлагаю сначала разобрать каждую часть, разделенную точкой с запятой, затем обработать их последовательно - или просто реализовать что-то вроде strtok для вашего случая с точкой с запятой, а затем с радостью использовать strtok во внутреннем цикле.

1 голос
/ 28 октября 2011

Использование strcspn ().Исправлены буферы, результаты попадают в глобальные переменные.буфер данных [] изменен (и поэтому должен быть доступен для записи).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;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...