reading a file....

Started by
16 comments, last by BlackWind 17 years, 1 month ago
Hi, i have some problem reading a file i want to parse.... it has a format like this (is a .raw file generated by milkshape3d): object1 36.065701 4.730784 1.899187 36.973099 5.891685 1.898429 34.065498 3.886485 1.898370 34.065498 3.886485 1.898370 36.973099 5.891685 1.898429 37.416302 7.511585 1.898335 34.065498 3.886485 1.898370 37.416302 7.511585 1.898335 31.540001 3.410384 1.897815 37.416302 7.511585 1.898335 37.851398 9.623985 1.898234 31.540001 3.410384 1.897815 37.851398 9.623985 1.898234 29.062401 3.400085 1.898075 31.540001 3.410384 1.897815 29.062401 3.400085 1.898075 37.851398 9.623985 1.898234 26.679501 4.336085 1.896880 37.851398 9.623985 1.898234 24.538500 5.668586 1.898248 26.679501 4.336085 1.896880 22.969200 7.943485 1.899194 24.538500 5.668586 1.898248 37.851398 9.623985 1.898234 22.127001 10.779885 1.898426 22.969200 7.943485 1.899194 37.851398 9.623985 1.898234 21.901501 13.360915 1.898337 22.127001 10.779885 1.898426 37.851398 9.623985 1.898234 21.901501 13.360915 1.898337 37.851398 9.623985 1.898234 38.195499 11.935485 1.897456 32.375198 21.947132 1.898189 31.283899 22.036659 1.898314 33.621899 21.475061 1.897475 31.283899 22.036659 1.898314 30.191500 21.883495 1.898425 33.621899 21.475061 1.897475 object2 73.928902 -14.603115 2.261673 74.228600 -13.175915 2.261673 71.259003 -13.976112 2.260420 71.259003 -13.976112 2.260420 74.228600 -13.175915 2.261673 72.029999 -12.199013 2.259457 74.228600 -13.175915 2.261673 75.138298 -10.267612 2.261672 72.669403 -10.115314 2.260881 74.228600 -13.175915 2.261673 72.669403 -10.115314 2.260881 72.029999 -12.199013 2.259457 object3 -12.199013 2.259457 74.228600 -13.175915 2.261673 75.138298 -10.267612 2.261672 72.669403 -10.115314 2.260881 etc.... it has 9 float values per line, and a string in some lines (which lines has a string or the 9 float numbers is unknown) before i got a file with strings, i was reading the file like this:

