I've got the Vector (input parsing) blues

A

{AGUT2}=IWIK=

Hello all,

It's my fisrt post here and I am feeling a little stupid here, so go easy..
:) (Oh, and I've spent _hours_ searching...)

I am desperately trying to read in an ASCII "stereolithography" file (*.STL)
into my program. This has the following syntax...

Begin STL Snippet
**********
facet normal -0.00000904 -0.00002272 -1.00000000
outer loop
vertex -2.71325651 0.49965868 -0.00399721
vertex -1.14940957 0.00000000 -0.00400000
vertex -5.03708494 0.00000000 -0.00396485
endloop
endfacet
*********
End STL Snippet

I am putting the various numbers into a facet (an array of vectors) -
myArray[numOfFacets][4]; - from my vector class. Slots 0,1 & 2 are taken by
the vector components, and 3 by the normal, with numOfFAcets being
(drumroll...) the number of facets.

I have two problems..

1) I want to dynamically size the vector array, as the number of facets will
be different for different input files. HOWEVER, I read through the file and
I then 'numOfFacets++;' for each occurence of 'facet'. But, I get...

cfdcasdr1_1.cpp(54) : error C2057: expected constant expression
cfdcasdr1_1.cpp(54) : error C2466: cannot allocate an array of constant size
0
cfdcasdr1_1.cpp(54) : error C2133: 'myArray' : unknown size

.... upon compiling. (VC++ 6.0) Is there a way around this?

Also,

2) I have a 'while' loop to read the numbers in, doing a strtod() on them.
The problem is, I am relying on the program seeing the 'vertex' and 'normal'
part of the file to tell the program that the next (three) inputs are going
to be the vector's x, y and z coordinates.

unfortunately the...

if (buffer == "vertex")
{
}

....thing won't work with strings (AFAICT). How can I use the 'if' statement
to this end? I could to a strtod() - STRing TO Double - on everything, but
if it can't do it, it returns 0 - which the vector components can _also_ be,
so this is no help! :/

I would greatly appreciate any help you could give me.

Alexander Livingstone
 
J

John Harrison

{AGUT2}=IWIK= said:
Hello all,

It's my fisrt post here and I am feeling a little stupid here, so go easy..
:) (Oh, and I've spent _hours_ searching...)

I am desperately trying to read in an ASCII "stereolithography" file (*.STL)
into my program. This has the following syntax...

Begin STL Snippet
**********
facet normal -0.00000904 -0.00002272 -1.00000000
outer loop
vertex -2.71325651 0.49965868 -0.00399721
vertex -1.14940957 0.00000000 -0.00400000
vertex -5.03708494 0.00000000 -0.00396485
endloop
endfacet
*********
End STL Snippet

I am putting the various numbers into a facet (an array of vectors) -
myArray[numOfFacets][4]; - from my vector class. Slots 0,1 & 2 are taken by
the vector components, and 3 by the normal, with numOfFAcets being
(drumroll...) the number of facets.

I have two problems..

1) I want to dynamically size the vector array, as the number of facets will
be different for different input files. HOWEVER, I read through the file and
I then 'numOfFacets++;' for each occurence of 'facet'. But, I get...

cfdcasdr1_1.cpp(54) : error C2057: expected constant expression
cfdcasdr1_1.cpp(54) : error C2466: cannot allocate an array of constant size
0
cfdcasdr1_1.cpp(54) : error C2133: 'myArray' : unknown size

... upon compiling. (VC++ 6.0) Is there a way around this?

I'm sure there is, but you need to post code, not tiny snippetts of it, but
proper compilable code. Line 54 would be a help, as would the complete
definitions of any variables or types on line 54. And how about what you are
calling 'your vector class'.

Also,

2) I have a 'while' loop to read the numbers in, doing a strtod() on them.
The problem is, I am relying on the program seeing the 'vertex' and 'normal'
part of the file to tell the program that the next (three) inputs are going
to be the vector's x, y and z coordinates.

unfortunately the...

if (buffer == "vertex")
{
}

...thing won't work with strings (AFAICT).

Again the problem is the incomplete code. What is the type of buffer? What
is its value? Did you know there are two types of strings in C++? Which one
are you using?

I would guess that the answer is

if (strcmp(buffer, "vertex") == 0)
{
}

but since my crystal ball is at the menders I'm not really sure.
How can I use the 'if' statement
to this end? I could to a strtod() - STRing TO Double - on everything, but
if it can't do it, it returns 0 - which the vector components can _also_ be,
so this is no help! :/

I would greatly appreciate any help you could give me.

Alexander Livingstone

Please post proper code, this sounds easy enough.

john
 
J

Jon Bell

