Hello, all,
I am pretty new to C++ and I need to write a program for calculating radio propagation path loss based on ray tracing, C++ is used for its faster processing rather than MATLAB. I have a question about passing 2D arrays between functions.
One of the files looks something like this:

/*this file gets the map information, the map is a 3D vector database which 
contains the coordinates of all the corners of the buildings(because the 
actual dataset is not available now, so only a text file made up by my own is 
used for testing). */

#include "mapInfo.h"
#include <iostream>
#include <fstream>
#include <vector>
using namespace std;

MapInfo::MapInfo()
{
}


//this function read the map in uda format and returns a 2D array contains building infomation.
//in form of: [building_number][no_of_corners x y.....wall_thickness bld_type]
std::vector<std::vector<double> > MapInfo::getMapInfo()
{
	char str[100];
	char name[80];
	int max_corner_no = 10;
	int building_number;
	int corner_number;
	int index;
	char *tokenPtr;	
 
	cout << "Enter file name:";
	cin.getline(name,79);
	ifstream dataFile(name,ios::in);
	if(!dataFile)
	{
		cerr << "File could not be opened\n";
		exit(1);
	}

	// skip the first 5 lines 
	for (int i=0; i<5;i++)
	{
		dataFile.getline(str,99);
	}

	//get the number of buildings from the 6th line
	dataFile.getline(str,99);
	no_of_blds = atoi(&str[0]);

	std::vector<std::vector<double> > bld_info(no_of_blds,std::vector<double>(max_corner_no*2+3));
	/*bld_info = new double *[no_of_blds];
	for (int i=0; i<=no_of_blds-1; i++)
		bld_info[i]=new double[max_corner_no*2+3];  //*2 because we need x and y coordinates, rest 3 for number
													//of corners, wall thickness and building type respectively.*/

	// now get the data
	while(!dataFile.eof())
	{
		index=1;
		dataFile.getline(str,99);
		
		// get the building coordinates
		tokenPtr = strtok(str," ");
		//get the building number first
		building_number = atoi(tokenPtr);
		tokenPtr = strtok(NULL," ");
		//now get the number of corners of this building 
		corner_number = atof(tokenPtr);
		no_of_corners += atoi(tokenPtr);
		tokenPtr = strtok(NULL," ");
		bld_info[building_number-1][0] = corner_number;
		while (tokenPtr != NULL)
		{
			bld_info[building_number-1][index] = atof(tokenPtr);
			tokenPtr = strtok(NULL," ");	
			index++;
		}
	}
	return bld_info;
}

//this function returns the number of buildings in the map
int MapInfo::getNumOfBlds ()
{
	return no_of_blds;
}

//this function returns the total number of corners for all the buildings
int MapInfo::getNumOfCorners ()
{
	return no_of_corners;
}

//this function returns the gradient of a straight line given two points
double MapInfo::getGrad(double x1,double y1,double x2,double y2)
{
	return (y2-y1)/(x2-x1);
}

//this function returns the coordinates of all the corners in a 2D array
//in form of [corner_number][x,y,bld_num]
std::vector<std::vector<double> > MapInfo::getCoordinates(std::vector<std::vector<double> > map_info,int total_blds,int total_corners)
{
	int bld_corners;
	int x,y;
	int coor_index=0;
	/*CoordinateArray = new double *[total_corners];
	for (int i=0; i<total_corners; i++)
		CoordinateArray[i] = new double [3]; // 3 here for [x,y,bld_num]*/
	cout<<"here is fine\n";
	std::vector<std::vector<double> > CoordinateArray(total_corners,std::vector<double>(3));
	for (int bld_num=0; bld_num<total_blds; bld_num++)
	{
		bld_corners = map_info[bld_num][0];
		int cnt=1;
		for (int j=0; j<bld_corners; j++)
		{
			x=map_info[bld_num][cnt];
			y=map_info[bld_num][cnt+1];
			CoordinateArray[coor_index][0] = x;
			CoordinateArray[coor_index][1] = y;
			CoordinateArray[coor_index][2] = bld_num+1;
			coor_index++;
			cnt+=2;
		}
	}
	return CoordinateArray;
}


