Can someone explain me, why my code is not working? - c++

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();
}

Related

Arbitrary matrix dimension in matrix class

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

How to initialize a matrix in a function and return it efficiently in C++?

My task is to generate a square matrix of zeros in a function and return it. There are plenty ways to do this, but I decided not to go with returning the matrix by value for efficiency. I went for a pointer approach like in this answer, but since it requires manual cleaning memory (and also as far as I know it's better to use smart pointers), I decided to turn it into std::unique_ptr, but I can't get it to work. This is my code:
#include <iostream>
#include <memory>
std::unique_ptr<std::unique_ptr<int>[] > GenerateMatrix(const int &n) {
std::unique_ptr<std::unique_ptr<int>[] > matrix(new std::unique_ptr<int>[n]);
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
matrix[i].get()[j] = 0;
}
}
return matrix;
}
int main() {
int n = 4;
auto matrix = GenerateMatrix(n);
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
std::cout<<matrix[j].get()[i]<<" ";
}
std::cout<<std::endl;
}
return 0;
}
What do I do wrong here? Is this approach even correct?
Why not just make your life easier by
vector<vector<int>> generate (int m, int n)
{
return vector<vector<int>>(m ,vector<int>(n));
}
int main()
{
int m = 3, n = 4;
auto matrix = generate(m, n); // a 3-by-4 matrix of zeros
return 0;
}
Just rely on guarenteed copy elision or return value optimization:
std::vector<int> GenerateMatrix(const int &n) {
return std::vector<int>(n*n, 0);//, 0 can be omitted (as elements will then be zero-initialized)
}
You might create and initialize a matrix at compile time. For example:
template<int RowCount, int ColumnCount, int DefaultValue = 0>
struct Matrix
{
static_assert(RowCount >= 0 && ColumnCount >=0,
"The number of rows and columns should be positive");
struct Row
{
int column[ColumnCount] = { DefaultValue };
};
Row row[RowCount];
};
And use it like:
Matrix<2, 2, 33> matrix;
auto val = matrix.row[0].column[0]; // val == 33
matrix.row[0].column[0] = 55;
val = matrix.row[0].column[0]; // val == 55
Beware the matrix dimensions, when refer to its elements by row and column.
You are not allocating enough memory for your matrix. Change this line:
std::unique_ptr<std::unique_ptr<int>[] > matrix(new std::unique_ptr<int>[n*n]);
Also, I would just use i*n + j for your accesses since you are really dealing with a 1D array:
#include <iostream>
#include <memory>
std::unique_ptr<std::unique_ptr<int>[] > GenerateMatrix(const int &n) {
std::unique_ptr<std::unique_ptr<int>[] > matrix(new std::unique_ptr<int>[n*n]);
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
matrix.get()[i*n+j] = 0;
}
}
return matrix;
}
int main() {
int n = 4;
auto matrix = GenerateMatrix(n);
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
std::cout<<matrix.get()[i*n+j]<<" ";
}
std::cout<<std::endl;
}
return 0;
}

Replacing values in a 2D array

I have to create a program that allows a user to fill in a (partial) Latin Square of order 4. You can use 0's to represent empty cells. The user will give the number to place, the row and column. The number should only be placed if it does not violate the properties of a partial Latin square and it shouldn't rewrite numbers that have already been placed.
I have an matrix that is outputting all zeroes now. So next I have to replace each of these values by what the user is inputting. The problem is I don't know how to do this.
Here is my code:
#include <iostream>
using namespace std;
const int ORDER = 4;
void fill (int m[], int order);
void outputMatrix (int m[], int order);
void replaceValue (int m[], int order, int n, int row, int column);
int main(){
int matrix[ORDER];
int row;
int column;
int n;
fill (matrix, ORDER);
outputMatrix (matrix, ORDER);
do {
cout << "Enter the number to place, the row and the column, each seperated by a space: ";
cin >> n;
cin >> row;
cin >> column;
}while (n > 0 || n <= ORDER);
if (n <= 0 || n >= ORDER){
cout << "Thank you";
cout << endl;
}
return 0;
}
void fill (int m[], int order){
for (int i = 0; i < order*order; i++){
m[i] = 0;
}
}
void outputMatrix (int m[], int order){
int c = 0;
for (int i = 0; i < order*order; i++){
c++;
cout << m[i] << ' ';
if (c == order){
cout << endl;
c = 0;
}
}
cout << endl;
}
void replaceValue (int m[], int order, int n, int row, int column){
for (int i = 0; i < order; i++){
m[order] = m[row][column];
m[row][column] = n;
}
}
How do I replace values in a Matrix in C++?
If you have a matrix, matrix[row][col] = value; would do the trick. However, I see that you allocate a single array. Make sure you look at this.
EDIT:
I looked closer at you code and you are doing some things wrong.
First:
matrix[ORDER]
will create a single array of ORDER values. If you want and ORDER by ORDER matrix try:
matrix[ORDER][ORDER]
Second:
You are calling:
void fill (int m[], int order){
for (int i = 0; i < order*order; i++){
m[i] = 0;
}
}
with an of size 4 and order == 4. This will loop outside the array and give you problems.
Try something like:
matrix[ORDER][ORDER];
for (int row = 0; row != ORDER; ++row)
{
for (int col = 0; col != ORDER; ++col)
{
matrix[row][col] = 0;
}
}
Hope this helps.
You can't really write arr[i][j] if arr is defined as arr[]. There's no information about the length of the row (how many columns there are).
You could use arrays of type arr[][4], and write your functions like so:
// The & is to pass by reference.
void print(int (&arr)[][4], int length)
{
for(int i = 0; i < length; i++) {
for(int j = 0; j < 4; j++) {
cout << arr[i][j] << " ";
}
cout << endl;
}
}
But in my opinion for a low-order multidimensional array like this one, using a typedef for a vector of vectors is the better option:
typedef vector<vector<int> > Matrix;
void print(Matrix& arr)
{
for(int i = 0; i < arr.size(); i++) {
for(int j = 0; j < arr[i].size(); j++) {
cout << arr[i][j] << " ";
}
cout << endl;
}
}
In either case, writing arr[i][j] = k will behave as you expect.
The easiest way to clear/zero your matrix is that:
memset( &matrix, 0, sizeof(matrix));
;-)