Begin STL Snippet
**********
facet normal -0.00000904 -0.00002272 -1.00000000
outer loop
vertex -2.71325651 0.49965868 -0.00399721
vertex -1.14940957 0.00000000 -0.00400000
vertex -5.03708494 0.00000000 -0.00396485
endloop
endfacet
*********
End STL Snippet

I am putting the various numbers into a facet (an array of vectors) -

I take it you're using "vector" to mean simply one of the triplets of
numbers that appear in the snippet above? If so, you should be aware that
to a C++ programmer, "vector" means a data structure somewhat like an
array, but more powerful, that is included in the C++ standard library.
This might cause some miscommunication.
myArray[numOfFacets][4]; - from my vector class. Slots 0,1 & 2 are taken by
the vector components, and 3 by the normal, with numOfFAcets being
(drumroll...) the number of facets.

OK, so in C++ terms, you're trying to use a two-dimsnsional array, or more
precisely an array of arrays.
1) I want to dynamically size the vector array, as the number of facets will
be different for different input files. HOWEVER, I read through the file and
I then 'numOfFacets++;' for each occurence of 'facet'. But, I get...

cfdcasdr1_1.cpp(54) : error C2057: expected constant expression
cfdcasdr1_1.cpp(54) : error C2466: cannot allocate an array of constant size
0
cfdcasdr1_1.cpp(54) : error C2133: 'myArray' : unknown size

This sounds like you're trying to use a variable for one dimension of the
array, to establish the size dynamically at run time when you declare it.
You can't do this directly. You have to allocate the memory explicitly
using 'new', keep a pointer to it, and then deallocate the memory when
you're finished. This is tricky for two-dimensional arrays.

However, the aforementioned C++ vectors *can* be sized (and even resized)
dynamically at run time. They handle their own memory allocation. So
instead of an array of arrays, you might try a vector of vectors:

#include <vector>

using namespace std; // if you don't have this already

vector<vector<double> > myArray (numOfFacets, vector<double>(4));

This declares a vector (named myArray) which contains numOfFacets vectors,
each of which in turn contains four doubles. numOfFacets can be a
variable determined at run time, and you can access each item in myArray
using ordinary subscript notation: myArray[facetNum][k].
2) I have a 'while' loop to read the numbers in, doing a strtod() on them.
The problem is, I am relying on the program seeing the 'vertex' and 'normal'
part of the file to tell the program that the next (three) inputs are going
to be the vector's x, y and z coordinates.

unfortunately the...

if (buffer == "vertex")
{
}

...thing won't work with strings (AFAICT).

I take it you're using arrays of char as C-style strings? Using the ==
operator actually compares pointers to the locations of the strings in
memory, which will give you equality only if the two strings are actually
the same string (i.e. in the same memory location). To compare the
*contents* of two C-style strings, you need to use the strcmp() function.

You *can*, however, use == to compare two C++-style strings:

#include <string>

using namespace std; // if you don't already have this somewhere

string buffer;
// read into buffer from your data, then
if (buffer == "vector")
{
// do something
}

It looks like you're learning C++ from a book that teaches the older
C-style constructs before teaching the newer C++-style constructs (if
indeed it does use the C++ style stuff at all). You might try looking for
a more modern book. Many people here (including me) will recommend Koenig
and Moo's "Accelerated C++" if you already have some programming
experience.
 
A

{AGUT2} {H}-IWIK

John,

Thanks very much for the assistance! I'm composing this on a train on my
elderly notbook, but will be back with my box soon, so will try the
programs with the strcmp() thing when I get back. In the mean time, I've
included the code of my program so far....

#include "stdafx.h"
#include "stdlib.h"
#include "math.h"
#include "iostream.h"
#include "iomanip.h"
#include "fstream.h"
#include "vectorr1_1.h"
#include "string.h"
#include "string"

// I'm sure I don't need all these, but I'll strip them out later. :)

