Re: Help reading a file and picking out numerical values
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1
Hi
Am 06.12.12 18:16, schrieb mariogreece@googlemail.com:
So what i'm trying to do is read a file which contains both
characters and numbers I'm kinda new to c++ so bear with me a
little bit :P
There are lots of things from C that have better replacements in C++.
I'm going to comment on that in the code.
So i cast the lines into strings with getline and then try and
convert that with sscanf . In order to do that though i must make a
distinction between lines.
lines starting with f are for inteer values whereas those starting
with v are for floating.
Any integer can also be treated like a float. Your final data
structure is Coordinate_Matrix and it contains floats only. So you
might as well just try to read floats.
The code seems stuck once i try to run it somewhere and i can't
figure out where.
I'll include both a sample of the file and my code. any feedback is
much appreciated!
Code: ===================================
#include <iostream> #include <fstream> #include <string> #include
<stdio.h> #include <stdlib.h>
// instead include:
#include <cstdio>
#include <cstdlib>
using namespace std;
int main () { ifstream myobject("Model_1.txt"); string line;
if(!myobject.good()) { cout << " Problem reading Object file!
Aborting. "; } int number_of_lines = 0,counter,i; while (
getline(myobject, line) ){ ++number_of_lines; }
Good loop!
myobject.close(); myobject.open("Model_1.txt"); cout << 1 <<endl;
int Buffer_float_vector[3]; float Buffer_int_vector[3];
Big problem: naming and type don't match. This leads to an error in
use of sscanf. If on your compiler the types float and int use a
different number of bits for storage (that is
sizeof(float)!=sizeof(int)) the sscanf calls below will likely make
your program do funny things, just as you described "code seems stuck".
float Coordinate_Matrix[number_of_lines][3];
std::vector is a dynamically resizable array. You could make the
Coordinate_Matrix a std::vector<std::array<float, 3>> and add entries
as you read the file. You wouldn't need to count the lines beforehand.
cout << 2 << endl;
counter=0; while(!myobject.eof() ) { getline(myobject, line);
Bad loop! With C++ streams the eof() function is not functional as a
loop condition. You need to check whether getline has completed
without an error, just as you did in the good loop.
if (line.c_str()[0] == 'v'){ line[0]=' '; // set pointer to 0 at
the 1st character found sscanf(line.c_str(),"%f %f %f",
&Buffer_float_vector[0], &Buffer_float_vector[1],
&Buffer_float_vector[2]);
The sscanf format string specifies to read floats, but your
Buffer_float_vector is actually an int array. This mismatch is a big
problem.
sscanf is an old C function. Since you are reading a file stream
anyway you might as well just use the stream operators for reading values:
while(myobject && counter < number_of_lines)
{
char c;
if( myobject >> c)
{
switch(c)
{
case 'v':
case 'f':
myobject
Coordinate_Matrix[counter][0]
Coordinate_Matrix[counter][1]
Coordinate_Matrix[counter][2]
;
if(myobject) ++counter; // increment when no error
break;
default:
getline(myobject, line); // skip line
break;
}
}
}
cout << counter << endl; cout << Buffer_float_vector[0] <<" "<<
Buffer_float_vector[1] <<" "<< Buffer_float_vector[2] << endl; //
for(i=0;i=2;i++){
Coordinate_Matrix[counter][i]=Buffer_float_vector[i];
You could read into Coordinate_Matrix directly with sscanf and
&Coordinate_Matrix[counter][0].
Buffer_float_vector[i]= ' '; //
This will convert the character ' ' (space) into an int (or float).
The space converted to int means the number 32 (most probably, depends
on compiler). So what purpose does the assignment serve? Why assign 32?
} counter++; } else if (line.c_str()[0] == 'f'){ line[0] = ' ';
sscanf(line.c_str(),"%i %i %i", &Buffer_int_vector[0],
&Buffer_int_vector[1], &Buffer_int_vector[2] );
The sscanf format string specifies to read ints, but your
Buffer_int_vector is actually an float array. This mismatch is a big
problem.
cout << counter << endl; // for(int i=0;i=2;i++){
Coordinate_Matrix[counter][i]=Buffer_float_vector[i];
Buffer_int_vector[i]=' ';
Same here: why assign 32?
} counter++; } else{ counter = -1;
You set the counter to negative one, but you will not exit the loop.
On reading the next line from the file you end up accessing
Coordinate_Matrix on a negative index. This is also a big problem.
Using a std::vector and accessing the elements via the at() function
will check for array index out of bounds automatically.
}
} cout << " First Matrix Element : " << Coordinate_Matrix[1][0] <<
" || " << Coordinate_Matrix[1][1] << " || " <<
Coordinate_Matrix[0][2] << endl; cout << " Last Matrix Element : "
<< Coordinate_Matrix[number_of_lines][0] << " || " <<
Coordinate_Matrix[number_of_lines][1] << " || "
<<Coordinate_Matrix[number_of_lines][2] << " || " << endl;
The index "number_of_lines" is out of bounds for Coordinate_Matrix.
The last valid index is "number_of_lines-1" and the first is zero.
Accessing the array out of bounds is a big problem.
cout << " counter = " << counter; myobject.close(); return 0; }
// quick start on std::vector:
#include <vector>
struct Element { float x, y, z; };
typedef std::vector<Element> ElementArray;
ElementArray Coordinate_Matrix;
....
// add element:
Element e;
if(myobject >> e.x >> e.y >> e.z)
Coordinate_Matrix.push_back(e);
....
cout << "number of elements: " << Coordinate_Matrix.size() << '\n';
HTH,
Frank
-----BEGIN PGP SIGNATURE-----
Version: GnuPG/MacGPG2 v2.0.17 (Darwin)
Comment: GPGTools - http://gpgtools.org
Comment: keyserver x-hkp://pool.sks-keyservers.net
iEYEARECAAYFAlDA89gACgkQhAOUmAZhnmosbQCeOUISlUBfhtlUAAZmBCTNAPKX
K2QAn17v6LpM1DmhTf9UKKgl2nJAeTro
=tLMY
-----END PGP SIGNATURE-----
--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]