//this function evaluates all the wall functions
//input of this function should be map_info evaluated from getMapInfo()
//output of this function is the coefficients of each line(wall) in form y=kx+b,
//in form of [wall_num][k,b,x1,y1,x2,y2,bld_num]
std::vector<std::vector<double> > MapInfo::getWallFuncs(std::vector<std::vector<double> > coorArray,int num_of_walls) //number of walls equals to number of corners
{
	double x1,y1,x2,y2;
	double temp_x,temp_y;	
	//initialize temp_x and temp_y values to the first corner coordinate in the file
	temp_x = coorArray[0][0];
	temp_y = coorArray[0][1];
	double k,b;	//straight line coefficients

	//allocate memory for the wall coefficients and relevant numbers
	/*WallFuncs = new double *[num_of_walls];
	for (int i=0; i<num_of_walls; i++)
		WallFuncs[i] = new double [7];	//7 here stores all the relevant numbers*/
	std::vector<std::vector<double> > WallFuncs(num_of_walls,std::vector<double>(7));

	for (int wall_num=0; wall_num<num_of_walls-1; wall_num++)
	{
		//test if the two walls belong to the same building
		//same building in this case
		if(coorArray[wall_num][2] == coorArray[wall_num+1][2])
		{
			x1 = coorArray[wall_num][0];
			y1 = coorArray[wall_num][1];
			x2 = coorArray[wall_num+1][0];
			y2 = coorArray[wall_num+1][1];
			k = getGrad(x1,y1,x2,y2);
			b = y2-k*x2;
		}

		// two edges from different buildings
		else
		{
			x1 = coorArray[wall_num][0];
			y1 = coorArray[wall_num][1];
			x2 = temp_x;
			y2 = temp_y;
			k = getGrad(x1,y1,temp_x,temp_y);
			b = y1-k*x1;

			temp_x = coorArray[wall_num+1][0];
			temp_y = coorArray[wall_num+1][1];
		}
		WallFuncs[wall_num][0] = k;
		WallFuncs[wall_num][1] = b;
		WallFuncs[wall_num][2] = x1;
		WallFuncs[wall_num][3] = y1;
		WallFuncs[wall_num][4] = x2;
		WallFuncs[wall_num][5] = y2;
		WallFuncs[wall_num][6] = coorArray[wall_num][2];
	}
	//last wall coefficients
	k = getGrad(x2,y2,temp_x,temp_y);
	b = y2-k*x2;
	WallFuncs[num_of_walls-1][0] = k;
	WallFuncs[num_of_walls-1][1] = b;
	WallFuncs[num_of_walls-1][2] = x2;
	WallFuncs[num_of_walls-1][3] = y2;
	WallFuncs[num_of_walls-1][4] = temp_x;
	WallFuncs[num_of_walls-1][5] = temp_y;
	WallFuncs[num_of_walls-1][6] = coorArray[num_of_walls-1][2];

	return WallFuncs;
}

now I want to test if this program can give correct result, so in another file which contains only the main function, I got:

#include "mapInfo.h"
#include "firstLayerVisibility.h"
#include <iostream>
using namespace std;

int main()
{
	MapInfo map;
	FirstLayerVisibility flv;
	std::vector<std::vector<double> > angle_result;
	std::vector<std::vector<double> > angle_result2;
	std::vector<std::vector<double> > mapInfo;
	std::vector<std::vector<double> > coorArray;
	std::vector<std::vector<double> > wallFunc;
	mapInfo = map.getMapInfo();
	cout<<mapInfo[0][0]<<" "<<mapInfo[0][1]<<" "<<mapInfo[0][2]<<" "<<mapInfo[0][3]<<" "<<mapInfo[0][4]<<"\n";
	int total_corners = map.getNumOfCorners();
	int total_blds = map.getNumOfBlds();
	
	[B]coorArray[/B] = map.getCoordinates(mapInfo,total_blds,total_corners);
	angle_result = flv.compAngleArray(coorArray,130,300,total_corners);
	angle_result2 = flv.sortAngles(angle_result,map.getNumOfCorners());
	wallFunc = map.getWallFuncs(coorArray,total_corners);
	for(int i=0; i<16; i++)
	{
		cout<<wallFunc[i][0]<<"  "<<wallFunc[i][1]<<" "<<wallFunc[i][2]<<"  "<<wallFunc[i][3]<<" " <<wallFunc[i][4]<<"  "<<wallFunc[i][5]<<" " <<wallFunc[i][6]<<"\n";
	}
	cout << "total number of corners is: " << map.getNumOfCorners();
	for(int i=0; i<16; i++)
	{
		cout<<angle_result[i][0]<<"  "<<angle_result[i][1]<<" "<<angle_result[i][2]<<" "<<angle_result[i][3]<<" " <<angle_result[i][4] <<" "<<angle_result[i][5]<<"\n";
	}
	cout << "total number of corners is: " << map.getNumOfCorners();
	flv.visiblePoints(wallFunc,angle_result2,130,300,16);
	return 0;
}