int main()
{
char fileName[255];
cout << "Enter the name of the input *.STL file (including extension): ";
cin >> fileName;
ifstream inf(fileName);
char buffer[128];
char * ehWhy;
int facetTot=1;
int facetNum=0;
int normFlag=0;
int vertFlag=0;
int compFlag=0;
int solidFlag=0;
char vcheck[128] = "\nvertex";
char ncheck[128] = "\nnormal";

while(!inf.getline(buffer, 128 ,' ').eof())
{
// What I have done here is put the carriage return from
// the line before in the buffer check. Do I need to do this?
// If so is this the right way? or should I use that ignore
// doodad that I have seen in reference to strings
if(buffer == "\nfacet")
{
facetTot++;
}
}
const int facetTot1 = facetTot;

// This was 'line 54' - I've stripped some stuff to uncomplicate it.
// The compiler doesn't like it. Even with facetTot set to 1 (I'll
// fix the exact facet numbering later).
vector mySurface[facetTot1][4];


while(!inf.getline(buffer, 128, ' ').eof())
{
if (buffer == "\nnormal")
{
cout << ".";
normFlag=1;
compFlag=1;
} else if (buffer == "\nvertex" )
{
vertFlag++;
} else if (normFlag != 0)
{
// This is one thing I don't understand. TBH I'm not really sure
// about pointers in general, but am particularly curious as to
// why this pointer is necessary.
mySurface[facetNum][4].setComp(compFlag, strtod(buffer,&ehWhy));
compFlag++;
if (compFlag == 4)
{
compFlag=0;
normFlag=0;
}
} else if (vertFlag != 0)
{
mySurface[facetNum][vertFlag].setComp(compFlag, strtod(buffer,&ehWhy));
compFlag++;
if (compFlag == 4)
{
compFlag=0;
if (vertFlag == 4)
{
vertFlag=0;
facetNum++;
}
}
}
}
return 0;
}


******* End of main code file. ***********

******* Begin Vector.h *********
#include "iostream.h"
#include "math.h"

class vector
{
protected: // The 'protected' part ensures that 'xcoord' etc. are only
accessible from withing this specific class.

double xcoord, ycoord, zcoord;

public:

// Default constructor: when a vector is specified without arguments, it's
default co-cordinates are set to '0'
vector()
{
xcoord=0;
ycoord=0;
zcoord=0;
}

// Cartesian constructor: when argumants are supplied, they are set as the
co-ordinates.
vector(double x, double y, double z)
{
xcoord=x;
ycoord=y;
zcoord=z;
}

// Prints out to the screen.
void print()
{
cout << "(" << xcoord << "," << ycoord << "," << zcoord << ")";
}

// Access methods for the co-ordinates

double getx()
{
return xcoord;
}

double gety()
{
return ycoord;
}

double getz()
{
return zcoord;
}

double getComp(int compNum)
{
if (compNum == 1)
{
return xcoord;
} else if (compNum == 2)
{
return ycoord;
} else if (compNum == 3)
{
return zcoord;
} else
{
cout << "\n\n Error! Error! Vector getComp\n\n";
}
}

double lenOf()
{
double lengthVal=0;
lengthVal=(xcoord*xcoord);
lengthVal+=(ycoord*ycoord);
lengthVal+=(zcoord*zcoord);
return lengthVal;
}

void setx( double value)
{
xcoord=value;
}

void sety( double value)
{
ycoord=value;
}

void setz( double value)
{
zcoord=value;
}

void setComp(int compNum, double value)
{
if (compNum == 1)
{
xcoord=value;
} else if (compNum == 2)
{
ycoord=value;
} else if (compNum == 3)
{
zcoord=value;
} else
{
cout << "\n\n Error! Error! Vector setComp\n\n";
}
}

// Overload + - Addition
vector operator+(vector v_old)
{
vector v_sum(v_old.getx()+xcoord, v_old.gety()+ycoord, v_old.getz()
+zcoord);
return v_sum;
}

// Overload - - Subtraction
vector operator-(vector v_old)
{
vector v_diff(xcoord-v_old.getx(), ycoord-v_old.gety(), zcoord-
v_old.getz());
return v_diff;
}

// Overload * - Scalar multiplication
vector operator*(double scalar)
{
vector v_scalar(xcoord*scalar, ycoord*scalar, zcoord*scalar);
return v_scalar;
}

// Overload / - Scalar division
vector operator/(double scalar)
{
vector v_scalar(xcoord/scalar, ycoord/scalar, zcoord/scalar);
return v_scalar;
}

// Overload += = Self-assigned Addition
vector operator+=(vector v_old)
{
xcoord+=v_old.getx();
ycoord+=v_old.gety();
zcoord+=v_old.getz();
}

// Overload -= Self-assigned Subtraction
vector operator-=(vector v_old)
{
xcoord-=v_old.getx();
ycoord-=v_old.gety();
zcoord-=v_old.getz();
}

// Overload *= Self-assigned Multiplication
vector operator*=(double scalar)
{
xcoord*=scalar;
ycoord*=scalar;
zcoord*=scalar;
}

// Overload /= Self-assigned Multiplication
vector operator/=(double scalar)
{
xcoord/=scalar;
ycoord/=scalar;
zcoord/=scalar;
}

// Overload * - Dot product
double operator*(vector v_old)
{
double dotProd((xcoord*v_old.getx())+(ycoord*v_old.gety())
+(zcoord*v_old.getz()));
return dotProd;
}

// Overload ^ - Cross product
vector operator^(vector v_old)
{
vector v_cross((ycoord*v_old.getz())-(zcoord*v_old.gety()),
(zcoord*v_old.getx())-(xcoord*v_old.getz()),
(xcoord*v_old.gety())-(ycoord*v_old.getx()));
return v_cross;
}


}; //EVIL SEMI-COLON MUST STAY TO AVOID DAYS OF WONDERING WHAT IS WRONG
WITH YOUR HEADER!!!