for(int i = 0; i < g_NumberOfVerts; i+=3)
{		
		
			fscanf(fp, "%f %f %f   ", &g_pVertices.x, &g_pVertices.y, &g_pVertices.z );	
			fscanf(fp, "%f %f %f   ", &g_pVertices[i+1].x, &g_pVertices[i+1].y, &g_pVertices[i+1].z );	
			fscanf(fp, "%f %f %f\n", &g_pVertices[i+2].x, &g_pVertices[i+2].y, &g_pVertices[i+2].z );	
		

}
but now, with a string i some lines, i dont know how to read the file, because i need to ignore that string, i only need the float numbers to be stored into my g_pVertices array (in order)..... how can i do it? it doesnt matter if its with C or C++.....
Advertisement
ifstream in(filename);if (!in){  // handle error}while (!in.eof()){  string line;  getline(in, line);  int numRead = sscanf(line.c_str(), "%lf %lf %lf %lf %lf %lf %lf %lf %lf",                       &x1, &y1, &z1, &x2, &y2, &z2, &x3, &y3, &z3);  // if all the values weren't read in for this line,  // we might be at a line with the string  if (numRead == 9)  {    // add vertices  }}


I've not tried to compile this, but this should work.
<a href="http://www.slimcalcs.com>www.slimcalcs.com
it didnt worked......
it seems that is not reading all the data.....

any clue?
Please don't use sscanf() or any of that other stdio.h stuff in C++. There's really no call for it any more.

ifstream in(filename);if (!in){  // handle error}// Also, prefer this idiom for reading all lines of a file:string line;while (getline(in, line)) {  if (stringstream(line) >> x1 >> y1 >> z1 >> x2 >> y2 >> z2 >> x3 >> y3 >> z3) {    // We successfully read 9 vertices out of this line, so add them.  }  // Otherwise, there was something wrong with the contents of this line;  // for now, we just ignore these lines.}


If it doesn't work, I'll need to see the code where you collect the vertices.
Wow!
thanks a lot Zahlman, it worked perfectly, but now i have 2 questions:

Quote:Original post by Zahlman
Please don't use sscanf() or any of that other stdio.h stuff in C++. There's really no call for it any more.

1.-why? is there any perfomance issue with the stdio?

2.- How does ifstream works? doesnt it has something like the rewind(fileptr) in the FILE* "class"?
i ask this, because, as you can see, in this program, i need first to read how many vertices does the file has, so then i can allocate enought memory for my g_pVertices array.
So what i do is:
1.- read the file
2.- get the vertice count
3.- allocate the memory based on the vertice count
4.- read the file again
5.- set the vertice data to my array

the problem i have, is that i have to create a new instance of ifstream:
ifstream in1 <-- to read the file for the first time
ifstream in2 <-- to read the file for the second time

beacuase if i try to use the same, the second time i try to read the file, it doesnt read anything, even if i close and reopen the file....

so... isnt there any way to solve this problem?
Quote:I need first to read how many vertices does the file has, so then i can allocate enought memory for my g_pVertices array.


You might want to use a std::vector as a temporary to hold you vertex data, then alocate g_pVerticesbased on the number of elements you vector reports to have, or, you might want to use a std::vector *instead* of g_pVertices ;)

But of course there is probably a way to do what you're trying to do the way you want do do it (rewinding the file stream)

Quote:
i ask this, because, as you can see, in this program, i need first to read how many vertices does the file has, so then i can allocate enought memory for my g_pVertices array.
So what i do is:
1.- read the file
2.- get the vertice count
3.- allocate the memory based on the vertice count
4.- read the file again
5.- set the vertice data to my array


If you used a std::vector, you wouldn't have to worry about this. Since this is still contiguous memory, you can still refer to the raw array data later if you need to (though you shouldn't need to hehe).

edit: arrrr, beaten to it... but I have a link :D
well, the problem here, is that i have my 3DVector class, that handles a lot of 3dmath, camera and other things, and my pVertices array, is an instance of that class; and i already have a lot of code that use that kind of data, to modify all the code will be a big problem (i also use std::vector, but for other things...)
Quote:Original post by BlackWind
well, the problem here, is that i have my 3DVector class, that handles a lot of 3dmath, camera and other things, and my pVertices array, is an instance of that class; and i already have a lot of code that use that kind of data, to modify all the code will be a big problem (i also use std::vector, but for other things...)
Well, pVertices probably isn't an instance of your 3DVector class; I'm guessing it's of type 3DVector*.

In any case, I suggest that you go ahead and make the switch to std::vector<3DVector>. Depending on how much code we're talking about here it might take you an hour or two, but the time spent will be well worth it.

First you'll have to do a global replace on the name 'pVertices' (which by the way is a good example of why you shouldn't use Hungarian notation or its derivatives). Direct access via the [] operator can be left as is, but you'll need to change occurrences of 'pVertices' to '&vertices.front()' when passing around the raw data (e.g. to third-party APIs).

I think once you get started you'll find that the switch requires fewer changes to your code than you might guess. Just make sure to back everything up before diving in :)

As for sscanf(), the issue is not performance, but rather robustness, flexibility, and safety (remember, performance is not the end all and be all of programming, game or otherwise, especially not these days).

As for parsing your .raw file, there are any number of ways you can go about it, but you can easily do it using only std::string and getline() (similar to what's been posted already, but with a little extra code to handle the 'object' identifiers).

To make it even easier though, grab Boost and use either the Boost Tokenizer or Boost String Algorithms library, perhaps along with boost::lexical_cast, to manage the details of splitting the lines into tokens, trimming the individual tokens if necessary, and performing the appropriate lexical conversions. Note that the libraries mentioned are header-only, so you don't have to build Boost to use them.

The above is not the only (or perhaps even the best) means of parsing your file, but is certainly to be preferred over the C library functions mentioned earlier. And if you get stuck on something, you can always ask :)
Quote:Original post by jyk
First you'll have to do a global replace on the name 'pVertices' (which by the way is a good example of why you shouldn't use Hungarian notation or its derivatives).


Theres plenty more reasons why its good to use hungarian notation derivatives though, especially weak ones. Readability being the main one.

This topic is closed to new replies.

Advertisement