Поиск узла в древовидной структуре .txt файл - PullRequest
2 голосов
/ 27 января 2020

У меня есть файл .txt с древовидной структурой, который выглядит следующим образом:

R  R1   1        "Template for setting parameters"  ENGLISH        1                      1
U U1    "Any user"   ENGLISH   100%      1

 A A1   "Setup stim levels" 0min          0           0%           AVAILABLE FALSE FALSE TRUE TRUE

  B SA1 1 "Engine tests"
   M CH1 1 1 120mA 10us 450us 40Hz ASYM "Channel 1"
   M CH2 1 2 120mA 10us 450us 40Hz ASYM "Channel 2"
   M CH3 1 3 120mA 10us 450us 40Hz ASYM "Channel 3"

   P P0 "Phase zero" 0ms NONE 2000ms STOP STOP STOP   
    O CH1 0mA  0ms    0ms   600000ns 180us RATE
    O CH2 0mA  0ms    0ms   600000ns 180us RATE
    O CH3 0mA  0ms    0ms   600000ns 180us RATE

   P P1 "Phase one" 0ms NONE 2000ms STOP STOP STOP  
    O CH1 0mA  0ms    0ms   600000ns 180us RATE
    O CH2 0mA  0ms    0ms   600000ns 180us RATE
    O CH3 0mA  0ms    0ms   600000ns 180us RATE


@--------

Здесь каждый узел имеет только одного родителя, его ссылка уникальна среди его братьев и сестер (например, P0, P1 et c.)

Я могу искать значения в дочерних элементах (строки начинаются с "O CH"), разбивая строки следующим образом:

        QString filename = "config_keygrip";
            QString path = QCoreApplication::applicationDirPath()+"/"+filename+".txt";

            QFile originalFile(path);
            originalFile.open(QIODevice::ReadOnly | QIODevice::Text); 
            while (!originalFile.atEnd()) {
                QByteArray line = originalFile.readLine();
                if (line.contains("O CH")) {
                    QStringList list = QString::fromUtf8(line).split(' ', QString::SkipEmptyParts);

                    qDebug()<<"Extracted values are: "<< list[1]<< list[2]<<list[3]<< list[4]<< list[5]<<"and"<<list[6];
                }

            }
    originalFile.close();


Приведенный выше код дает мне значения для всех дочерних элементов.

Я немного застрял в том, как искать дочерние элементы определенного узла.

Например Нажав pushButton с именем NEXT, как попасть в узлы один за другим и извлечь дочерние значения (как указано выше)?

1 Ответ

2 голосов
/ 27 января 2020

Примечание: я предполагаю, что отступ здесь важен, ie дети более отступы, чем их родители. Также предполагается, что уровни вложенности находятся на расстоянии одного пробела.

Начнем с простой Node структуры:

struct Node {
    Node * parent;
    char tag;
    QString reference;
    QString full_line;
    QVector<Node *> children;
};

Сначала напишите функцию, которая обрабатывает строку и возвращает std::optional<std::pair<int, Node*>>. Это либо возвратит пустое значение (если нечего читать в этой строке), либо пару (уровень отступа, новый узел).

std::optional<std::pair<int, Node*>> process_line(QString line) {
    int indentation = 0;
    while (line.size() > indentation && line[indentation] == ' ') {
      indentation++;
    }
    line = line.mid(indentation);
    if (line.isEmpty())
        return std::nullopt; // This line only contains spaces, return nothing.

    Node * ret = new Node;
    ret->parent = nullptr;
    QTextStream ts(&line);
    ts >> ret->tag >> ret->reference;
    ret->full_line = line;

    return std::make_pair(indentation, ret);
}

Затем создайте al oop, который обрабатывает каждую строку файл. Следите за стеком Node * элементов, который изначально является просто root узлом. Для каждой строки в файле передайте ее read_line и реализуйте следующую логику c:

  • Если read_line вернул nullopt: ничего не делать.
  • Иначе , проверьте уровень отступа возвращаемой пары относительно текущего стека узлов:
    • Если indentation == nodes.size() - 1: это дочерний элемент текущего верхнего узла. Установите new_node->parent = nodes.top() и nodes.top()->children.push_back(new_node). Pu sh new_node на стек узлов.
    • Если indentation < nodes.size() - 1: выдвинуть nodes до indentation == nodes.size() - 1, то сделать, как указано выше.

Теперь у вас есть дерево, по которому можно перемещаться вниз (через children) и вверх (parent).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...