This would be better handled using an HTML/XML parser (depending on what your file actually contains).
That being said, you are not parsing the lines correctly.
Your first call to getline(in,t.tag);
is not specifying a delimiter, so it reads the entire line, not just the first word. You would have to use getline(in, t.tag, ' ');
instead.
Also, your tags can have multiple attributes, but you are only reading and storing the first attribute, ignoring the rest. You need a loop to read all of them, and a std::vector
to store them all into.
Try something more like this instead:
#include <iostream>
#include <sstream>
#include <string>
#include <vector>
#include <fstream>
using namespace std;
struct tagattribute {
string name;
string value;
};
struct tagline {
string tag;
vector<tagattribute> attributes;
};
int main() {
vector<tagline> information;
string line;
ifstream readFile("file.txt");
while (getline(readFile, line)) {
istringstream in(line);
tagline t;
tagattribute attr;
in >> ws;
char ch = in.get();
if (ch != '<')
continue;
if (!(in >> t.tag))
continue;
do
{
in >> ws;
ch = in.peek();
if (ch == '>')
break;
if (getline(in, attr.name, '=') &&
in.ignore() &&
getline(in, attr.value, '"'))
{
t.attributes.push_back(attr);
}
else
break;
}
while (true);
information.push_back(t);
}
vector<tagline>::iterator it = information.begin();
for(; it != information.end(); ++it) {
cout << "Tag: " << it->tag << "\n";
vector<tagattribute>::iterator it2 = it->attributes.begin();
for(; it2 != it->attributes.end(); ++it2) {
cout << "name: " << it2->name << "\n"
<< "value: " << it2->value << "\n";
}
cout << "\n";
}
return 0;
}
Live demo
Alternatively, consider writing some custom operator>>
to help with the parsing, eg:
#include <iostream>
#include <sstream>
#include <string>
#include <vector>
#include <fstream>
using namespace std;
struct tagattribute {
string name;
string value;
};
istream& operator>>(istream &in, tagattribute &attr)
{
getline(in, attr.name, '=');
in.ignore();
getline(in, attr.value, '"');
return in;
}
struct tagline {
string tag;
vector<tagattribute> attributes;
};
istream& operator>>(istream &in, tagline &t)
{
tagattribute attr;
in >> ws;
char ch = in.get();
if (ch != '<')
{
in.setstate(ios_base::failbit);
return in;
}
if (!(in >> t.tag))
return in;
do
{
in >> ws;
ch = in.peek();
if (ch == '>')
{
in.ignore();
break;
}
if (!(in >> attr))
break;
t.attributes.push_back(attr);
}
while (true);
return in;
}
int main() {
vector<tagline> information;
string line;
ifstream readFile("file.txt");
while (getline(readFile, line)) {
istringstream in(line);
tagline t;
if (in >> t)
information.push_back(t);
}
vector<tagline>::iterator it = information.begin();
for(; it != information.end(); ++it) {
cout << "Tag: " << it->tag << "\n";
vector<tagattribute>::iterator it2 = it->attributes.begin();
for(; it2 != it->attributes.end(); ++it2) {
cout << "name: " << it2->name << "\n"
<< "value: " << it2->value << "\n";
}
cout << "\n";
}
return 0;
}
Live demo