0

So the question given to me is to make a C++ program where the user inputs the size (declared by n) of a matrix N x N, and then there's a function for the user to fill the matrix called inputMatrix

#include <iostream>
using namespace std;

int n;

void inputMatrix(int matrix[][n]) // first error
{
    for (int i=0 ; i<n ; i++)
    {
        for(int j=0 ; j<n ; j++)
        {
            cout << "Matrix[" << i << "][" << j << "]: ";
            cin >> **(matrix + i + n * j);
        }
    }
}

int main()
{
    cout << "input n: ";
    cin >> n;

    int matrix[n][n];
    inputMatrix(matrix[n][n]); // second error
}

When I run, it gets an error

error: size of array 'matrix' is not an integral constant-expression

and

error: invalid conversion from 'int' to 'int (*)[1]' [-fpermissive]

10
  • 2
    Your code is invalid C++, see Why aren't variable-length arrays part of the C++ standard? Commented 9 hours ago
  • 1
    It is statically unknown what the array size is. The array can be allocated dynamically using new: https://stackoverflow.com/questions/35532427/how-to-dynamically-allocate-arrays-in-c. Commented 9 hours ago
  • 2
    Incidentally, even ignoring the use of a VLA (which is invalid in standard C++) inputMatrix(matrix[n][n]) tries to pass a single but non-existent element of matrix to inputMatrix(). Simply evaluating matrix[n][n] gives undefined behaviour. And (probable reason for at least one compilation error) its type is not the type that inputMatrix() expects. Commented 9 hours ago
  • 2
    Make a matrix class! And pass it by (const) reference. The matrix class internally should manage its memory e.g. by using std::vector + index calculations by you (to keep all memory contiguous). Commented 8 hours ago
  • 2
    Side note : stop using "using namespace std;" Commented 8 hours ago

2 Answers 2

3

You can use mdspan multidimensional array view since C++23. The standard conforming code:

#include <iostream>
#include <mdspan>
#include <vector>

void inputMatrix(const auto& matrix) {
  for (std::size_t i = 0; i < matrix.extent(0); i++) {
    for (std::size_t j = 0; j < matrix.extent(1); j++) {
      std::cout << "Matrix[" << i << "][" << j << "]: ";
      std::cin >> matrix[i, j];
    }
  }
}

int main() {
  std::size_t n = 0;
  std::cout << "input n: ";
  std::cin >> n;

  std::vector<int> storage(n * n);
  std::mdspan matrix(storage.data(), n, n);
  inputMatrix(matrix);
}
Sign up to request clarification or add additional context in comments.

8 Comments

VLA (int matrix[n][n];) is still invalid in C++23.
**(matrix + i + n * j): i thought i would fill the array with the user input
No don't do that... a matrix isn't a 2D array of values. Use a Matrix class instead.
This is UB even without VLA, &matrix[0][0] can only be used to access the first subarray.
[deleted]
[deleted]
*(&matrix[0][0]+n) is UB even if &matrix[0][0]+n happens to coincide with the address given by &matrix[1][0]. This is a comment w.r.t your first code block.
Not sure what you mean by sequenced.
Сontinuous subarrays.
|
2

You shouldn't use arrays at all but a matrix class. It is very easy to make one and will avoid all kind of lifecycle and other issues. This is after all C++ not C, and as an added benefit you will use the type system. making sure you are not passing random arrays as matrices (or the other way around) when calling functions


#include <vector>
#include <iostream>
#include <stdexcept>

class Matrix
{

public:
    Matrix(std::size_t rows, std::size_t cols)
        : m_data(rows * cols, 0), m_rows(rows), m_cols(cols)
    {
    }

    Matrix(std::initializer_list<std::initializer_list<int>> init)
    {
        m_rows = init.size();
        m_cols = m_rows ? init.begin()->size() : 0;
        m_data.reserve(m_rows * m_cols);
        for (const auto& row : init) {
            if (row.size() != m_cols) {
                throw std::invalid_argument("All rows must have the same number of columns");
            }
            m_data.insert(m_data.end(), row.begin(), row.end());
        }
    }

    int& at(std::size_t row, std::size_t col)
    {
        if (row >= m_rows || col >= m_cols) {
            throw std::out_of_range("Matrix::at: index out of bounds");
        }
        return m_data.at(row * m_cols + col);
    }

    const int& at(std::size_t row, std::size_t col) const
    {
        if (row >= m_rows || col >= m_cols) {
            throw std::out_of_range("Matrix::at: index out of bounds");
        }
        return m_data.at(row * m_cols + col);
    }

    std::size_t rows() const { return m_rows; }
    std::size_t cols() const { return m_cols; }
private:

    std::vector<int> m_data;
    std::size_t m_rows;
    std::size_t m_cols;
};

// And this is how you pass a Matrix to a function that prints it
std::ostream& operator<<(std::ostream& os, const Matrix& mat) {
    for (std::size_t i = 0; i < mat.rows(); ++i) {
        for (std::size_t j = 0; j < mat.cols(); ++j) {
            os << mat.at(i, j) << ' ';
        }
        os << '\n';
    }
    return os;
}

int main()
{
    Matrix matrix{ {1, 2}, {3, 4} };
    std::cout << matrix;

    return 0;
}

https://onlinegdb.com/jERaNCQ-zX

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.