Hello there,

I'm very new to C++ and I'm mainly using it for graphics using the opengl libraries.

Anyway, I'm having trouble with some initialisation. I am writing a file reader class that will read a file containing vertex and face data for a series of polygons.

Data.h

#ifndef _DATA_H_
#define _DATA_H_

// Vertex class holds x, y, and z values, and provides the getter
// and setter methods.
class Vertex {

public:
	Vertex() { x = y = z = 0.0; }
	~Vertex() { }
	float getX();
	float getY();
	float getZ();
	void setX(float);
	void setY(float);
	void setZ(float);

private:
	float x, y, z;

};

// Face class contains an array of ints that will be used to reference
// the vertices when creating a shape.
class Face {

public:
	Face();
	Face(int);
	~Face() { }
	int* getPoints();
	int getNumberOfPoints();
	void addPoint(int, int);

private:
	int numberOfPoints;
	int* points;

};

#endif

Data.cpp

/***************************************************************
 * The Data.cpp file provides the functions definitions for    *
 * the classes defined in Data.h. These will be used when      *
 * the data file is to be read in and stored.                  *
 ***************************************************************/

#include "Data.h"

// Vertex getters
float Vertex::getX() { return x; }
float Vertex::getY() { return y; }
float Vertex::getZ() { return z; }

// Vertex setters
void Vertex::setX(float newX) { x = newX; }
void Vertex::setY(float newY) { y = newY; }
void Vertex::setZ(float newZ) { z = newZ; }

// Face constructor
Face::Face()
{
	numberOfPoints = 0;
	points = new int[10];
}

Face::Face(int no)
{
	numberOfPoints = no;
	points = new int[no];
}

void Face::addPoint(int location, int p)
{
	*(points + location) = p;
}

// Getter for the array
int* Face::getPoints()
{
	return points;
}

int Face::getNumberOfPoints()
{
	return numberOfPoints;
}

DataReader.h

#ifndef _DATAREADER_H_
#define _DATAREADER_H_

#include "Data.h"

class Reader {

public:
	Reader(char[]);
	~Reader() {}
	void readFile();
	Vertex getVertices();
	Face getFaces();
	
private:
	char *file;
	Vertex* verticies;
	Face* faces;
};

#endif

DataReader.cpp

/***************************************************************
 * The FileReader class reads external data files, and creates *
 * arrays to store the read data in. The data to be read is a  *
 * range of verticies, and data about faces.                   *
 ***************************************************************/

#include <iostream>
#include <fstream>
#include "Data.h"
#include "DataReader.h"

using namespace std;

Reader::Reader(char c[])
{
	file = c;
}

void Reader::readFile()
{
	//set up file stream
	ifstream file(file);
	if (file.is_open())
	{
		//read in the number of verticies
		int numberOfVerticies;
		file >> numberOfVerticies;
		cout << "VERTICIES\nNumber of Verticies: " << numberOfVerticies << "\n";

		//set the array to hold the number of vertex objects needed
		verticies = new Vertex[numberOfVerticies];

		//for each vertex
		for (int i = 1; i <= numberOfVerticies; i++)
		{
			float vNumber, x, y, z;
			Vertex v;
			
			//read in values and store them in the vertex object
			file >> vNumber >> x >> y >> z;
			v.setX(x);
			v.setY(y);
			v.setZ(z);

			//add the vertex to the array
			*(verticies + i) = v;
			
			cout << "Vertex " << i << " - X: " << v.getX() << " Y: " << v.getY() << " Z: " << v.getZ() << "\n"; 
		}

		cout << "\n";

		//check that the array has the data stored correctly
		for (int p = 1; p <= numberOfVerticies; p++)
		{
			Vertex v = *(verticies + p);
			cout << "Vertex " << p << " - X: " << v.getX() << " Y: " << v.getY() << " Z: " << v.getZ() << "\n";
		}

		cout << "\nFACES\n";

		//read in the number of faces
		int numberOfFaces;
		file >> numberOfFaces;
		cout << "Number of Faces: " << numberOfFaces << "\n";

		//initialise the array to the size of the number of faces
		faces = new Face[numberOfFaces];

		//for each face
		for (int j = 0; j < numberOfFaces; j++)
		{
			//find the number of points for each face
			int numberOfPoints;
			file >> numberOfPoints;
			cout << "\nFace " << j << "\nNumber of Points: " << numberOfPoints << "\n";

			//create a new Face, initialising the int array size to the number of points
			Face f(numberOfPoints);

			//for each point
			for (int k = 0; k < numberOfPoints; k++)
			{
				//read the point and store it in the array
				int point;
				file >> point;
				f.addPoint(k, point);
				cout << point;
			}

			//add the face to the array of faces
			*(faces + j) = f;
		}
	}	
	file.close();
}

I'm sorry for all the code, I'm just stuck for options, and have tried a lot of different ways to get around it.

Objects of class reader each have an array of verticies and faces. These are pointers, that are initialised in the readFile method. I want to initialise each pointer to an array, where the size is read in from the input file. verticies is initialised to an array of size numberOfVerticies, using the default constructor.

