0

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

}    
Mat
  • 202,337
  • 40
  • 393
  • 406
Josh.K
  • 3
  • 1
  • 3
  • Because C++ does not have variable-length arrays. `rows` and `columns` need to be compile time constants to work – UnholySheep May 26 '18 at 12:38
  • I am not that much familiar with C++ as well but I guess it is impossible to define functions inside of structs. You need to use "class" instead – mangusta May 26 '18 at 12:38
  • 6
    @mangusta that's completely wrong. `struct` and `class` are the same thing in C++ (except for default access and inheritance modifier) – UnholySheep May 26 '18 at 12:39
  • @UnholySheep yes, I re-checked the C++ specs, you are right – mangusta May 26 '18 at 12:40
  • @UnholySheep Does that mean that rows and columns need to be specific integers before I run my code ? – Josh.K May 26 '18 at 12:52
  • @Josh.K Take a look at this answer to get started: https://stackoverflow.com/a/2076668/3527268 – snow_abstraction May 26 '18 at 12:57
  • They need to be either specific integers, or you need to use `std::vector` instead of arrays. Open your C++ book to the chapter that explains to you how to use `std::vector`, and start reading. – Sam Varshavchik May 26 '18 at 12:59
  • 2
    Additionally, a vector/array declared in one class method has absolutely nothing to do with anything used in another class method. You are attempting to declare a local array/vector in one class method, and use it in another class method. C++ does not work this way. Your array/vector must be a class member. Instead of going back and forth to stackoverflow.com with every question, you should simply read your C++ book. stackoverflow.com is not a C++ tutorial, and is not a substitute for a [good C++ book](https://stackoverflow.com/questions/388242/the-definitive-c-book-guide-and-list). – Sam Varshavchik May 26 '18 at 13:00
  • @SamVarshavchik I know that this is not a tutorial. Currently I am reading the C++ Primer but nevertheless i could not find my mistake. – Josh.K May 26 '18 at 13:21

3 Answers3

2

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
Killzone Kid
  • 6,171
  • 3
  • 17
  • 37
1

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;
}
};
mks
  • 76
  • 4
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();
}
mahesh
  • 1,028
  • 10
  • 24
  • What is the purpose of "resize" ? – Josh.K May 26 '18 at 14:14
  • @Josh.K: resize sets the size of the vector to the value we want, also allocating memory. So later, we can simply refer to the element with the operator[]. – mahesh May 26 '18 at 17:36