Copyright © Alexander Livingstone, 2003

******* End Vector.h *****

Yes, I know it's newbie programming, and probably not worthy of a
copyright, but I'm proud of it ;)

Thank you for the help.

Yours,

Alexander.
 
A

{AGUT2} {H}-IWIK

I take it you're using "vector" to mean simply one of the triplets of
numbers that appear in the snippet above? If so, you should be aware
that to a C++ programmer, "vector" means a data structure somewhat like
an array, but more powerful, that is included in the C++ standard
library. This might cause some miscommunication.

Eek! Ok, cheers. My vector calss isn't QUITE so impressive as the one in
the old include directory, however...
However, the aforementioned C++ vectors *can* be sized (and even resized)
dynamically at run time. They handle their own memory allocation. So
instead of an array of arrays, you might try a vector of vectors:

#include <vector>
using namespace std; // if you don't have this already
vector<vector<double> > myArray (numOfFacets, vector<double>(4));
You *can*, however, use == to compare two C++-style strings:
It looks like you're learning C++ from a book that teaches the older
C-style constructs before teaching the newer C++-style constructs (if
indeed it does use the C++ style stuff at all). You might try looking
for a more modern book. Many people here (including me) will recommend
Koenig and Moo's "Accelerated C++" if you already have some programming
experience.

Thank you for the advice. I have a '97 version of '21 days' that's
yellowing already.. :)

It looks like some frightening syntax changes, but I'll give it a go...

Alexander.
 
L

llewelly

{AGUT2} {H}-IWIK said:
Eek! Ok, cheers. My vector calss isn't QUITE so impressive as the one
in the old include directory, however...




Thank you for the advice. I have a '97 version of '21 days' that's

'21 days'? Scariest thing one might see in the title of a C++
book. See the book reviews at www.accu.org, and look up yours to
see what experienced programmers think of it.
yellowing already.. :)

It looks like some frightening syntax changes, but I'll give it a
go...

But look on the bright side. All those troubles you're having with
arrays that can't be resized, just go away, because vector<double>
can be resized. And so on. Really, the standard library makes your
life a lot easier.
 
J

Jon Bell

Thank you for the advice. I have a '97 version of '21 days' that's
yellowing already.. :)

1997 is rather old in C++ terms. That's just before the C++ standard came
along and introduced nifty stuff like vectors and strings, along with
changing the names of the standard headers and introducing the concept of
"namespaces" that you have to deal with somehow if you're using the new
headers (even if only in Band-aid type fashion via 'using namespace
std;').
 
J

John Harrison

{AGUT2} {H}-IWIK said:
John,

Thanks very much for the assistance! I'm composing this on a train on my
elderly notbook, but will be back with my box soon, so will try the
programs with the strcmp() thing when I get back. In the mean time, I've
included the code of my program so far....

[snip]

const int facetTot1 = facetTot;

// This was 'line 54' - I've stripped some stuff to uncomplicate it.
// The compiler doesn't like it. Even with facetTot set to 1 (I'll
// fix the exact facet numbering later).
vector mySurface[facetTot1][4];

You've obviously heard that array bounds must be constant, that's why you
say const int facetTot1 ..., but actually its worse than that. Array bounds
must be compile time constants, that is (more or less) the compiler must be
able to work out what the value is when it is compiling. Obviously this is
not the case here since facetTot is computed when the program is running.

You need dynamic memory allocation, are you familiar with the new operator?

typedef vector surface[4];

surface* mySurface = new surface[facetTot];

That says a surface is an array of four vectors, and then dynamically
allocates facetTot surfaces and assigns then to the pointer mySurface. The
typedef statement should go somewhere near the top of your code, after you
include the vector header but before main.

Somewhere later in your code (probably at the end of main) you should say
that you no longer need mySurface with

delete[] mySurface;

That releases the dynamically allocated memory.

Because arrays and pointers are very similar beasties you should be able to
use the pointer mySurface in exactly the same way as the array mySurface and
so you should need to change the rest of your code.

john
 
J

John Harrison

so you should need to change the rest of your code.
typo - so you shouldn't need to change the rest of your code.

john
 
A

{AGUT2} {H}-IWIK

Thank you all, you've been a wonderful help. This is why I love the
internet :) I shall stay subscribed and when I have a little skill, will
endeavour to put something back.

Yours,

Alexander
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,755
Messages
2,569,536
Members
45,011
Latest member
AjaUqq1950

Latest Threads

Top