I have a text file that contains nested objects and I need to preserve the relationship between them. How would I read them? I think I need to use a data structure like a tree whose nodes can have an arbitrary number of children (sort of like an n-ary tree without the 'n' limitation). Parsing the data and building the tree in memory is tripping me up.
The data in the text file is structured as follows:
{
Element_A (3)
Element_B (3,4)
{
Element_B (6,24)
Element_A (1)
}
{
Element_A (3)
{
Element_A (4)
Element_B (12,6)
}
Element_B (1,4)
}
}
EDIT: Just to clarify, the opening/closing braces enclose a single object and all its children. Element_A and Element_B above are parts of the same object.
So far, I parse the entire file into a vector of strings like so:
vector<string> lines;
ifstream file("input.txt");
string s;
while (getline(file, s))
lines.push_back(s);
and read data from each line using something like the following
std::regex re(R"(Element_A \(\s*(\d+)\))");
std::smatch m;
if (std::regex_search(line, m, re) )
{
// extract data from 'm'
}
EDIT 2: Scheff's solution adapted to my program.
// Node is defined somewhere at the top of the file
struct Node
{
int a = 0;
int b[2] = {0};
std::vector<Node> children;
};
// this code is inside some function that does the parsing
Node root;
stack<Node*> nodeStack;
nodeStack.push(&root);
for(string line; getline(fin, line);)
{
line = trim(line); // custom function to remove leading/trailing spaces/tabs (not included in this post for brevity)
if (line.size() == 0) // empty line (data file might have empty lines for readability)
continue;
else if (line.size() == 1) // only one character
{
if (line[0] == '{')
{
nodeStack.top()->children.push_back(Node());
nodeStack.push(&nodeStack.top()->children.back());
}
else if (line[0] == '}')
{
nodeStack.pop();
}
else
cerr << "Error: Invalid character detected.\n";
}
else // at least two characters
{
regex reEl_A(R"(Element_A \(\s*(\d+)\))");
regex reEl_B(R"(Element_B \(\s*(\d+),\s*(\d+)\))");
smatch m;
if (std::regex_search(line, m, reEl_A))
{
nodeStack.top()->a = std::stoi(m[1]);
continue;
}
if (std::regex_search(line, m, reEl_B))
{
nodeStack.top()->b[0] = std::stoi(m[1]);
nodeStack.top()->b[1] = std::stoi(m[2]);
continue;
}
}
}
if (nodeStack.empty() || nodeStack.top() != &root)
{
std::cerr << "ERROR! Data not well balanced.\n";
}