I am using VS 2008, now when I run the test it reports an error "this program has requested the Runtime to terminate it in an unusual way...", the program terminates at the creation of the second 2D array (map.getCoordinates()), where the first array "mapInfo" is all right. I think this is something to do with the memory allocation, as before I used dynamic 2D array allocation like:
WallFuncs = new double *[num_of_walls];
for (int i=0; i<num_of_walls; i++)
WallFuncs = new double [7];
and this reports an error of invalid memory allocation with a big value. But when I write all my functions within one file, it works properly. So I am just wondering if this is anything to do with the "OO design"? In the above test, when a new object "map" is created, the contents of "mapInfo" can be printed out with correct values, but the program terminates at "coorArray" for error of invalid memory allocation(for using dynamic 2D array allocation) or Runtime error if using std::vector<std::vector<double> > type. Can anyone please help me to work this out? I do need to pass 2D arrays between functions for large number of calculations, so what would be a solution for this?

Another question is that at some later stage of this program, if I want to develop a GUI for it using MFC in visual C++, do I create another "Win32 project" or "MFC application"? As currently the above is a "win32 console application", so what is the basic idea to convert it into a application with GUI using MFC?

Thank you very much for your attention, any comment would be helpful.

Recommended Answers

All 15 Replies

> for (int i=0; i<=no_of_blds-1; i++)
> bld_info=new double[max_corner_no*2+3]; //*2 because we need x and y coordinates, rest 3 for number
This is unnecessary (in fact, I think it should at least have raised some warnings). Assuming the maths is correct in the previous line, you already have a 2D vector of doubles.

> while(!dataFile.eof())
http://faq.cprogramming.com/cgi-bin/smartfaq.cgi?answer=1046476070&id=1043284351
The problem is, eof is a state, not a prediction. This means it relys on some other function (say getline) failing to read input before it will return true. So what this means for you is the getline on the previous loop failed, and you tried to strtok your way through bad input. At some point, you tried to use an unchecked NULL from strtok and that's when it blew up.

while ( datafile.getline(str) )

Fixes this problem, and also checks that getline actually succeeded in returning a useful line.

> char str[100];
Use std::string for all input.
Even where you absolutely need a char array (the filename), you can do

std::string name;
cin.getline(name);
ifstream dataFile(name.c_str(),ios::in);

For everything else, use a string stream, so

dataFile.getline(str,99);
no_of_blds = atoi(&str[0]);

would be something like

std::string str;
dataFile.getline(str);
std::stringstream s(str);
s >> no_of_blds;

There should be no need for you to use char arrays and unchecked strtok to parse the line.

> if I want to develop a GUI for it using MFC in visual C++,
> do I create another "Win32 project" or "MFC application"?
I thought Microsoft was trying to deprecate MFC, so it's not the best thing to be using for new code (and your new compiler).
Personally, I would suggest a 3rd party portable UI toolkit such as wxwidgets

Hello, Salem,
Thank you very much for your reply, regarding to that:
> for (int i=0; i<=no_of_blds-1; i++)
> bld_info=new double[max_corner_no*2+3]; //*2 because we need x and y coordinates, >rest 3 for number
>This is unnecessary (in fact, I think it should at least have raised some warnings). Assuming >the maths is correct in the previous line, you already have a 2D vector of doubles.

