I am working on a C++ class that consists of a 2D Vector of Doubles. I am about to create the 2D Vector but when I try to edit the values inside of it, the program crashes. I have tried using the [][] operator and setting it equal to myDub and I have tried using a class like myMat.editSlot(i,j,myDub) and both have caused the program to crash.
//n == # of rows and cols (all matrices are square)
//infile opens the file properly
mat my_mat(n,n);
// Read input data
for (int i=0; i<n; i++) {
for (int j=0; j<n; j++) {
double myDub;
inFile >> myDub;
my_mat.editSlot(i,j,myDub);
}
}
and here is the class:
class mat
{
mat( int x , int y ) {
int row = x;
int col = y;
vector<vector<double>> A( row , vector<double>( row , 0 ) );
for ( int i = 0; i<row; i++ )
{
for ( int j = 0; j<col; j++ )
{
cout << setw( 6 ) << A[i][j];
}
cout << endl;
}
}
void editSlot( int x , int y , double val ) {
A[x][y] = val;
}
vector<vector<double>> A;
private:
int n;
};
It looks to me that the way you're initializing A is wrong. Try something like this:
A = vector<vector<double>>( row , vector<double>( row , 0 ) );
Another thing to consider both the constructor and the edit function aren't declared public.
Main problem that leads to crush is that you change size of a temporal vector A in your constructor while A vector that you declared as a field in your class object is not touched.
I suggest doing something like this:
mat(int x,int y) : A(y,vector<double>(x,0)) {
int row = x;
int col = y;
for(int i=0; i<row; i++)
{
for(int j=0; j<col; j++)
{
cout<<setw(6)<<A[i][j];
}
cout<<endl;
}
}
}
In this case you won't hide your A field in class with temporal A object in constructor function.
Also please pay attention not to swap x and y in your functions. For example, you have an error in your editSlot function:
void editSlot( int x , int y , double val ) {
A[x][y] = val;
}
, it should be:
A[y][x] = val;
according to constructor.
Related
I tried to solve the following problem:
Let x,y,z be integers in the domain [-5,5]. Display the number of solutions (x,y,z) that satisfy 3*x+y^3-z^2=0. My initial solution was this:
int main() {
int x=-6;
int y=-6;
int z=-6;
int p=0;
for(int i=-5; i<6; i++)
{
x++;
for (int j=-5; j<6; j++)
{
y++;
for(int k=-5; k<6; k++)
{
z++;
if(3*x +y*y*y -z*z==0)
p++;
}
}
}
std::cout<< p ;
return 0;
}
This is the correct solution:
int main() {
int x=-5;
int y=-5;
int z=-5;
int p=0;
for( x=-5; x<=5; x++)
for (y=-5; y<=5; y++)
for( z=-5; z<=5; z++)
if(3*x +y*y*y -z*z==0)
p++;
std::cout<< p;
return 0;
}
Why are these two different and what did I do wrong in the first one?
In the "correct" solution, y begins again from -5 for each new value of x. In your version, y carries on incrementing from its previous value, so the second iteration covers [5,15], the third [15,25], and so on.
The weird extra variable j covers the range you want y to cover each time, but y itself does not.
In the incorrect code, the variables y and z are not reset to the beginning of their range at the begining of the loop.
An even shorter correct exemple would be:
int main()
{
int p = 0;
for( int x=-5; x<=5; ++x )
for( int y=-5; y<=5; ++y )
for( z=-5; z<=5; ++z)
if( 3*x + y*y*y - z*z == 0 )
++p;
std::cout << p << std::endl;
return 0;
}
The variable initializations can be put directly into the loops.
As they are trivial variables there is no performance penalty.
I have written a function to raise matrix to a certain power.
But when running the code the result is the memory location not the actual values. I think the problem is with the pointers.
My code:
#include <iostream>
using namespace std;
typedef int array2d [2][2];
array2d A,B,r;
void pow(array2d* r,array2d C);
int main(){
array2d resa,resb;
A[0][0]=2;
A[0][1]=2;
A[1][0]=2;
A[1][1]=2;
B[0][0]=3;
B[0][1]=3;
B[1][0]=3;
B[1][1]=3;
r[0][0]=1;
r[0][1]=0;
r[1][0]=0;
r[1][1]=1;
pow(&resa,A);
for(int i=0;i<2;i++){
for(int j=0;j<2;j++)
{
cout<<resa[i][j]<<" ";
}
cout<<endl;
}
pow(&resb,B);
for(int i=0;i<2;i++){
for(int j=0;j<2;j++)
{
cout<<resb[i][j]<<" ";
}
cout<<endl;
}
return 0;
}
void pow(array2d* r, array2d C)
{
array2d temp;
for(int w=0;w<3;w++)
{
for(int i=0;i<2;i++){
for(int j=0;j<2;j++)
{
temp[i][j]=0;
for(int k=0;k<2;k++)
temp[i][j]+=(*r)[i][k]*C[k][j];
}}
for(int i=0;i<2;i++){
for(int j=0;j<2;j++)
{
(*r)[i][j]=temp[i][j];
}}
}
}
How can I solve this problem.
Thank You.
Your error has nothing to do with pointers or addresses, but your algorithms is erroneous:
pow(&resa, A);
multiplies the matrix A with the uninitialized matrix resa which can yield any number of possible results.
The quick and dirty fix would be to initialize resa and resb as identity matrices:
array2d resa = { { 1, 0 }, { 0, 1 } };
array2d resb = { { 1, 0 }, { 0, 1 } };
EDIT or slightly better: Initialize r inside of pow
//passing r by pointer is not actually necessary here,
//but I don't want to modify too much of the code
(r*)[0][0] = 1;
(r*)[1][0] = 0;
(r*)[0][1] = 0;
(r*)[1][1] = 1;
The more elegant solution would be to first multiply the parameter C with itself, store the result in r and then go on with your algorithm.
On a side note: don't use c-style arrays, if you don't need them (especially not in typedefs). Use std::array instead, which will get rid of most of the confusion regarding to parameter passing.
you really should avoid global when you can, and using the same name in global and local variables is even worse
also the name of your variables MATTERS, here i call the input matrix IN and output matrix OUT (ok "n" should be called power)
using namespace std;
typedef int array2d [2][2];
void display( array2d a ) ;
void pow(array2d IN ,array2d OUT , int n);
int main()
{
array2d A,B;
array2d resa,resb;
A[0][0]=2;
A[0][1]=2;
A[1][0]=2;
A[1][1]=2;
B[0][0]=3;
B[0][1]=1;
B[1][0]=2;
B[1][1]=1;
pow (A , resa , 5);
pow( B , resb, 2 ) ;
return 0;
}
and
void pow(array2d IN, array2d OUT , int n )
{
for( int i = 0 ; i < 2 ; ++ i )
for( int j = 0 ; j < 2 ; ++ j )
OUT[i][j] = ( i == j ) ;
display( OUT ) ;
array2d temp;
for(int w=0;w<n;w++)
{
for(int i=0;i<2;i++)
{
for(int j=0;j<2;j++)
{
temp[i][j]=0;
for(int k=0;k<2;k++)
{
temp[i][j]+=OUT[i][k]*IN[k][j];
}
}
}
for(int i=0;i<2;i++){
for(int j=0;j<2;j++)
{
OUT[i][j]=temp[i][j];
}
}
display( OUT ) ;
}
}
with
void display( array2d a )
{
cout << endl ;
for( int i = 0 ; i < 2 ; ++ i )
{
for( int j = 0 ; j < 2 ; ++ j )
cout << a[i][j] << " " ;
cout << endl ;
}
}
The first parameter of your pow function, change it to the pass by reference: void pow(array2d &r,array2d C);
Then where you call it, call it like so: pow(resa,A);
Finally, you don't need to deference r in your pow function now, so (*r)[i][j]=temp[i][j]; can be changed to r[i][j]=temp[i][j];
I think this is what you wanted to do. ( pass by reference )
( I am not in front of a pc where I can test this right now, will confirm as soon as I can, and maybe flesh out why this is better ( can read up about pointers, heap memory and pass by reference )
I have a huge 3d vector where I store double values. In order to increase the performance I wanted to reserve the number of elements in advance as I know them before processing;however, I couldn't really figure it out how reserve&clear&erase work in this case.
I have implemented a small program which has 2d vector in this case, pls see the code snippet below:`
for(int counter = 0; counter < 2; counter++){
cout << "Counter-> " << counter << endl;
vector<vector<double> > vec2D;
vec2D.reserve(2);
// assign values to the vec
for(int i = 0; i < 2; i++){
vec2D[i].reserve(5);
for(int j = 0; j < 5; j++){
vec2D[i][j] = j;
}
}
// print the vector content
for(int i = 0; i < 2; i++){
for(int j = 0; j < 5; j++){
cout << vec2D[i][j] << "\t";
}
vec2D[i].clear();
cout << endl;
}
vec2D.clear();
}
When I run this code snippet it iterates thorugh the for loop just for once where it should do it twice; however, when I declare the vector outside of the for loop it does iterate twice. The output of the above snippet is:
Counter-> 0
0 1 2 3 4
0 1 2 3 4
Counter-> 1
Could you please make it clear how it actually should be in this case and how it works.
Thanks in advance.
You have a big problem in your code: reserve() does not change the size of the vector, only its storage capacity (to avoid system calls in the future).
What is needed in your case instead of reserve() is assign() or resize().
If you want any semblance of performance don't use vectors of vectors: this is terribly inefficient. This is probably the most efficient memory utilization, and faster access than vectors, although there are faster solution with some memory trade-offs:
class GridWithSmallDimensions
{
double * values;
int sizeX, sizeY, sizeZ;
public:
GridWithSmallDimensions(int x, int y, int z)
: sizeX(x), sizeY(y), sizeZ(z)
{
values = new double [x*y*z];
}
~ GridWithSmallDimensions()
{
delete [] values;
}
double get(int x, int y, int z)
{
return value[x+sizeX*(y+sizeY*z)];
}
void set(int x, int y, int z, double v)
{
value[x+sizeX*(y+sizeY)] = v;
}
};
Here's a slightly more involved implementation, aimed at reduction of index calculations:
class GridWithRowPointers
{
int sizeX, sizeY, sizeZ; // Dimensions
double * values; // Data
double ** rows; // Pointers to "rows" of data indexed by x
inline int getIndex(y, z) const // Get index of data within a row
{
return sizeZ * y + z;
}
public:
GridWithRowPointers(int x, int y, int z)
: sizeX(x), sizeY(y), sizeZ(z)
{
values = new double [x*y*z]; // Allocate data
rows = new (double*) [x]; // Allocate row pointers
for( int n = 0; n < sizeX; n++ )
{
rows[n] = values + sizeY * sizeZ;
}
}
~ GridWithRowPointers()
{
delete [] values;
delete [] rows;
}
inline double get(int x, int y, int z) const
{
// Access value via row pointer
return rows[ x ][ getIndex(y,z) ];
}
inline void set(int x, int y, int z, double v)
{
// Access value via row pointer
rows[ x ][ getIndex(y,z) ] = v;
}
};
I'm trying to modify the elements inside a vector. After I change a certain block in an array and display it again, it won't show the new values but instead, retain the previous output. Am I doing it wrong?
////////////////////////////////////////////////////
// This displays the array/maze
////////////////////////////////////////////////////
void displayMaze( vector< vector<char> > &maze ) {
for( int i = 0; i < ROW; i++ ) {
for( int j = 0; j < COL; j++ ) {
cout << "[" << maze[ i ][ j ] << "] ";
}
cout << endl;
}
}
////////////////////////////////////////////////////
// This is where I change a certain element
////////////////////////////////////////////////////
void updateMouse( vector< vector<char> > maze, const int &mouse_row, const int &mouse_col ) {
for( int row = 0; row < ROW; row++ ){
for( int col = 0; col < COL; col++ ) {
if( ( row == mouse_row ) && ( col == mouse_col ) ) {
maze[ row ][ col ] = 'M';
break;
}
}
}
}
updateMouse takes the maze argument by value. Any changes it makes to the vector are made to the local copy within the function, which will be destroyed when the function exits. Change the function so that it takes the maze argument by reference.
void updateMouse( vector<vector<char>>& maze, const int &mouse_row, const int &mouse_col ) {
// ^^^
The updateMouse function can also be simplified to
void updateMouse( vector<vector<char>>& maze, int mouse_row, int mouse_col ) {
if(mouse_row < maze.size()) {
if(mouse_col < maze[mouse_row].size()) {
maze[mouse_row][mouse_col] = 'M';
}
}
}
You should be passing your vector as a reference (or pointer):
void updateMouse( vector< vector<char> > & maze, const int &mouse_row, const int &mouse_col ) {
Otherwise what you do is you change the copy of the maze
Alright, I'm trying to implement a simple 2D matrix class right now. This is what it looks like so far:
template <typename Type>
class dyMatrix {
private:
Type *mat;
int width, height;
int length;
public:
dyMatrix (int _width, int _height)
: width(_width), height(_height), mat(0)
{
length = width * height;
mat = new Type[length];
};
// ---
int getWidth() {
return width;
};
int getHeight() {
return height;
};
int getLength() {
return length;
}
// ---
Type& operator() (int i, int j) {
return mat[j * width + i];
};
Type& operator() (int i) {
return mat[i];
};
// ---
~dyMatrix() {
delete[] mat;
};
};
To test it, and compare with static multi-dimensional arrays, I wrote the following snippet of code:
#include <iostream>
using namespace std;
/* matrix class goes here */
struct Coord {
int x, y;
Coord()
: x(0), y(0)
{};
Coord (int _x, int _y)
: x(_x), y(_y)
{};
void print() {
cout << x << ", " << y;
};
};
int main() {
dyMatrix<Coord> adabo(5, 7);
Coord inakos[5][7];
int i = 5, j = 0;
adabo(i, j) = *(new Coord(i, j));
inakos[i][j] = *(new Coord(i, j));
inakos[i][j].print();
adabo(i, j).print();
return 0;
}
"Adabo" and "Inakos" being arbitrarily chosen names. Upon execution, inakos prints its contents but the program crashes before adabo can do anything. Another interesting thing is that, if I give i and j values other than 5 and 0, like 5 and 1, respectively, it works fine.
I don't know what exact numbers work and which make the program go haywire, I only know that there's a irregularity here. What am I possibly doing wrong? I'm an amateur at C++, so I may or not have misused something in any of the structures.
If anyone also has the time, I'd very much like to know if there's any other error of notice in my matrix class. Anything that's not possibly related to the problem, but is a fallacy nevertheless.
I've also tested it with the following main(), but it still crashes after inakos prints its contents in [5][1]. Maybe it has to do not with dyMatrix, but a loosely-implemented Coord?
int main() {
dyMatrix<Coord> adabo(5, 7);
Coord inakos[5][7];
for (int i = 0; i < adabo.getHeight(); i++) {
for (int j = 0; j < adabo.getWidth(); j++) {
adabo(i, j) = *(new Coord(i, j));
inakos[i][j] = *(new Coord(i, j));
inakos[i][j].print();
cout << "; ";
}
cout << "\n\n";
}
cout << "\n\n\n";
Coord temp;
for (int i = 0; i < 7; i++) {
for (int j = 0; j < 5; j++) {
temp = adabo(i, j);
temp.print();
cout << "; ";
}
cout << "\n\n";
}
return 0;
}
edit: It hasn't to do with Coord. Just tested with a dyMatrix of ints and static matrix of ints, and it crashes after [5][0] nevertheless.
In your first example, you declared inakos[5][7] so the indices range from 0 to 4 and 0 to 6. inakos[5][0] and inakos[5][1] could therefore crash.
In your second example, you again declare inakos[5][7] yet you let the first index loop from 0 to 6. Again inakos[i][j] can crash. One fix is to switch your indices (ie, change to i<adabo.getWidth() and j<adabo.getHeight()).