I want to create a transpose function for dynamic 2d arrays. I want the functions to have as parameters the 2d array and the rows and columns. I ve decided to use double pointer. However i m a bit confused about how i gonna call the function from main. So i ve got the above code
#include<iostream>
using namespace std;
void transposeMatrix(double **mat, int rows, int columns)
{
mat = new double*[rows];
for (int i = 0; i < rows; ++i)
{
mat[i] = new double[columns];
}
double temp;
for (int i = 0; i<rows; i++)
{
for (int j = i+1; j<columns; j++)
{
temp=mat[i][j];
mat[i][j]=mat[j][i];
mat[j][i]=temp;
}
}
cout<< "\n";
for (int i = 0; i<rows; i++)
{
for (int j = 0; j<columns; j++)
{
cout << mat[i][j] << " \t";
}
cout << "\n";
}
}
int main()
{
int rows = 10;
int columns = 10;
double mat[rows][columns];
for (int i = 0; i<rows; i++)
{
for (int j = 0; j<columns; j++)
{
mat[i][j] = j;
}
}
for (int i = 0; i<rows; i++)
{
for (int j = 0; j<columns; j++)
{
cout << mat[i][j] << " \t";
}
cout << "\n";
}
//mat = new double[50][1];
transposeMatrix(mat, 10, 10);
system("pause");
return 0;
}
Any idea?
You're very close. You're calling the function correctly and the function's parameter list is correct. First, remove this section from the transpose function:
mat = new double*[rows];
for (int i = 0; i < rows; ++i)
mat[i] = new double[columns];
}
Now make sure all your brackets match up. (There was one missing.)
You can't define a static array (one that looks like this: x[y][z]) with non-constant variables as the size arguments. (I.e. y and z must be constants.) But actually, you're passing a dynamic array to the transpose function anyway, and rows and columns don't have to be constants to do that. So, in main, define a dynamic array like this:
double** mat = new double*[rows];
for (int i = 0; i < rows; i++)
mat[i] = new double[columns];
After that, your code should work. But you could also make it better by putting your matrix display code in a function. Then, instead of cutting and pasting it everywhere, all you have to do is call the function! It's an important habit to get into. Have fun!
There are a couple of major issues with your code.
The biggest one is that a double[10][10] is not convertible to a double** pointer.
You also have a memory leak (mat) in your transposeMatrix() implementation.
I recommend that you separate the concerns of printing a matrix and transposing a matrix. Perhaps a separate methods on a (templated) matrix class.
And now, having said that...
Why write one when a perfectly good implementation already exists?
Example:
#include <boost/numeric/ublas/matrix.hpp>
#include <boost/numeric/ublas/io.hpp>
int main ()
{
using namespace boost::numeric::ublas;
matrix<double> m(3, 3);
for (unsigned i = 0; i < m.size1(); ++i)
{
for (unsigned j = 0; j < m.size2(); ++j)
{
m(i, j) = 3 * i + j;
}
}
std::cout << m << std::endl;
std::cout << trans(m) << std::endl;
}
Output:
[3,3]((0,1,2),(3,4,5),(6,7,8))
[3,3]((0,3,6),(1,4,7),(2,5,8))
double ** transpose(double **matrix, int rows, int columns){
double ** trans;
trans=new double *[columns];
for(int i=0;i<columns;i++){
trans[i]=new double[rows];
for(int j=0;j<rows;j++)
trans[i][j]=matrix[j][i];
}
return trans;
for(int i=0;i<columns;i++)
delete[] trans[i];
delete[] trans;
}
Here is the code for transpose of the matrix.
Related
I am trying to copy a matrix from an old matrix class to an armadillo matrix. Unfortunately when attempting to do this with a for loop the armadillo matrix will copy the value from the old matrix to the ENTIRE column when the lowest-most element is non-zero (I am using sparse matrices). I have attached the code that is being used below. This is very simplified because I need to figure out why it is doing this first. According to the documentation this should work.
main()
{
OldMatrixClass MatrixA(size, size);
FillMatrix(MatrixA, size);
for (auto i = 0; i < size; i++)
{
for (auto j = 0; j < size; j++)
{
file << MatrixA[i][j] << "\t";
}
file << "\n";
}
arma::Mat<double> ArmaA(size, size);
ArmaA.zeros();
CopyMatrix(MatrixA, ArmaA, size);
for (int i = 0; i < size; i++)
{
for (int j = 0; j < size; j++)
{
file << ArmaA[i,j] << "\t";
}
file << "\n";
}
}
void FillMatrix(OldMatrixClass &A, int size)
{
double num = 0.15;
for (int i = 0; i < size; i++)
{
for (int j = 0; j < size; j++)
{
if (rand() % 101 < 26)
{
A[i][j] = num;
}
else
{
A[i][j] = 0;
}
}
}
}
void CopyMatrix(OldMatrixClass A, arma::Mat<double> &B, int size)
{
for (int k = 0; k < size; k++)
{
for (int j = 0; j < size; j++)
{
B[j, k] = A[j][k];
}
}
}
This is the output when I run this code... As you can see only the entire columns are altered if the last element in MatrixA column is non-zero.
Output
Is there something I'm doing wrong? Is my syntax messed up somewhere?
See the documentation:
Caveat: accessing elements via [i,j] and [i,j,k] does not work correctly in C++; instead use (i,j) and (i,j,k)
The task is as follows: Describe the class "matrix of numbers" with component data: the dimensions of the matrix, a pointer to the elements. Overload operations: << (matrix output to the screen), + (addition of matrices), unary ¬– (change the sign of each element), / = (divide each element by a number). I performed it, and performed it correctly, but you need to set the matrix dimension from the keyboard, and as you can see, it is set in advance for me [3] [3]. It sounds pretty simple, but something I'm really dumb. Thanks in advance for your help. Here is the code:
#include "pch.h"
#include <iostream>
using namespace std;
class Matrix
{
public:
Matrix()
{
int Table[3][3];
}
int Table[3][3];
void Create()
{
for (int i = 0; i < 3; i++)
for (int j = 0; j < 3; j++)
Table[i][j] = 10;
}
};
ostream& operator <<(ostream& t, Matrix a)
{
for (int i = 0; i < 3; i++)
{
for (int j = 0; j < 3; j++)
t << a.Table[i][j] << " ";
t << "\n";
}
return t;
}
Matrix& operator /=(Matrix& a, int num)
{
for (int i = 0; i < 3; i++)
for (int j = 0; j < 3; j++)
a.Table[i][j] /= num;
return a;
}
Matrix& operator -(Matrix& a, int empty)
{
for (int i = 0; i < 3; i++)
for (int j = 0; j < 3; j++)
a.Table[i][j] = -a.Table[i][j];
return a;
}
Matrix& operator +(Matrix& a, Matrix b)
{
for (int i = 0; i < 3; i++)
for (int j = 0; j < 3; j++)
a.Table[i][j] += b.Table[i][j];
return a;
}
int main()
{
int u;
setlocale(LC_ALL, "Russian");
Matrix Example;
Example.Create();
Matrix Example1;
Example1.Create();
cout << Example;
cout << Example1;
cout << "Сумма матриц: "<<endl;
cout << Example + Example1;
Example - 1;
Example1 - 1;
cout<< Example + Example1;
cout << "На сколько вы хотите её поделить?\n";
cin >> u;
Example /= u;
Example1 /= u;
cout << Example;
cout << Example1;
}`
You need to dynamically create the matrix.
In order to this you need to use pointers(*). Change int table[3][3]
double table**;
An example of how it could be implemented (note that I use matrix instead of table)
class Matrix {
private:
double** matrix;
int col;
int row;
public:
Matrix(){};
void Create(int row, int col);
};
void Matrix::Create(int row_, int col_){
double val = 0.0;
col = col_; // initalize private members
row = row_;
matrix = new double*[row]; // Create a new array of size row_
for(int i = 0; i < row; i++)
{
matrix[i] = new double[col]; // Create new cols of size col (inside array of row)
}
for(int i = 0; i < row; i++)
{
for(int j = 0; j < col; j++)
{
matrix[i][j] = val;
val = val + 1.0;
}
}
}
I tried to reuse your design for simplicity, but I really suggest that you try to specify the dimensions of the matrix in a constructor instead and maybe even construct the matrix in it as well.
Something like this:
Matrix(int row_, int col_) : row(row_), col(col_) {*/ create matrix here /*};
You can skip the "create matrix here" part and use your own Create() if you want to.
You need dynamic memory allocation for that. I won't fiddle around with pointers (new / delete) unless you are explicitly told to. As a beginner you should probably use the standard template library (STL) tools:
#include <vector> and use std::vector<std::vector<int>> Table instead of int Table[3][3]. Then write a constructor like this:
Matrix(std::size_t rows, std::size_t cols)
{
Table.resize(rows);
for (unsigned int i = 0; i < Table.size(); ++i)
Table[i].resize(cols);
}
You can additionally store the dimension of the matrix, but there is no need to do it since you can get the information from the vectors. Replace the hardcoded dimensions in all loops by the corresponding dynamic sizes (stored or extracted from the vectors). For example:
Matrix& operator +(Matrix& a, Matrix b)
{
unsigned int rows = a.Table.size();
unsigned int cols = a.Table[0].size();
for (unsigned int i = 0; i < rows; i++)
for (unsigned int j = 0; j < cols; j++)
a.Table[i][j] += b.Table[i][j];
return a;
}
However, this vector of vectors is not really effective. Better would be a single vector but I guess for a beginner it is okay.
Greetings
I am completely new in C++ and I have to solve a task for college, where I have to make a struct Matrix and fill it with random integers. I marked the line with a "!" where the error appears.
It is the error C2131(Visual C++ Compiler). It says "expression did not evaluate to a constant".
struct Matrix{
int rows;
int columns;
Matrix(int r, int c){
rows = r, columns = c;
}
int produceMatrix(){
int matrix[rows][columns]; "!"
for(int i = 0; i != rows; i++){
for(int j = 0; j != columns; j++){
matrix[i][j] = rand() %10 +1;
}
}
return 0;
}
int showMatrix(){
for(int i = 0; i != rows; i++){
for(int j = 0; j != columns; j++){
cout << matrix[i][j]<< endl;
}
}
}
};
int main()
{
srand(time(0));
Matrix a(3, 4);
}
If you are planning to create your matrix with rows and columns values only known at runtime, you are better off using std::vector<std::vector<int>> to hold your data, as the static array you use needs to know its size at compile time. But if all your sizes are known at compile time and you just want flexibility of creating different matrix sizes, you can use template, for example:
#include <iostream>
#include <ctime>
template <int ROWS, int COLUMNS>
struct Matrix
{
int rows = ROWS;
int columns = COLUMNS;
int matrix[ROWS][COLUMNS] = {};
void produceMatrix()
{
for (int i = 0; i < rows; i++)
{
for (int j = 0; j < columns; j++)
{
matrix[i][j] = rand() % 10 + 1;
}
}
}
void showMatrix()
{
for (int i = 0; i < rows; i++)
{
for (int j = 0; j < columns; j++)
{
std::cout << matrix[i][j] << "\t";
}
std::cout << std::endl;
}
}
};
int main()
{
srand(time(0));
Matrix<3,4> a;
a.produceMatrix();
a.showMatrix();
}
https://ideone.com/rCLxSn
4 10 5 5
3 8 3 6
2 4 9 10
One thing is that you cannot make variable-length arrays this way.
Another thing is that if you create a variable within a function (like you were doing here with int matrix in produceMatrix()), it is then not visible in another function.
Therefore, the array containing the elements of the matrix should be declared in your struct there, where you have declared rows and columns.
To store the elements of your matrix, you can use one-dimensional array of length equal to rows*columns.
Now, you need some kind of dynamic array to be able to make it of the length not known in the compilation time.
One solution is to use a pointer and define an array with new operator in the constructor. However, if you use new, then you have to use delete at some point to deallocate memory, which here means that the destructor is needed. Another problem would be with copying of your matrices.
Another, simpler solution is to use std::vector, a container provided by c++ standard library. Here's how to do it with std::vector (you need to add #include<vector> to your file):
struct Matrix{
int rows;
int columns;
vector<int> matrix;
Matrix(int r, int c){
rows = r, columns = c;
matrix = vector<int>(c*r);
}
int produceMatrix(){
for(int i = 0; i < matrix.size(); i++){
matrix[i] = rand() %10 +1;
}
return 0;
}
int showMatrix(){
for(int i = 1; i <= matrix.size(); i++){
cout << matrix[i-1];
if(i%columns == 0) cout << endl;
else cout << " ";
}
return 0;
}
};
As many people commented, please go through a good C++ book to learn about arrays, classes, structs etc. As for your code, the following might produce what I think you want:
#include <iostream>
#include <vector>
struct Matrix
{
int rows;
int columns;
std::vector<std::vector<int>> matrix;
Matrix(int r, int c): rows(r), columns(c)
{
matrix.resize(r);
for(int i = 0; i < r; i++)
matrix[i].resize(c);
}
int produceMatrix()
{
for(int i = 0; i != rows; i++)
for(int j = 0; j != columns; j++)
matrix[i][j] = rand() %10 +1;
return 0;
}
int showMatrix()
{
for(int i = 0; i != rows; i++)
{
for(int j = 0; j != columns; j++)
std::cout << matrix[i][j]<<" ";
}
std::cout<<'\n';
}
};
int main()
{
srand(time(0));
Matrix a(3, 4);
a.produceMatrix();
a.showMatrix();
}
I am trying to create MxN matrix using 2D-arrays in C++.
The createMatrix() function asks for user input for matrix items and the printMatrix() function has to print the matrix.
But the printing task is not working (I can't access the array created, I don't understand why)
I receive the error :
matrix.cpp:35:20: error: invalid types ‘int[int]’ for array subscript
cout << matrix[i][j];
The code I'm working with is:
#include "iostream"
using namespace std;
// user input matrix
int createMatrix(int m, int n){
int arr[m][n];
for(int i = 0; i < m; i++){
for(int j = 0; j < n; j++){
cout << "A[" << i << "][" << j << "] : ";
cin >> arr[i][j];
}
cout << endl;
}
return arr[m][n];
}
/*
void printMatrix(int matrix[][2], int m, int n){
for(int i = 0; i < m; i++){
for(int j = 0; j < n; j++){
cout << matrix[i][j];
}
}
}
*/
int main(){
int m = 2, n = 2; // m = rows, n = columns
int matrix = createMatrix(m,n);
// printMatrix(matrix, m, n); // not working as sub-routine too, main target to make it work with sub-routine
// to print matrix
for(int i = 0; i < m; i++){
for(int j = 0; j < n; j++){
cout << matrix[i][j];
}
}
return 0;
}
matrix is an int not an int[][]. Since it is an int there is no subscript operator and that is why you are getting the error you are getting. You are also using veriable length arrays which is not standard C++. I would suggest you change your code to use a std::vector like
std::vector<std::vector<int>> createMatrix(int m, int n)
{
std::vector<std::vector<int>> arr(m, std::vector<int>(n));
for(int i = 0; i < m; i++){
for(int j = 0; j < n; j++){
cout << "A[" << i << "][" << j << "] : ";
cin >> arr[i][j];
}
cout << endl;
}
return arr;
}
And then main() would be:
int main(){
int m = 2, n = 2; // m = rows, n = columns
std::vector<std::vector<int>> matrix = createMatrix(m,n);
// printMatrix(matrix, m, n); // not working as sub-routine too, main target to make it work with sub-routine
// to print matrix
for(int i = 0; i < m; i++){
for(int j = 0; j < n; j++){
cout << matrix[i][j];
}
}
return 0;
}
Your matrix is not array. it is int.
You need to work with the pointers.
Yes, createMatrix works but you won't be able to do anything with what it created. Because:
arr[n][m] is local (and out of boundaries by the way). It is not a matrix as you probably thought but an item of arr at position [n][m].
It is not well defined to declare array of fixed sizes with vary sizes that depend on function input.
You need to pass to createMatrix array from the main() as pointer (like you did in printMatrix) and createMatrix should work with it and not something local.
Now regarding your original question:
But the printing task is not working (I can't access the array
created, I don't understand why)
matrix was defined as int, not as array.
int matrix = createMatrix(m,n);
I have this function meant to initialize a multidimensional 2d (6x6) array to zero. I call the function in main using cout to test it and it outputs garbage. Please help. Thanks!
int** initializeArray(void)
{
typedef int* rollArray; //this line is actually outside of the function in my
//program
int i, j;
rollArray *m = new rollArray[6];
for (i = 0; i < 6; i++)
m[i] = new int[6];
for (i = 0; i < 6; i++)
for (j = 0; j < 6; j++)
m[i][j] = 0;
return m;
}
If the value 6 is known at compile-time, I would suggest using std::array in a nested fashion. For example:
#include <array>
#include <iostream>
int main()
{
std::array<std::array<int,6>,6> a = {0};
for (int i = 0; i < 6; ++i)
{
for (int j = 0; j < 6; ++j)
{
std::cout << a[i][j] << std::endl; // Prints 0.
}
}
return 0;
}
In fact, you won't even need to create a function to initialize your array. Declare your nested array and you are good to go. (If you don't know the dimension at compile-time, you could use std::vector in a similar fashion.)
The problem is with your test.
How can you mess up such a simple test? Just use:
int ** a = initializeArray();
int i,j;
for (i = 0; i < 6; i++) {
for (j = 0; j < 6; j++) {
cout << a[i][j] << " ";
}
cout << endl;
}