I have actually commented out this part in my program. I just want to show that for both of the cases when I used to declare the 2D array(either dynamic allocation using "new" or using vector, it does not work in either case. The main problem for me now is that when I was trying to create a new variable from class MapInfo, and parse the file, it can parse the file correctly and all the variables are successfully stored in the 2D array "mapInfo". But when I try to call another function "getCoordinates()", which uses "mapInfo" as one of its inputs and creates another 2D array for its output, then a memory allocation error occurs if use dynamic allocation (Runtime error if use vector class). But if I combine all my functions together within one file (which means do not create new object for MapInfo, they are not written in classes, just simple function calls) , then the program works as expected without any crash. So this is the part I got confused, why cant I just create another 2D array? Is that because the allocated memory is not freed? or there is something to do with OO design? Actually I can not free the double array as I still need to pass it to another function. So how can I fix that part?
And thank you for your comment on the GUI part, I will take a look later.

What's in your class (in "mapInfo.h") ?

Because if it contains a member called map_info, then your getCoordinates function has to resolve between the member name and the parameter name, and that just isn't going to work.

Further, if you DO have a 2D vector of double as a member variable (and you should), then you definitely should not be returning the same thing by value to the outside world.

Here is the file "mapInfo.h"

#ifndef MAPINFO_H
#define MAPINFO_H
#include <iostream>
#include <vector>

class MapInfo 
{
public:
	MapInfo();
	std::vector<std::vector<double> > getMapInfo();
	int getNumOfBlds();
	int getNumOfCorners();
	std::vector<std::vector<double> > getCoordinates(std::vector<std::vector<double> >,int,int);
	std::vector<std::vector<double> > getWallFuncs(std::vector<std::vector<double> >,int);
	double getGrad(double,double,double,double);
private:
	int no_of_blds;		//number of buildings in the map
	int no_of_corners;	//total number of corners in the map
	std::vector<std::vector<double> > bld_info;	//allocate memory for building info
	std::vector<std::vector<double> > CoordinateArray;	//allocate memory for coordinate array
	std::vector<std::vector<double> > WallFuncs;
};
#endif

If I can not get the 2D variable by value in the main function, how can I get the variable from the member function in class "MapInfo"? I have tried to use "double **" in order to pass the variable but it still does not work at the "CoordinateArray" part. I am confused at the part why it can parse the file and get everything into a 2D array "mapInfo" properly but not for "CoordinateArray"? If I can not get the 2D array return by value, then what should I do in order to get the 2d arrays in the main function? Because I do need them to pass between different functions from different classes.
Thank you.

I suggest that you familiarize yourself with the concept of passing by reference, including passing by const reference. And while you are at it, check out returning by reference too.
Now you are passing vectors by value into functions that are supposed to modify the input, however, that simply will not work.

To me it appeared that you are in the belief that the following
case would not work:

std::vector<std::vector<double> > aFunction( void )
{
    // Grab the needed vector here ...
    std::vector<std::vector<double> > aVector;

    // Modify the vector here as you wish ...
   for( ... )

   // All done, return the vector
   return aVector;
}

int main()
{
    // A vector 
    std::vector<std::vector<double> > MyVector;
    // Go do the stuff ...
    MyVector = aFunction();

    return 0;
}

It works however.

Hello, mitrmkar,
Thank you for your reply.
I have looked at some references on passing by value and passing by reference, so basically instead of passing the entire object as the function argument, only the address of the array is used to modify the content, is this correct?
Then I tried this:
change the function "getMapInfo()" to

std::vector<std::vector<double> > &getMapInfo();

and "getCoordinates()" to

std::vector<std::vector<double> >&getCoordinates(const std::vector<std::vector<double> > &, int,int);

with others remain the same(getWallFuncs() will be tested later if the above works), and in the main function, I was trying to get some output from "getMapInfo()" by using:

std::vector<std::vector<double> > &mapInfo = map.getMapInfo();
cout<<mapInfo[0][0]<<" "<<mapInfo[0][1]"..........

which reports an error saying "vector subscript out of range...", and I tried also cout<<map.getMapInfo()[0][0] which reports the same error message. So I am confused what I have done wrong here?
Thank you

Hello all,
So I am just wondering if I can do this in c++:
I got one class (called "MapInfo")with 2 member functions, one is used to get the content of the file and save all the numbers in the file into a 2D array and return this array, this function is called "getMapInfo()", and another one called "getCoordinates()" which uses the return value of "getMapInfo()" as one of its inputs and return another 2D array with the coordinates infomation for each single corner of the building. so both of the 2 functions return different 2D arrays with different dimensions, and both of them creates a new 2D array in the funtion call.
now in the main function which is written in another file, I need to pass the return values between each function, now I know I need to pass the 2D array by reference as mitrmkar pointed out, so I am not sure if I can do this:

int main(){
MapInfo map;
MapInfo &rMap = map;
std::vector<std::vector<double> > &mapInfo = rMap.getMapInfo();
}

( getMapInfo is defined as :std::vector<std::vector<double> > &getMapInfo(); which returns the reference to the 2D array )
and I think "mapInfo" should be the reference to the 2D array but when I was trying to access its contents like :cout<<rMap.getMapInfo()[0].size(); it reports an error "vector subscript out of range". So why it did not return the correct 2D array?
Also if I try to call the second function "getCoordinates()", the program crash at the point where a new 2D array is defined in this function:
std::vector<std::vector<double> > CoordinateArray(total_corners,std::vector<double>(3));
I am very confused in this part why a new 2D array can not be created. because when I did everything within one file without define any class, then everything works fine even if I pass the 2D vectors by value.
Can anyone please help me on this? I have been stucked here for quite a long time and still can not find the solution.
Thank you,
Regards

I don't think you should be returning a map at all from your getMapInfo(). You already store the same information inside the class.

void MapInfo::getMapInfo()
{
	char str[100];
	char name[80];
	int max_corner_no = 10;
	int building_number;
	int corner_number;
	int index;
	char *tokenPtr;	
 
	cout << "Enter file name:";
	cin.getline(name,79);
	ifstream dataFile(name,ios::in);
	if(!dataFile)
	{
		cerr << "File could not be opened\n";
		exit(1);
	}

	// skip the first 5 lines 
	for (int i=0; i<5;i++)
	{
		dataFile.getline(str,99);
	}

	//get the number of buildings from the 6th line
	dataFile.getline(str,99);
	no_of_blds = atoi(&str[0]);

	//!!std::vector<std::vector<double> > bld_info(no_of_blds,std::vector<double>(max_corner_no*2+3));
	//!! Here, you should do bld_info.resize() on the vector bld_info stored in the class.

	// now get the data
	while(!dataFile.eof())
	{
		index=1;
		dataFile.getline(str,99);
		
		// get the building coordinates
		tokenPtr = strtok(str," ");
		//get the building number first
		building_number = atoi(tokenPtr);
		tokenPtr = strtok(NULL," ");
		//now get the number of corners of this building 
		corner_number = atof(tokenPtr);
		no_of_corners += atoi(tokenPtr);
		tokenPtr = strtok(NULL," ");
		bld_info[building_number-1][0] = corner_number;
		while (tokenPtr != NULL)
		{
			bld_info[building_number-1][index] = atof(tokenPtr);
			tokenPtr = strtok(NULL," ");	
			index++;
		}
	}
	//!!return bld_info;
}

There's no need to return anything, because anything you stored inside class member variables will be preserved until the next class method you invoke. In fact, they're preserved until the class instance (in main) goes out of scope.

As an aside, I think you should pass the filename to be read to getMapInfo(). Keep the purpose of any single function tightly focussed on the specific problem at hand.

The key part of 'OO' is that the data is hidden, so when you're using 'get' functions just to return information which you later pass as a parameter to some other function of the same class, then you're definitely doing the wrong thing.


Likewise, when you call your getCoordinates(), there's no need to pass in copies of the vector (and sizes), since this is already in the class.
So

void MapInfo::getCoordinates(void)
{
	int bld_corners;
	int x,y;
	int coor_index=0;
	cout<<"here is fine\n";
	//!!std::vector<std::vector<double> > CoordinateArray(total_corners,std::vector<double>(3));
	//!! again, resize() the one in the class
	//!! total_blds and total_corners are also in the class, no need to pass as params
	for (int bld_num=0; bld_num<total_blds; bld_num++)
	{
		bld_corners = map_info[bld_num][0];
		int cnt=1;
		for (int j=0; j<bld_corners; j++)
		{
			x=map_info[bld_num][cnt];
			y=map_info[bld_num][cnt+1];
			CoordinateArray[coor_index][0] = x;
			CoordinateArray[coor_index][1] = y;
			CoordinateArray[coor_index][2] = bld_num+1;
			coor_index++;
			cnt+=2;
		}
	}
	//!!return CoordinateArray;
}

Ditto for getWallFuncs(), it uses data inside the class to update other data inside the class. The outside world just doesn't need to know what's going on.

Your first 3 lines of main should just be

int main()
{
	MapInfo map;
	map.getMapInfo();
	map.getCoordinates();
	// more map.methods here
}

Hello, Salem,
Thank you so much for your helpful comment, It really helps me a lot.
Best Regards.

Hello, Salem,
I did some modifications of my code as you suggested, and here is what I got:

#ifndef MAPINFO_H
#define MAPINFO_H
#include <iostream>
#include <vector>

class MapInfo 
{
public:
	MapInfo();
	void getMapInfo(char []);
	void getCoordinates();
	void getWallFuncs();
	int getNumOfBlds();
	int getNumOfCorners();
	double getGrad(double,double,double,double);
	std::vector<std::vector<double> > & getRefMapInfo();
	std::vector<std::vector<double> > & getRefCoordinateArray();
private:
	int no_of_blds;		//number of buildings in the map
	int no_of_corners;	//total number of corners in the map
	std::vector<std::vector<double> > bld_info;	//allocate memory for building info
	std::vector<std::vector<double> > CoordinateArray;	//allocate memory for coordinate array
	std::vector<std::vector<double> > WallFuncs;
};
#endif
#include "mapInfo.h"
#include <iostream>
#include <fstream>
#include <vector>
using namespace std;

MapInfo::MapInfo()
{
}


//this function read the map in uda format and returns a 2D array contains building infomation.
//in form of: [building_number][no_of_corners x y.....wall_thickness bld_type]
void MapInfo::getMapInfo(char file_name[80])
{
	char str[100];
	char name[80];
	int max_corner_no = 10;
	int building_number;
	int corner_number;
	int index;
	char *tokenPtr;	
 
	ifstream dataFile(file_name,ios::in);
	if(!dataFile)
	{
		cerr << "File could not be opened\n";
		exit(1);
	}

	// skip the first 5 lines 
	for (int i=0; i<5;i++)
	{
		dataFile.getline(str,99);
	}

	//get the number of buildings from the 6th line
	dataFile.getline(str,99);
	no_of_blds = atoi(&str[0]);

	//std::vector<std::vector<double> > bld_info(no_of_blds,std::vector<double>(max_corner_no*2+3));

	//resize the vector which contains the building infomation
	bld_info.resize(no_of_blds);
	for(int i=0; i<no_of_blds; i++)
	{
		bld_info[i].resize(max_corner_no*2+3); //*2 because we need x and y coordinates, rest 3 for number
													//of corners, wall thickness and building type respectively.*/
	}

	// now get the data
	while(!dataFile.eof())
	{
		index=1;
		dataFile.getline(str,99);
		
		// get the building coordinates
		tokenPtr = strtok(str," ");
		//get the building number first
		building_number = atoi(tokenPtr);
		tokenPtr = strtok(NULL," ");
		//now get the number of corners of this building 
		corner_number = atof(tokenPtr);
		no_of_corners += atoi(tokenPtr);
		tokenPtr = strtok(NULL," ");
		bld_info[building_number-1][0] = corner_number;
		while (tokenPtr != NULL)
		{
			bld_info[building_number-1][index] = atof(tokenPtr);
			tokenPtr = strtok(NULL," ");	
			index++;
		}
	}
}

//this function returns the number of buildings in the map
int MapInfo::getNumOfBlds ()
{
	return no_of_blds;
}

//this function returns the total number of corners for all the buildings
int MapInfo::getNumOfCorners ()
{
	return no_of_corners;
}

//this function returns the gradient of a straight line given two points
double MapInfo::getGrad(double x1,double y1,double x2,double y2)
{
	return (y2-y1)/(x2-x1);
}

//this function returns the coordinates of all the corners in a 2D array
//in form of [corner_number][x,y,bld_num]
void MapInfo::getCoordinates()
{
	int x,y;
	int coor_index=0;
	CoordinateArray.resize(no_of_corners);
	for(int i=0; i<no_of_corners; i++)
	{
		CoordinateArray[i].resize(3);
	}
	for (int bld_num=0; bld_num<no_of_blds; bld_num++)
	{
		int cnt=1;
		for (int j=0; j<no_of_corners; j++)
		{
			x=bld_info[bld_num][cnt];
			y=bld_info[bld_num][cnt+1];
			CoordinateArray[coor_index][0] = x;
			CoordinateArray[coor_index][1] = y;
			CoordinateArray[coor_index][2] = bld_num+1;
			coor_index++;
			cnt+=2;
		}
	}
}


//this function evaluates all the wall functions
//input of this function should be map_info evaluated from getMapInfo()
//output of this function is the coefficients of each line(wall) in form y=kx+b,
//in form of [wall_num][k,b,x1,y1,x2,y2,bld_num]
void MapInfo::getWallFuncs() //number of walls equals to number of corners
{
	double x1,y1,x2,y2;
	double temp_x,temp_y;	
	//initialize temp_x and temp_y values to the first corner coordinate in the file
	temp_x = CoordinateArray[0][0];
	temp_y = CoordinateArray[0][1];
	double k,b;	//straight line coefficients

	//allocate memory for the wall coefficients and relevant numbers
	//7 here stores all the relevant numbers*/
	WallFuncs.resize(no_of_corners);
	for(int i=0; i<no_of_corners; i++)
	{
		WallFuncs[i].resize(7);
	}

	for (int wall_num=0; wall_num<no_of_corners-1; wall_num++)
	{
		//test if the two walls belong to the same building
		//same building in this case
		if(CoordinateArray[wall_num][2] == CoordinateArray[wall_num+1][2])
		{
			x1 = CoordinateArray[wall_num][0];
			y1 = CoordinateArray[wall_num][1];
			x2 = CoordinateArray[wall_num+1][0];
			y2 = CoordinateArray[wall_num+1][1];
			k = getGrad(x1,y1,x2,y2);
			b = y2-k*x2;
		}

		// two edges from different buildings
		else
		{
			x1 = CoordinateArray[wall_num][0];
			y1 = CoordinateArray[wall_num][1];
			x2 = temp_x;
			y2 = temp_y;
			k = getGrad(x1,y1,temp_x,temp_y);
			b = y1-k*x1;

			temp_x = CoordinateArray[wall_num+1][0];
			temp_y = CoordinateArray[wall_num+1][1];
		}
		WallFuncs[wall_num][0] = k;
		WallFuncs[wall_num][1] = b;
		WallFuncs[wall_num][2] = x1;
		WallFuncs[wall_num][3] = y1;
		WallFuncs[wall_num][4] = x2;
		WallFuncs[wall_num][5] = y2;
		WallFuncs[wall_num][6] = CoordinateArray[wall_num][2];
	}
	//last wall coefficients
	k = getGrad(x2,y2,temp_x,temp_y);
	b = y2-k*x2;
	WallFuncs[no_of_corners-1][0] = k;
	WallFuncs[no_of_corners-1][1] = b;
	WallFuncs[no_of_corners-1][2] = x2;
	WallFuncs[no_of_corners-1][3] = y2;
	WallFuncs[no_of_corners-1][4] = temp_x;
	WallFuncs[no_of_corners-1][5] = temp_y;
	WallFuncs[no_of_corners-1][6] = CoordinateArray[no_of_corners-1][2];
}

//this function returns the reference to the map information
std::vector<std::vector<double> > & MapInfo::getRefMapInfo()
{
	return bld_info;
}

//this function returns the reference to the coordinate array
std::vector<std::vector<double> > & MapInfo::getRefCoordinateArray()
{
	return CoordinateArray;
}

and in the main function, I got a run time error:

#include "mapInfo.h"
#include "firstLayerVisibility.h"
#include <iostream>
#include <vector>
using namespace std;

int main()
{
	MapInfo map;
	map.getMapInfo("map1.uda");
	std::vector<std::vector<double> > &mapInfo = map.getRefMapInfo();
	cout<<mapInfo[3][0]<<" "<<mapInfo[3][1]<<" "<<mapInfo[3][2]<<" "<<mapInfo[3][3]<<" "<<mapInfo[3][4]<<"\n"; //can be printed out correctly
	map.getCoordinates();  //crashed at here
	map.getWallFuncs();
	return 0;
}

the program crashed at the point "CoordinateArray.resize(no_of_corners);" in the function "getCoordinates()". It can print the "mapInfo" correctly, but I have no idea why it does not work in here, as both of the two function pretty much doing similar task which stores data into 2D vectors, so what I did wrong in here?
In this case, if getMapInfo() is called first, which causes the relevant data to be saved into the vector "bld_info", so any other member function of this class who need this data can have the access of the data after this function call, without passing it as a parameter, is this correct?
As I need the 2D vectors to be returned and used as inputs to some other functions from other classes, so is this the correct way of passing by reference: std::vector<std::vector<double> > & getRefMapInfo();
std::vector<std::vector<double> > & getRefCoordinateArray();
Sorry I keep asking some basic stuff in c++ but I do need to get this clear, I am very appreciated for your time and help.
Best Regards,

... so any other member function of this class who need this data can have the access of the data after this function call, without passing it as a parameter, is this correct?

Yes it is.

As I need the 2D vectors to be returned and used as inputs to some other functions from other classes, so is this the correct way of passing by reference: std::vector<std::vector<double> > & getRefMapInfo();
std::vector<std::vector<double> > & getRefCoordinateArray();

Yes, and if a function is not supposed to modify a vector it receives, you can use a const reference, e.g. function() receives the vector as read-only void function([B]const[/B] std::vector<std::vector<double> > & vect);

Thanks for the replies.
I still can not get this program to work. I changed the method getMapInfo() to this:

void MapInfo::getMapInfo(std::string file_name)
{
	char str[256];
	int max_corner_no = 10;
	int building_number;
	int corner_number;
	int index;
	char *tokenPtr;	
 
	ifstream dataFile(file_name.c_str(),ios::in);
	if(!dataFile)
	{
		cerr << "File could not be opened\n";
		exit(1);
	}

	// skip the first 5 lines 
	for (int i=0; i<5;i++)
	{
		dataFile.getline(str,256);
	}

	//get the number of buildings from the 6th line
	dataFile.getline(str,256);
	no_of_blds = atoi(&str[0]);

	//std::vector<std::vector<double> > bld_info(no_of_blds,std::vector<double>(max_corner_no*2+3));

	//resize the vector which contains the building infomation
	bld_info.resize(no_of_blds);
	for(int i=0; i<no_of_blds; i++)
	{
		bld_info[i].resize(max_corner_no*2+3); //*2 because we need x and y coordinates, rest 3 for number
													//of corners, wall thickness and building type respectively.*/
	}

	// now get the data
	while(dataFile.getline(str,256))
	{
		index=1;		
		cout<<str<<"\n";
		// get the building coordinates
		tokenPtr = strtok(str," ");
		//get the building number first
		building_number = atoi(tokenPtr);
		tokenPtr = strtok(NULL," ");
		//now get the number of corners of this building 
		corner_number = atof(tokenPtr);
		no_of_corners += atoi(tokenPtr);
		tokenPtr = strtok(NULL," ");
		bld_info[building_number-1][0] = corner_number;
		while (tokenPtr != NULL)
		{
			bld_info[building_number-1][index] = atof(tokenPtr);
			tokenPtr = strtok(NULL," ");	
			index++;
		}
	}
}

I have changed the part for reading the file in order to get the data, and I have checked the output which prints out the correct output as expected. However, I did not use string stream to parse the file as the input file is in the format of something like this:

The Buildings and header line
Version: 1.0
Size of the area:
Max.x = 500.00
Max.y = 500.00
4 0 0 500.00 500.00
1 4 100.00 350.00 130.00 350.00 130.00 300.00 100.00 300.00 20.00 25.00 0
2 4 200.00 350.00 300.00 350.00 300.00 300.00 200.00 300.00 20.00 25.00 0
3 4 200.00 150.00 300.00 150.00 300.00 100.00 200.00 100.00 20.00 25.00 0
4 4 100.00 150.00 130.00 150.00 130.00 100.00 100.00 100.00 20.00 25.00 0

to represent each building's coordinates, so a string tokenizer is needed in order to parse every single number and save it in the 2D array. I have searched on the web and there is no method like "stringTokenizer" which is able to parse the line in string stream, so I used char[] instead.
The same problem happens as before, where the program crashed at the point
CoordinateArray.resize(no_of_corners);
in the function getCoordinateArray(), which gives a RunTime error. This is so confusing as getMapInfo() gives the correct value, whereas getCoordinateArray() does a very similar job but crashed somehow, I still can not figure out which part I have missed or my approach is wrong?
Thanks for the help.
Regards,

What is the value of no_of_corners at the point where you do
CoordinateArray.resize(no_of_corners);
no_of_corners seems to be a member variable, I take that you are initializing it to zero before using it anywhere (?).

That's exactly the part that I missed out, I got the program working now. Thank you so much for your helpful comments, mitrmkar and salem, I am very appreciated for your time and comments.
Best Regards

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.