The structure is pretty simple:
- Main point
- List item – 5
- List item – 6
- …
- Main point
- List item – 2
- List item – 3
- …
To make it easier to read I have added some delimiters, Here is the actual file:
>Point one
item 1 | 150
item 2 | 20
>Point two
item 1 | 150
item 2 | 10
And I wrote a C++ function which should read it. But I have tangled somewhere in my own logic and made a mistake. Could find it for me?
ifstream fileR("file.txt");
int i = 0;
getline(fileR, sTemp);
do {
if(!sTemp.empty() && sTemp[0]==DELIM){
R[0][i] = sTemp.substr(1);
i++;
}else{
j = 0;
do {
if(!sTemp.empty() && sTemp[0] != DELIM){
string::const_iterator pos = find(sTemp.begin(), sTemp.end(), '|');
string name(sTemp.begin(), pos);
string a_raw(pos + 1, sTemp.end());
a_raw = trim(a_raw);
double amount(atof(a_raw.c_str()));
R[j+1][i].set(trim(name), amount);
j++;
}else{
break;
}
}while(getline(fileR, sTemp));
}
}while(getline(fileR, sTemp));
Where the read values are handed is not important because I tried to simplify this function because it is actually some containers with dynamic arrays. I have tested them and they do work fine. So there is a problem with reading. It seam to read the first value fine but afterwards it makes some kind of mess.
If you think my attempt is a complete disaster I would welcome hints of how to make a really working function.
EDIT:
I have a good night sleep and I have fixed it. Here is a wokrking version:
bool read = true;
for(int i = 0; i<n; i++) {
if(read){getline(fileR, sTemp);}else{ read = true; }
if(!sTemp.empty() && sTemp[0]==DELIM){
R[i].setName(sTemp.substr(1));
i--;
}else{
R[i].toFirstSubpoint();
do {
if(!sTemp.empty() && sTemp[0] != DELIM){
string::const_iterator pos = find(sTemp.begin(), sTemp.end(), '|');
string name(sTemp.begin(), pos);
string a_raw(pos + 1, sTemp.end());
a_raw = trim(a_raw);
double amount(atof(a_raw.c_str()));
R[i].setSubpoint(trim(name), amount);
R[i].toNextSubpoint();
}else{
read = false;
break;
}
}while(getline(fileR, sTemp));
}
The my most important mistake was that I forgot that if after condition is checked the loop goes to next index and does not execute the other (else) condition of it.
The answer below is actually better way to do it is much more simple and easier to understand yet I could not have used vectors this time and I am guessing that my script should be a bit quicker since it doe not use them. Anyhow next time I will run into similar situation I will use the solution below.
You should probably consider using a parsing library like boost::spirit, however if the file format is optional there are plenty of thing you can do to make it easier to parse without such measures,
Consider the following date layout
This could easily be loaded with the following.
This is wholey untested and uncompiled, but conceptually it should work.
EDIT: code changed to meet item with name and value.