I am currently trying to read in characters into a class that looks like this
struct data {
string segment; string name;
double length; double radius; double wall_thickness;
double young_modulus; double compliance;
};
I also have a vector that contains the following elements:
2A
Aorta_Ascendens
2
1.47
.164
4
53.4
2B
Aorta_Ascendens
2
1.44
.161
4
51.0
3A
I want to read in the text file into each part, and currently this is my algorithm to continuously read through the text file and add each part respectively.
int place = 0;
while (place != temp_data.size()){
int counter = 0;
for (counter; counter <= 7; ++counter){
istringstream is(temp_data[place + counter]);
if (counter == 0){ is >> a.segment; }
if (counter == 1){ is >> a.name; }
if (counter == 2){ is >> a.length; }
if (counter == 3){ is >> a.radius; }
if (counter == 4){ is >> a.wall_thickness; }
if (counter == 5){ is >> a.young_modulus; }
if (counter == 6){ is >> a.compliance; }
}
counter = counter - 1; //since the next segment is at temp_data[7], must subtract one to have place = 7.
place = counter + place;
v.push_back(a);
}
The problem I ran into is trying to find a way to make sure the right part of the text goes into the right part of the object. for the first seven lines of text the object should be like this :
segment: 2A
name: Aorta_Ascendens
length: 2
radius: 1.47
wall_thickness: .164
young modulus: 4
compliance: 53.4
This should repeat the same way for the whole of the text file. temp_data is a vector that holds the elements that need to be added into the object, but I cant find a good way to continually cycle through the vector and put the elements into the right place.
The algorithm I made has a counter and a place holder, the counter would cycle through the vector points and the place holder would hold spot for the first object's data member, in this case segment. At the end of the algorithm, place should equal the size of temp_data and get out of the loop. But I am having a problem when it compiles and runs, it seems to be putting the wrong element into the wrong object member.
Any ideas?
Well you could use a more classic approach of using a mapping in your fileformat (that is, if you have access to the spec (the content) of your files).
You already give the perfect example of what your text should look like:
What's the problem with that format ? So it gives better flexibility (safety) because you can check for sure that a member is what you expect to read. You could separate objects with a delimiter:
Use ifstream.readlines() to get an array of C++ style strings, which will help you parse using
find()
function (returnsstring::npos
if not found).In the Parse() function it involves iterating over the lines of the file, first, use
find
to look for:
character, takes the left part usingsubstr
to check which member to assign the value (and how to parse, integer, enumeration ?...) and anothersubstr
with a little calculation (egsize - posfound
) to take the right part, and put that into yourlexical_cast
of choice. Eitherboost::lexial_cast
orstd::istringstream
.Otherwise, you have the choice of using
boost::serialization
which will let you write only one super simple function to read this kind of formats. (cf annex)Or more complex data binding frameworks like Code Synthesis XSD (Xerces?):
http://www.codesynthesis.com/products/xsd/
And even more simple, use python. you just have to do
eval()
PS: Annex (with
boost::serialization
) taken from the doc :isn't it stupid simple ? and its guaranteed to work. (well as long as you wrote the file with the same serializer).
refer to http://www.boost.org/doc/libs/1_55_0/libs/serialization/doc/index.html
A simple, clean way to approach this is to write a custom streaming operator:
No
temp_data
,istringstream
orcounter
.To use this:
(There are more declarative ways to use Standard algorithms and
back_inserter
iterators to copy from the stream to the vector, but IMHO simple and obvious is good)