What I need for faces, is an array of face objects. Each face object has an int pointer, to an array on ints, the size being the number of points read in.

The problem when I run it, the cmd window appears, but then I get an illegal exception error and the window crashes. It reads the vertices correctly, but crashes when reading the faces. What is strange is that when I step through with the debugger it works fine, yet when I run it , it crashes.

I know I'm being vague, so please ask if you want me to clear anything up.

Thanks very much, I know there is a lot of code there to sift through.

ps I know i've spelt vertices as verticies in some of the bits of code, I've sorted that typo in the real thing :D

In Face::addPoint() you should verify that location < the allocation size of numberOfPoints.

Actually, you don't need data.cpp at all. Just use inline code in the header files.

Can't really help you much more without example data file to work with.

Thanks for the reply dragon.

I've come from Java to C++ and finding it quite difficult. I've yet to of read about inline code in my textbook, but I'll be sure to look it up on the internet. Data.cpp does seem pointless if it can be put into the header file.

Here my Data.h revision:

#ifndef _DATA_H_
#define _DATA_H_

#include <iostream>
using namespace std;

// Vertex class holds x, y, and z values, and provides the getter
// and setter methods.
class Vertex {

public:
	Vertex() { x = y = z = 0.0; }
	~Vertex() { }
	float getX();
	float getY();
	float getZ();
	void setX(float);
	void setY(float);
	void setZ(float);

private:
	float x, y, z;

};

// Vertex getters
inline float Vertex::getX() { return x; }
inline float Vertex::getY() { return y; }
inline float Vertex::getZ() { return z; }

// Vertex setters
inline void Vertex::setX(float newX) { x = newX; }
inline void Vertex::setY(float newY) { y = newY; }
inline void Vertex::setZ(float newZ) { z = newZ; }

// Face class contains an array of ints that will be used to reference
// the vertices when creating a shape.
class Face {

public:
	Face();
	Face(int);
	~Face() { }
	int* getPoints();
	int getNumberOfPoints();
	void addPoint(int, int);

private:
	int numberOfPoints;
	int* points;

};

// Face constructors
// Default
inline Face::Face()
{
	numberOfPoints = 0;
	points = new int[10];
}

// Initialise size of the array
inline Face::Face(int no)
{
	numberOfPoints = no;
	points = new int[no];
}

// Add a point to the array
inline void Face::addPoint(int location, int p)
{
	if (location < numberOfPoints)
	{
		*(points + location) = p;
	} else {
		cerr << "You cannot reference that array location!" << endl;
	}
}

// Getter for the array
inline int* Face::getPoints()
{
	return points;
}

//Getter for the number of points
inline int Face::getNumberOfPoints()
{
	return numberOfPoints;
}

#endif

I've added the check that location is a valid option.

I knew I'd forgotten something, ofcourse you need to see the example data. This is what I have been trying to read in, a tetrahedron. The verticies get read in and stored fine, but the faces crash after reading the number of faces.

4
   1   1 1 1
   2   1 -1 -1
   3   -1 1 -1
   4   -1 -1 1
4
   3  4 3 2
   3  3 4 1
   3  2 1 4
   3  1 2 3

This is the console output as well, up until the point it crashes:

VERTICES
Number of Vertices: 4
Vertex 1 - X: 1 Y: 1 Z: 1
Vertex 2 - X: 1 Y: -1 Z: -1
Vertex 3 - X: -1 Y: 1 Z: -1
Vertex 4 - X: -1 Y: -1 Z: 1

Vertex 1 - X: 1 Y: 1 Z: 1
Vertex 2 - X: 1 Y: -1 Z: -1
Vertex 3 - X: -1 Y: 1 Z: -1
Vertex 4 - X: -1 Y: -1 Z: 1

FACES
Number of Faces: 4

This is what we mean by inline functions in the header file

class Vertex {

public:
	Vertex() { x = y = z = 0.0; }
	~Vertex() { }
	float getX() { return x;}
	float getY()  { return y;}
	float getZ() { return z; };
	void setX(float newX)  { x = newX; };
	void setY(float newY) { y = newY; };
	void setZ(float newZ) { z = newZ; };

private:
	float x, y, z;

};

Thanks, any idea about the crashing problem then?

EDIT: It is a problem with the faces declaration:

faces = new Face[numberOfFaces];

This should create an array of face objects with the default constructor. I then later create new Face objects and overwrite the ones in the array created by the default constructor.

> for (int i = 1; i <= numberOfVerticies; i++)
Arrays, including those you allocate, start at 0, not 1.
All your examples run off the end, and no doubt end up corrupting something else.

It should be for (int i = 0; i < numberOfVerticies; i++) In your face constructor,
> points = new int[10];
This is inconsistent with the value you've assigned for numberOfPoints.

Salem, you're my saviour!

It was the for loop statement. I did actually want to start the counter at 1, because the data for each face references a set of vertices by their number.

So for a face:
3 1 2 3
There are three points, that make a face using vertices 1, 2 and 3. I want to start the array at 1 to easily get the vertices.

All I need to do to fix this was to increase the vertices array with one extra location, leaving location[0] null.

Thanks very much!

This question has already been answered. Start a new discussion instead.