1,105,177 Community Members

Array of Structs member comparison help

Member Avatar
livinFuture
Newbie Poster
17 posts since Jan 2011
Reputation Points: 0 [?]
Q&As Helped to Solve: 1 [?]
Skill Endorsements: 0 [?]
 
0
 

Hello all. I am having difficulty getting my program to output data correctly. I have a class member function that is supposed to return the value of a specific member of a struct element based on identification with its (the struct element's) other members.

float MatrixType::valueAt(int i, int j) const
{ // code to return the float value at
  // significant location row i col j
	if(i == matrix[length].row && j == matrix[length].col)
		return matrix[length].value;
	// checks to match up row and col to find correct value
	else
		return 0.0;
} // end accessor valueAt

The matrix[] array is of type struct.

The struct is as follows:

struct oneitem
{
	int row, col;
	float value;
};

I know that I need to somehow change the count of the array (i.e. length) so that it searches through the entire array of structs to find one with matching row and col. I'm not sure if my if statement for comparison is correct either.

In a broad sense what I am trying to do with this program is input a two-dimensional matrix from .txt file and save only the non-zero values of the matrix into a one-dimensional array of structs. Then I want to take that one-dimensional array of structs and output its values so as to recreate the original two-dimensional matrix. I am effectively trying to take a dense matrix filled with numerous 0s and save it more effeciently (using an array of structs; I'm not up to par with pointers).

I have gotten to the point of reading in all the values perfectly and storing them (I'm fairly certain it's beeing stored correctly). Everytime I output the values, however, I either get a matrix filled with all 0s or I'll get the first non-zero value correct and all other values will be 0.

Member Avatar
Banfa
Master Poster
798 posts since Mar 2010
Reputation Points: 582 [?]
Q&As Helped to Solve: 132 [?]
Skill Endorsements: 12 [?]
Featured
 
0
 

You could implement this fairly easily with a std::map rather than writing all your own code.

However clearly in your valueAt method you need to be iterating over the entire array not just performing a single if test. Your MatrixType must surely store a std::vector (or array) of oneitem and the length of that array (vectors provide their length). You need to iterate over the whole array testing each location until you find one that matches or return 0.0 if none match.

With a std::map you could have a key class

class MatrixKey
{
public:
  MatrixKey(int r, int c) : row(r), col(c)
  {
  }

  // Implement various getters, setters and comparison operators

private:
   int row, col;
};

Then declare your map std::map<MatrixKey, float> , use it internally to MatrixType when you need to find a value create a MatrixKey for row/col look it up in the map and if it isn't found return 0.0;

Member Avatar
livinFuture
Newbie Poster
17 posts since Jan 2011
Reputation Points: 0 [?]
Q&As Helped to Solve: 1 [?]
Skill Endorsements: 0 [?]
 
0
 

I noticed that in another of my class member functions I increment length so I changed to using a temp value for my valueAt function.

float MatrixType::valueAt(int i, int j) const
{ // code to return the float value at
  // significant location row i col j
	int temp = 0; // temp value holder
	for(; temp < MAXSIZE; temp++){
		if(i == matrix[temp].row && j == matrix[temp].col)
		{
			temp++;
			return matrix[temp-1].value;
		} // checks to match up row and col to find correct value
		else
			return 0.0;
	} // end for loop
} // end accessor valueAt

The function I had incrementing member variable length is my storeItem function:

void MatrixType::storeItem(int i, int j, float v)
{
	if(v != 0)
	{ // if element is significant store members into array of structs
		matrix[length].row = i; // row index stored
		matrix[length].col = j; // col index stored
		matrix[length].value = v; // value index stored
		  // now element length in the matrix has the value v and 
		  // can be identified by members row and col
		length++; // increment for next significant value
	} // end if: the value has been stored at row and col
	// else
		// value is insignificant (ie is zero)
		// move on to next element
} // end mutator storeItem

I figured that by incrementing length in this function length's value was always the latest member in the array, so using it for comparison in my valueAt function would never yield the right value.

By changing my valueAt function to where it is now my output will only show the first significant value in the matrix correctly. All other values show zero.
i.e.
Input Matrix
0.0 3.1 0.0 0.0 0.0 0.0 4.2
5.8 0.0 0.0 0.0 0.0 0.0 0.0
0.0 0.0 1.7 2.3 0.0 0.0 0.0
0.0 0.9 9.4 0.0 0.0 0.0 0.1
0.0 0.0 0.0 0.0 4.2 0.0 0.0

Output Matrix
0.0 3.1 0.0 0.0 0.0 0.0 0.0
0.0 0.0 0.0 0.0 0.0 0.0 0.0
0.0 0.0 0.0 0.0 0.0 0.0 0.0
0.0 0.0 0.0 0.0 0.0 0.0 0.0
0.0 0.0 0.0 0.0 0.0 0.0 0.0

If I change my input, say make the 3.1 a 0.0 and leave the rest as is, the Output Matrix will show the 4.2 from the Input Matrix in the correct place (row 0 col 6) but all other values will return 0.

For further clarity: This is the function in main using the valueAt member function of class MatrixType.

void print_matrix(ostream& outfile, const MatrixType& matrix)
{ // exports sparse matrix to outfile in dense matrix form
	int sigRows, sigCols; // significant number of rows and columns
	int i, j; // row and col index of sparse matrix; significant rows and columns
	float v; // holds temp value for output

	sigRows = matrix.numRows(); // get numRows
	sigCols = matrix.numCols(); // get numCols

	outfile << sigRows << " " << sigCols << endl;// output numRows and numCols to file
	cout << "Output Matrix\n";
	for(i = 0; i < sigRows; i++) // each row
	{
		for(j = 0; j < sigCols; j++) // each col
		{
			v = matrix.valueAt(i, j); // get value at location i,j
			cout << v << " ";
			outfile << v << " "; // output value at location i,j
		} // end col for loop
		cout << endl;
		outfile << endl; // output file gets new line after end of col reached
	} // end row for loop
}

Any help getting to point me in the right direction for getting this output to function correctly would be greatly appreciated.

Member Avatar
livinFuture
Newbie Poster
17 posts since Jan 2011
Reputation Points: 0 [?]
Q&As Helped to Solve: 1 [?]
Skill Endorsements: 0 [?]
 
0
 

Your MatrixType must surely store a std::vector (or array) of oneitem and the length of that array (vectors provide their length). You need to iterate over the whole array testing each location until you find one that matches or return 0.0 if none match.

My matrix[] array stores an array of structs (oneitem). I have a private member variable length as well that stores the number of significant values from the matrix (i.e. numerous oneitem datas). I tried to implement a for loop for testing each value in the array of structs, but I can only seem to return the value of the first significant value. All others are beeing returned as 0 for some reason unknown to me. (I have my current code posted above)

With a std::map you could have a key class

Then declare your map std::map<MatrixKey, float> , use it internally to MatrixType when you need to find a value create a MatrixKey for row/col look it up in the map and if it isn't found return 0.0;

I can't use a dense matrix. I'm trying to store a dense matrix filled with numerous 0 values as an array of structs, which only holds significant values (ones not equal to 0). I am then trying to display that array of structs in the same format as the original dense matrix, so main is unaware that the matrix is beeing stored differently from a full 2D array.

Member Avatar
nezachem
Practically a Posting Shark
896 posts since Dec 2009
Reputation Points: 616 [?]
Q&As Helped to Solve: 197 [?]
Skill Endorsements: 0 [?]
 
1
 

In the valueAt, if the very first comparison fails you immediately enter the else clause and return 0. Get rid of else and move return 0.0 out of the loop.

Member Avatar
Banfa
Master Poster
798 posts since Mar 2010
Reputation Points: 582 [?]
Q&As Helped to Solve: 132 [?]
Skill Endorsements: 12 [?]
Featured
 
0
 

I can't use a dense matrix. I'm trying to store a dense matrix filled with numerous 0 values as an array of structs, which only holds significant values (ones not equal to 0). I am then trying to display that array of structs in the same format as the original dense matrix, so main is unaware that the matrix is beeing stored differently from a full 2D array.

I'm aware of that, I not suggesting you use a dense matrix, I'm suggesting you use a sparse matrix internally to your own class implemented using a std::map to handle all the look-up and data storage and allocation needs leaving you to concentrate on implementing the logic of the sparse matrix and removing from you the need to implement memory allocation, look-up functions and other utilities.

Member Avatar
livinFuture
Newbie Poster
17 posts since Jan 2011
Reputation Points: 0 [?]
Q&As Helped to Solve: 1 [?]
Skill Endorsements: 0 [?]
 
0
 

Thank you nezachem! It's working perfectly now. Those loops and return commands always get me.

Question Answered as of 2 Years Ago by Banfa and nezachem
You
This question has already been solved: Start a new discussion instead
Post:
Start New Discussion
View similar articles that have also been tagged: