Как разобрать строку, которая представляет древовидную структуру данных - PullRequest
0 голосов
/ 18 октября 2018

У меня есть строка в форме:

0002010212431438742295520465365303566540810000.005802NG5917Arinfbnuattest4086005Lagos61052340163049091

, состоящая из трех или более 100 * *1006* элементов, каждый из которых состоит из трех или трех элементов, таких как 1001 *, в каждом из которых по 1007 *, равных 100 * *1006*, в каждом из которых по 1007 элементов, таких как 1001 *, необходимо объединить по три элемента в каждом*

struct token {
    string id;
    int length;
    string value;
};

Каждый токен можно идентифицировать, используя его первый текст (длиной 2) (от 00 до 99), который является его идентификатором.Затем за идентификатором следует числовое значение, которое представляет длину значения, следующего за элементом, за которым следует длина.

Проблема здесь в том, что некоторые идентификаторы (токены) также представляют коллекцию токенов с каждым изих идентификатор начинается с 00 ... Я пытался решить его таким образом ...

tlv* Decoder::parsetlv(std::string data)
{
    tlv* root = new tlv();

    tlv* tlv_list = root;
    tlv* temp = nullptr;


    for (size_t index = 0; index < data.length(); temp = tlv_list, tlv_list = tlv_list->next) {

        if (!tlv_list) {
            temp->next = new tlv();
            tlv_list = temp->next;
        }


        tlv_list->Id = data.substr(index, 2);
        auto tempId = tlv_list->Id;
        index = index + 2;

        tlv_list->length = data.substr(index, 2);
        index = index + 2;

        int length = atoi(tlv_list->length.c_str());
        tlv_list->value = data.substr(index, length);
        if (any_of(_parentTagsIdentifiers, 72, tlv_list->Id)) {
            //place of horror
            tlv_list->child = tlv_list;

        }
        index = index + length;

    }

    return root;
}

Проблема, которую я обнаружил в своей реализации, заключается в том, что дочерний идентификатор путают как родительский идентификатор, так как они имеют одинаковыеid, где как иное, заключается в том, что родительский идентификатор находится под так называемым корневым идентификатором, в то время как дочерний идентификатор находится под (после) другого идентификатора, который в этом случае называется идентификатором шаблона.

В моей реализации яЯ использую какой-то связанный список, но идеи с использованием любого контейнера C ++ приветствуются.

EDIT

это реализация, которая использовала декодер ()

const char* doToString(const char * dataId)
{
if (strncmp("00", dataId, 2) == 0) {
    return "Payload Format";
}
else if (strncmp("01", dataId, 2) == 0) {
    return "Point of Initiation Method";
}
else if (strncmp("02", dataId, 2) == 0) {
    return "Visa Card id";
}
else if (strncmp("52", dataId, 2) == 0) {
    return "Merchant Category code";
}
else if (strncmp("53", dataId, 2) == 0) {
    return "Transaction Currency Code";
}
else if (strncmp("54", dataId, 2) == 0) {
    return "Transaction Amount";
}
else if (strncmp("55", dataId, 2) == 0) {
    return "Tip or Convinience Indicator";
}
else if (strncmp("56", dataId, 2) == 0) {
    return "Value of Convinience Fee Fixed";
}
else if (strncmp("57", dataId, 2) == 0) {
    return "Value of Convinience Fee Fixed";
}
else if (strncmp("58", dataId, 2) == 0) {
    return "Country Code";
}
else if (strncmp("59", dataId, 2) == 0) {
    return "Merchant Name";
}
else if (strncmp("60", dataId, 2) == 0) {
    return "Merchant City";
}
else if (strncmp("61", dataId, 2) == 0) {
    return "Merchant Postal Code";
}
else if (strncmp("62", dataId, 2) == 0) {
    return "Additional Data Field Template";
}
else if (strncmp("63", dataId, 2) == 0) {
    return "Cyclic Redundancy Check";
}
else if (strncmp("64", dataId, 2) == 0) {
    return "Merchant Info Lang Template";
}
}

void realTostring(string data) {
Qr::Decoder dec;
const Qr::tlv* head = dec.parsetlv(data);
const Qr::tlv* qr = head;
string name;
while (qr) {
    if (!qr->child) {
        std::cout << doToString(qr->Id.c_str()) << " " << qr->length << " " 
  << qr->value << std::endl;
    }
    else if(qr->child) {
        std::cout << qr->Id;
        std::cout << "Additional Child" <<" "<< qr->child->Id << " "
   << qr->child->length <<" "<<qr->child->value << std::endl;
    }
    qr = qr->next;
}
deleteTlv(head);
}

это вывод

Payload Format 02 01
02Additional Child 02 12 431438742295
Merchant Category code 04 6536
Transaction Currency Code 03 566
Transaction Amount 08 10000.00
Country Code 02 NG
Merchant Name 17 Arinfbnuattest408
Merchant City 05 Lagos
Merchant Postal Code 05 23401
Cyclic Redundancy Check 04 9091

из выходной второй строки, он показывает, что обрабатывает токен с идентификатором 02 как дочерний идентификатор для идентификатора шаблона 62, потому что tу них одинаковый идентификатор вторая строка должна быть для карты Visa id

1 Ответ

0 голосов
/ 18 октября 2018

Ниже приведен пример кода для преобразования данных в формат TLV. Посмотрите, как это работает :

#include <iostream>
#include <vector>
#include <string>
#include <cstdio>
using namespace std;

class TLV
{
    public:

        string tag;
        unsigned int length;
        string value;

        TLV(string data)
        {
            value = "";
            //If there is enough data
            if(data.length() >= 4)
            {
                tag = data.substr(0,2);
                sscanf(data.substr(2,4).c_str(),"%2x",&length);

                //If there is enough data
                if(data.length() >= 4 + length*2) value = data.substr(4,length*2);
            }
        }

        static void parseTLV(string data, vector<TLV*> &res)
        {
            while(data.length() >= 4)
            {
                TLV *t = new TLV(data);
                if(t->value == "") break;
                res.push_back(t);
                data = data.substr(4+(t->length+t->length));
            }

            if(data.length() != 0)
            {
                //Whole data is not in TLV format. Can throw some error
                cout<<"ERROR [1] :: ["<<data<<"]\n";
            }
        }
};


int main()
{
    string data = "0007AAAAAAAAAAAAAA010FAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA0220AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA";
    vector<TLV*> res;
    TLV::parseTLV(data, res);
    for(TLV *t:res)
    {
        printf("%s | %02X | %s |\n",t->tag.c_str(),t->length,t->value.c_str());
    }
    return 0;
}
...