How to sort elements into C++ matrix?

I'm new to C++ programming. I need to sort this matrix:
#include <iostream>
#include <iomanip>
#include <cstdlib>
using namespace std;
int main(int argc, char** argv) {
Mat10 a;
fillRand(a, 5, 5);
prnMat(a, 5, 5);
cout << endl;
return 0;
}
void fillRand(Mat10 m, int n, int k) {
for (int i = 0; i < n; i++)
for (int j = 0; j < k; j++)
m[i][j] = rand() % 1000;
}
void prnMat(Mat10 a, int m, int n) {
for (int i = 0; i < m; i++) {
for (int j = 0; j < n; j++)
cout << setw(8) << a[i][j];
cout << endl;
}
}
I need to sort the matrix from the beginning from the beginning. The smallest value must be at the beginning of the of the first column. The next must be below it and so on. The result must be sorted matrix - the smallest number must be at the beginning of the left column - the biggest value must be at the end of the matrix. Would you please help to solve the problem?
EDIT
Maybe I found possible solution:
void sort(int pin[10][2], int n)
{
int y,d;
for(int i=0;i<n-1;i++)
{
for(int j=0; j<n-1-i; j++)
{
if(pin[j+1][1] < pin[j][1]) // swap the elements depending on the second row if the next value is smaller
{
y = pin[j][1];
pin[j][1] = pin[j+1][1];
pin[j+1][1] = y;
d = pin[j][0];
pin[j][0] = pin[j+1][0];
pin[j+1][0] = d;
}
else if(pin[j+1][1] == pin[j][1]) // else if the two elements are equal, sort them depending on the first row
{
if(pin[j+1][0] < pin[j][0])
{
y = pin[j][1];
pin[j][1] = pin[j+1][1];
pin[j+1][1] = y;
d = pin[j][0];
pin[j][0] = pin[j+1][0];
pin[j+1][0] = d;
}
}
}
}
}
But since I'm new to programming I don't understand is this the solution?
Here is a simple example for you:
#include <vector>
#include <algorithm>
using namespace std;
//This is the comparation function needed for sort()
bool compareFunction (int i,int j)
{
return (i<j);
}
int main()
{
//let's say you have this matrix
int matrix[10][10];
//filling it with random numbers.
for (int i = 0; i < 10; i++)
for (int j = 0; j < 10; j++)
matrix[i][j] = rand() % 1000;
//Now we get all the data from the matrix into a vector.
std::vector<int> vect;
for (int i = 0; i < 10; i++)
for (int j = 0; j < 10; j++)
vect.push_back(matrix[i][j]);
//and sort the vector using standart sort() function
std::sort( vect.begin(), vect.end(), compareFunction );
//Finally, we put the data back into the matrix
for (int i = 0; i < 10; i++)
for (int j = 0; j < 10; j++)
matrix[i][j] = vect.at(i*10 + j);
}
After this, the matrix will be sorted by rows:
1 2
3 4
If you want it to be sorted by cols:
1 3
2 4
You need to replace matrix[i][j] in the last cycle only with matrix[j][i]
If you need to read about the the sort() function, you can do it here
Hope this helps.
You can simply call std::sort on the array:
#include <algorithm> // for std::sort
int main() {
int mat[10][10];
// fill in the matrix
...
// sort it
std::sort(&mat[0][0], &mat[0][0]+10*10);
}

Transpose a 2d dynamic matrix

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.