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()).
Related
So I have written the a code for the lattice that does:
const int Lx = 5, Ly = 5;
const int L = Lx*Ly;
inline void vector_lattice(){
for (int i = 0; i < L+1; i++){
s[i]=0.0;
}
for (int i = 0; i < L; i++){
s[i] =1;
}
}
This was fine for what I was doing, but now I want to have an actual lattice of vectors begin gin at x1,y1 and stoping at x2,y2. But I want to ultimately rotate those vectors 'sin(theta)' or something like that, so I need to have positions like x1,y1,x2 and y2 to plot arrows that represent the directions of all the vector in the lattice, in this case 25 arrows in a lattice 5x5.
Any one knows what I'd need to change to achieve that?
It sounds like you know the physics, but not the programming. I would make a 2-dimensional array, so you can access it like s[x][y] = whatever; However you are asking how to iterate over a 2d array represented in a 1d array, and I can help you there.
All you need is a 1 to 1 mapping of x,y coordinates to the array's index. It doesn't really matter what that mapping is, as long as it is 1to1, but here's an example:
#include <iostream>
#include <vector>
typedef std::pair<double, double> physics_vector;
const int Lx = 5, Ly = 5;
const int L = Lx*Ly;
int get_index(int x, int y) { return y * Ly + x; }
// almost forgot
int get_x(int index) { return index % Lx; }
int get_y(int index) { return index / Lx; }
class lattice : public std::vector< physics_vector >{
public:
lattice() { resize(L); }
};
void iterate_over_lattice(std::vector<physics_vector> &s){
for (int y = 0; y < Ly; y++){
for (int x = 0; x < Lx; x++){
int index = get_index(x, y);
s[index] = physics_vector(1, 0);
std::cout << index << ", ";
}
std::cout << std::endl;
}
}
int main(){
lattice s;
iterate_over_lattice(s);
return 0;
}
You could write a wrapper around a std::vector<std::pair<std::pair<int,int>, std::pair<double,double>>> which represents a lattice site - its co-ordinates and direction respectively in each std::pair. Something similar to below could work well,
#include <iostream>
#include <utility>
#include <vector>
class lattice_sites {
typedef std::vector<std::pair<
std::pair<int,int>,
std::pair<double,double>
>> lattice_vector;
public:
lattice_sites() : _lat_vec() {}
// create a lattice site with given position and direction
void create_site(const std::pair<int,int>& _coords,
const std::pair<double,double>& _drctn) {
_lat_vec.push_back(std::make_pair(_coords, _drctn));
}
// rotate all lattice sites
void rotate_all(const double& _rot_angle) {
for (auto& x : _lat_vec) {
x.second.first = std::cos(_rot_angle); // rotate x-direction
x.second.second = std::sin(_rot_angle); // rotate y-direction
}
}
// write to stream
std::ostream& write(std::ostream& _os) {
for (const auto& x : _lat_vec) {
_os << x.first.first << " " << x.first.second << "\t" // coords
<< x.second.first << " " << x.second.second << "\n"; // direction
}
return _os;
}
private:
lattice_vector _lat_vec;
};
Then you can manipulate instances of this class as follows,
int main(void) {
lattice_sites sites;
const int n = 100;
for (int i = 0; i < n; ++i) {
sites.create_site(std::make_pair(i,i), std::make_pair(0.0,0.0));
}
double rotation_angle = 0.5; // radians
sites.rotate_all(rotation_angle);
sites.write(std::cout);
}
This may require some tweaking (and optimisations such as using resize in the constructor if you already know the size of the lattice), but you should get the gist of it.
my homework assignment is asking me to create a array2d class and I am having trouble compiling it. It crashes every time it is compiled and I am unsure what I am doing wrong. My debugger is saying it is during my set value portion but I am not sure what it is exactly. Help would be great!
#include <iostream>
using namespace std;
class array2D {
private:
int xRes, yRes;
float **xtable;
public:
array2D(int xRes, int yRes){
float **xtable;
xtable = new float*[yRes];
for(int i=0;i < yRes;i++) {
xtable[i] = new float[xRes];}}
~array2D(){
for (int i = 0; i<yRes; i++){
delete [] xtable[i];}
delete [] xtable;}
void getSize(int &xRes, int &yRes){}
int getValue (int x, int y){return xtable[x][y];}
void setValue(int x, int y, int Val) {xtable[x][y]=Val;}
};
int main() {
array2D *a = new array2D(320,240);
int xRes, yRes;
a->getSize(xRes,yRes);
for(int i=0;i < yRes;i++){
for(int j=0;j < xRes;j++){
a->setValue(i,j,100); // constant value of 100 at all locations
}
}
for(int i=0;i < yRes;i++){
for(int j=0;j < xRes;j++){
cout << a->getValue(i,j) << " ";
}
cout << endl;
}
delete a;
}
In these lines
array2D(int xRes, int yRes){
float **xtable;
you are declaring a local variable. The class member variable of the same name remains uninitialized and you use that later.
Remove the second line.
Also, the member variables xRes and yRes are not initialized either.
Use:
array2D(int xResIn, int yResIn) : xRes(xResIn), yRes(yResIn) {
xtable = new float*[yRes];
for(int i=0;i < yRes;i++) {
xtable[i] = new float[xRes];
}
}
Also, change
void getSize(int &xRes, int &yRes){}
to
void getSize(int &xResOut, int &yResOut)
{
xResOut = this->xRes;
yResOut = this->yRes;
}
As you expand this class, keep in mind The Rule of Three and implement the copy constructor and copy assignment operator.
array2D(array2D const& copy) { ... }
array2D& operator=(array2D const& rhs) { ... }
I am using a dynamic array from boost in one of my classes and having trouble to write a proper getter function for it. Heres what I tried (I checked the size of the array within the class setter and with the getter from the main function):
#include <iostream>
#include "boost/multi_array.hpp"
using namespace std;
using namespace boost;
typedef multi_array<int, 3> array3i;
class Test {
private:
array3i test_array_;
void init(int x, int y, int z) {
array3i test_array_(extents[x][y][z]);
cout << "Size should be: " << test_array_.size() << endl;
for (int j=0; j<x; j++) {
for (int jj=0; jj<y; jj++) {
for (int jjj=0; jjj<z; jjj++) {
test_array_[j][jj][jjj] = j+jj+jjj;
}
}
}
};
public:
array3i test_array() {return test_array_;};
Test(int x, int y, int z) {
init(x, y, z);
};
};
int main(int argc, const char * argv[]) {
Test test(2,3,5);
cout << "Size from getter: " << test.test_array().size() << endl;
return 0;
}
The getter is working but you didn't initialize the member.
array3i test_array_(extents[x][y][z]);
initializes a local variable (that stops to exist after init() exits).
The problematic part was (likely) that you can't just assign a multi_array of different size/shape. So you need to use resize() (or initialize test_array_ shape in the constructor initializer list).
Live On Coliru
Fixed:
#include <iostream>
#include "boost/multi_array.hpp"
using namespace std;
using namespace boost;
typedef multi_array<int, 3> array3i;
class Test {
private:
array3i test_array_;
void init(int const x, int const y, int const z)
{
test_array_.resize(extents[x][y][z]);
cout << "Size should be: " << test_array_.size() << endl;
for (int j = 0; j < x; j++) {
for (int jj = 0; jj < y; jj++) {
for (int jjj = 0; jjj < z; jjj++) {
test_array_[j][jj][jjj] = j + jj + jjj;
}
}
}
};
public:
array3i test_array() { return test_array_; };
Test(int x, int y, int z) { init(x, y, z); };
};
int main()
{
Test test(2, 3, 5);
cout << "Size from getter: " << test.test_array().size() << endl;
}
The problem is probably that you have two test_array_ variables: One in the class as a class member, one local in the init function.
The local variables shadows, and overrides, the member variable.
In your init function you should be having:
void init(int const x, int const y, int const z)
{
//test_array_.resize(extents[x][y][z]);
test_array_ = array3i(extents[x][y][x]);
cout << "Size should be: " << test_array_.size() << endl;
for (int j = 0; j < x; j++) {
for (int jj = 0; jj < y; jj++) {
for (int jjj = 0; jjj < z; jjj++) {
test_array_[j][jj][jjj] = j + jj + jjj;
}
}
}
}
I am trying to take in an input for the dimensions of a 2D matrix. And then use user input to fill in this matrix. The way I tried doing this is via vectors (vectors of vectors). But I have encountered some errors whenever I try to read in data and append it to the matrix.
//cin>>CC; cin>>RR; already done
vector<vector<int> > matrix;
for(int i = 0; i<RR; i++)
{
for(int j = 0; j<CC; j++)
{
cout<<"Enter the number for Matrix 1";
cin>>matrix[i][j];
}
}
Whenever I try to do this, it gives me a subscript out of range error. Any advice?
You have to initialize the vector of vectors to the appropriate size before accessing any elements. You can do it like this:
// assumes using std::vector for brevity
vector<vector<int>> matrix(RR, vector<int>(CC));
This creates a vector of RR size CC vectors, filled with 0.
As it is, both dimensions of your vector are 0.
Instead, initialize the vector as this:
vector<vector<int> > matrix(RR);
for ( int i = 0 ; i < RR ; i++ )
matrix[i].resize(CC);
This will give you a matrix of dimensions RR * CC with all elements set to 0.
I'm not familiar with c++, but a quick look at the documentation suggests that this should work:
//cin>>CC; cin>>RR; already done
vector<vector<int> > matrix;
for(int i = 0; i<RR; i++)
{
vector<int> myvector;
for(int j = 0; j<CC; j++)
{
int tempVal = 0;
cout<<"Enter the number for Matrix 1";
cin>>tempVal;
myvector.push_back(tempVal);
}
matrix.push_back(myvector);
}
Assume we have the following class:
#include <vector>
class Matrix {
private:
std::vector<std::vector<int>> data;
};
First of all I would like suggest you to implement a default constructor:
#include <vector>
class Matrix {
public:
Matrix(): data({}) {}
private:
std::vector<std::vector<int>> data;
};
At this time we can create Matrix instance as follows:
Matrix one;
The next strategic step is to implement a Reset method, which takes two integer parameters that specify the new number of rows and columns of the matrix, respectively:
#include <vector>
class Matrix {
public:
Matrix(): data({}) {}
Matrix(const int &rows, const int &cols) {
Reset(rows, cols);
}
void Reset(const int &rows, const int &cols) {
if (rows == 0 || cols == 0) {
data.assign(0, std::vector<int>(0));
} else {
data.assign(rows, std::vector<int>(cols));
}
}
private:
std::vector<std::vector<int>> data;
};
At this time the Reset method changes the dimensions of the 2D-matrix to the given ones and resets all its elements. Let me show you a bit later why we may need this.
Well, we can create and initialize our matrix:
Matrix two(3, 5);
Lets add info methods for our matrix:
#include <vector>
class Matrix {
public:
Matrix(): data({}) {}
Matrix(const int &rows, const int &cols) {
Reset(rows, cols);
}
void Reset(const int &rows, const int &cols) {
data.resize(rows);
for (int i = 0; i < rows; ++i) {
data.at(i).resize(cols);
}
}
int GetNumRows() const {
return data.size();
}
int GetNumColumns() const {
if (GetNumRows() > 0) {
return data[0].size();
}
return 0;
}
private:
std::vector<std::vector<int>> data;
};
At this time we can get some trivial matrix debug info:
#include <iostream>
void MatrixInfo(const Matrix& m) {
std::cout << "{ \"rows\": " << m.GetNumRows()
<< ", \"cols\": " << m.GetNumColumns() << " }" << std::endl;
}
int main() {
Matrix three(3, 4);
MatrixInfo(three);
}
The second class method we need at this time is At. A sort of getter for our private data:
#include <vector>
class Matrix {
public:
Matrix(): data({}) {}
Matrix(const int &rows, const int &cols) {
Reset(rows, cols);
}
void Reset(const int &rows, const int &cols) {
data.resize(rows);
for (int i = 0; i < rows; ++i) {
data.at(i).resize(cols);
}
}
int At(const int &row, const int &col) const {
return data.at(row).at(col);
}
int& At(const int &row, const int &col) {
return data.at(row).at(col);
}
int GetNumRows() const {
return data.size();
}
int GetNumColumns() const {
if (GetNumRows() > 0) {
return data[0].size();
}
return 0;
}
private:
std::vector<std::vector<int>> data;
};
The constant At method takes the row number and column number and returns the value in the corresponding matrix cell:
#include <iostream>
int main() {
Matrix three(3, 4);
std::cout << three.At(1, 2); // 0 at this time
}
The second, non-constant At method with the same parameters returns a reference to the value in the corresponding matrix cell:
#include <iostream>
int main() {
Matrix three(3, 4);
three.At(1, 2) = 8;
std::cout << three.At(1, 2); // 8
}
Finally lets implement >> operator:
#include <iostream>
std::istream& operator>>(std::istream& stream, Matrix &matrix) {
int row = 0, col = 0;
stream >> row >> col;
matrix.Reset(row, col);
for (int r = 0; r < row; ++r) {
for (int c = 0; c < col; ++c) {
stream >> matrix.At(r, c);
}
}
return stream;
}
And test it:
#include <iostream>
int main() {
Matrix four; // An empty matrix
MatrixInfo(four);
// Example output:
//
// { "rows": 0, "cols": 0 }
std::cin >> four;
// Example input
//
// 2 3
// 4 -1 10
// 8 7 13
MatrixInfo(four);
// Example output:
//
// { "rows": 2, "cols": 3 }
}
Feel free to add out of range check. I hope this example helps you :)
try this. m = row, n = col
vector<vector<int>> matrix(m, vector<int>(n));
for(i = 0;i < m; i++)
{
for(j = 0; j < n; j++)
{
cin >> matrix[i][j];
}
cout << endl;
}
cout << "::matrix::" << endl;
for(i = 0; i < m; i++)
{
for(j = 0; j < n; j++)
{
cout << matrix[i][j] << " ";
}
cout << endl;
}
Vector needs to be initialized before using it as cin>>v[i][j]. Even if it was 1D vector, it still needs an initialization, see this link
After initialization there will be no errors, see this link
What you have initialized is a vector of vectors, so you definitely have to include a vector to be inserted("Pushed" in the terminology of vectors) in the original vector you have named matrix in your example.
One more thing, you cannot directly insert values in the vector using the operator "cin". Use a variable which takes input and then insert the same in the vector.
Please try this out :
int num;
for(int i=0; i<RR; i++){
vector<int>inter_mat; //Intermediate matrix to help insert(push) contents of whole row at a time
for(int j=0; j<CC; j++){
cin>>num; //Extra variable in helping push our number to vector
vin.push_back(num); //Inserting numbers in a row, one by one
}
v.push_back(vin); //Inserting the whole row at once to original 2D matrix
}
I did this class for that purpose. it produces a variable size matrix ( expandable) when more items are added
'''
#pragma once
#include<vector>
#include<iostream>
#include<iomanip>
using namespace std;
template <class T>class Matrix
{
public:
Matrix() = default;
bool AddItem(unsigned r, unsigned c, T value)
{
if (r >= Rows_count)
{
Rows.resize(r + 1);
Rows_count = r + 1;
}
else
{
Rows.resize(Rows_count);
}
if (c >= Columns_Count )
{
for (std::vector<T>& row : Rows)
{
row.resize(c + 1);
}
Columns_Count = c + 1;
}
else
{
for (std::vector<T>& row : Rows)
{
row.resize(Columns_Count);
}
}
if (r < Rows.size())
if (c < static_cast<std::vector<T>>(Rows.at(r)).size())
{
(Rows.at(r)).at(c) = value;
}
else
{
cout << Rows.at(r).size() << " greater than " << c << endl;
}
else
cout << "ERROR" << endl;
return true;
}
void Show()
{
std::cout << "*****************"<<std::endl;
for (std::vector<T> r : Rows)
{
for (auto& c : r)
std::cout << " " <<setw(5)<< c;
std::cout << std::endl;
}
std::cout << "*****************" << std::endl;
}
void Show(size_t n)
{
std::cout << "*****************" << std::endl;
for (std::vector<T> r : Rows)
{
for (auto& c : r)
std::cout << " " << setw(n) << c;
std::cout << std::endl;
}
std::cout << "*****************" << std::endl;
}
// ~Matrix();
public:
std::vector<std::vector<T>> Rows;
unsigned Rows_count;
unsigned Columns_Count;
};
'''
I am compiling a program with gcc and when I run a.out I get this error:
Segmentation fault: 11
I think it has to do with Board::display, but I don't see anything wrong with it..
#include <iostream>
using namespace std;
const bool WHITE = 0;
const bool BLACK = 1;
//-----------------------------
class Piece
{
public:
// constructors
Piece();
Piece(bool color);
// functions
char getColor() const {return color; }
bool getSymbol() const {return symbol;}
protected:
bool color;
char symbol;
};
ostream& operator << (ostream& out, const Piece & piece)
{
out << piece.getSymbol();
return out;
}
Piece::Piece() { }
Piece::Piece(bool color)
{
this->color = color;
}
//-----------------------------
class King : public Piece
{
public:
King(bool color);
};
King::King(bool color) : Piece(color)
{
this->symbol = 'K';
}
//-----------------------------
class Tile
{
public:
// constructors/destructors
Tile();
Tile(Piece piece, int row, int col);
// functions
bool getColor() const {return color;}
void display();
private:
Piece piece;
int row, col;
bool color;
};
Tile::Tile() { }
Tile::Tile(Piece piece, int row, int col)
{
this->row = row;
this->col = col;
}
void Tile::display()
{
if (getColor() == BLACK)
{
if (piece.getColor() == BLACK)
cout << "\E[30;47m " << piece << " \E[0m";
else
cout << "\E[37;47m " << piece << " \E[0m";
}
else
{
if (piece.getColor() == BLACK)
cout << "\E[30;41m " << piece << " \E[0m";
else
cout << "\E[37;41m " << piece << " \E[0m";
}
}
//---------------------------
class Board
{
public:
// constructor
Board();
// functions
void display();
private:
Tile *tiles[8][8];
};
Board::Board()
{
for (int r = 0; r < 8; r++)
for(int c = 8; c < 8; c++)
tiles[r][c] = new Tile(King(BLACK), r, c);
}
void Board::display()
{
for (int r = 7; r >= 0; r--)
{
for(int c = 7; c >= 0; c--)
tiles[r][c]->display();
cout << endl;
}
}
//---------------------------
int main()
{
Board board;
board.display();
}
In Board::display(), r++ should be r--, and ditto for c++.
If (like me) you prefer unsigned variables for array indices, you would write the loop like this:
for (std::size_t i = 0; i != N; ++i)
{
array[N - 1 - i] = something();
}
Or, if you find that to cumbersome but you still really don't like <= and prefer iterator-style "not-equals" termination (like me), you can stick with unsigned types and say:
for (std::size_t i = N; i != 0; --i)
{
array[i - 1] = anotherthing();
}
Your next mistake is to store a polymorphic object by value of the base. That can't work! Instead, you might want to save a pointer (or reference). While we're at it, it's time for you to learn constructor initializer lists:
class Tile
{
Piece * piece; // must be a polymorphic handle!
int row;
int col;
public:
Tile(Piece * p, int r, int c) : piece(p), row(r), col(c) { }
Tile() : piece(NULL), row(0), col(0) { }
};
If you store a polymorphic object by value, you end up slicing it. You could have saved yourself the trouble by making Piece abstract.
As you can see, you should also make sure the default constructor does something useful. In fact, I would argue that the default constructor doesn't actually make sense, and that you should just remove it.
Finally, I should add that the Tile class design is a terrible problem, because you don't manage the lifetime of the Piece objects, which currently just leak. If you were to manage them, you'd need to delete the piece in the destructor of Tile, but then you'd need to implement the Rule of Three, and now you realise that Piece needs a virtual destructor...
I'm realising that this is turning into a full-blown chapter of "How to do C++", so I'll stop now. I think we have several good books on our recommended list; please consult those.
In Board::display, you are incrementing your variables in the loops instead of decrementing them.
You also aren't assigning piece to Tile::piece in Tiles constructor. (this->piece = piece)
Surely you mean:
for (int r = 7; r >= 0; r--)
{
for(int c = 7; c >= 0; c--)
to be
for (int r = 6; r > 0; r--)
{
for(int c = 6; c > 0; c--)
Unless it is just a typo the line:
for(int c = 8; c < 8; c++)
in the Board constructor is wrong and will result in none of tiles being allocated with the ultimate result of "bad" things happening when you try to use them.
Change it to:
for(int c = 0; c < 8; c++)
At some point you'll want to delete these although a better option might to be not use pointers at all in this case, just Tile tiles[8][8]; or a vector<vector<Tile> > tiles.