Примечание: я предполагаю, что отступ здесь важен, 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
).