1

I am relatively new to C++ programming and I wanted to learn more about language by programming matrices. I have this code that works, but I can't figure out how to create code that would work for any amount of columns and rows. I have trouble passing matrices to functions, which have rows and columns determined by user input.

This is what I have:

#include <iostream>

using namespace std;

template <int rows, int cols>
void display(int (&array)[rows][cols]) {
  int i, j;
  cout<<"\n";
  for(i = 0; i<rows; i++) {
      for(j = 0; j<cols; j++) {
        cout<<" ";
        cout<<array[i][j];
      }
      cout<<"\n";
    }
}


int main() {
  int M1[3][3];
  cout<<"Enter your matrix elements: \n";
  int i, j;
    for(i = 0; i<3; i++) {
      for(j = 0; j<3; j++) {
        cout<<"a["<<i<<"]["<<j<<"]: ";
        cin>>M1[i][j];
      }
    }
    display(M1);
  return 0;
}

Is performing such task possible without complicating the code too much?

Ach113
  • 1,775
  • 3
  • 18
  • 40
  • 1
    you should read more about vectors. they are more dynamic, and it is more intuitive to work with – Arkady Godlin Apr 13 '18 at 17:29
  • 1
    I recommend searching the web for Matrix libraries. Also search the internet for "C++ FAQ matrix" if you plan on writing your own. – Thomas Matthews Apr 13 '18 at 17:29
  • 1
    define complicating the code too much. Are you comfortable with the STL :) ? – Srini Apr 13 '18 at 17:29
  • 2
    Use the library containers: an "int" matrix will be `std::vector> mat;` – kebs Apr 13 '18 at 17:30
  • 3
    It depends on what you are going to do with it and the size of the matrix. The `vector` of `vector`s can be horrifically slow for small matrices due to poor caching behaviour, but a single `vector` inside a simple wrapper class and doing the 2D-> 1D mapping yourself can be surprisingly efficient. Example: https://stackoverflow.com/a/44553264/4581301 – user4581301 Apr 13 '18 at 17:36
  • @kebs: No, `std::vector mat;`, wrapped as a private data member in a `Matrix` class, with the offsets calculated in a public member function like `operator()(int x, int y)`. – Christian Hackl Apr 13 '18 at 20:50

2 Answers2

1

Many remarks and comments are okay, but I think that the best strategy is to use a single vector for storage and a vector for the shape. Learn on pythons numpy to understand the concept or search for ndarray, which is how many different platforms name this concept (n dimensional array). A class bundling the data vector, the shape vector and convenient operators and member functions is then the way to go.

user3640029
  • 165
  • 4
  • The part noone seems to be answering the asker is that template resolution is done at compile time. So, it cannot call into differently sized function based on user input. You should add this to your already good answer. (although this site strongly favours vector of vector type of approaches) – Jeffrey Apr 13 '18 at 17:56
  • @Jeffrey I dunno. `vector` of `vector` sucks a lot of the time. – user4581301 Apr 13 '18 at 19:24
0

The classical answer would have required you to perform dynamic memory allocations for you array. This is a bit overwhelming especially if you are a newbie. (And to the best of my knowledge this is still way to do it in C)

However the recommend way to do something like that in modern C++ is to use the Standard Template Library.

/*
... Stuff where you get input from the user, specifically the num of rows and cols
... Say these vals were stored in 2 ints num_rows and num_cols
*/
std::vector<std::vector<int> > mat(num_rows);
for (int i = 0; i < num_rows; i++) {
    mat[i].resize(num_cols); // this will allow you to now just use [][] to access stuff
}

Please see the first comment below, it has a nice way to avoid the loop to set up the vector and takes care of it at initialization time

Srini
  • 1,619
  • 1
  • 19
  • 34
  • 2
    You can avoid the loop with slightly smarter initialization: `std::vector > mat(num_rows, std::vector(num_cols));` – user4581301 Apr 13 '18 at 17:47
  • Yes, you are right. That is much better and looks more elegant :) – Srini Apr 13 '18 at 17:48
  • 2
    The downsides of vector> are many. Most notably that the dimensions are not guaranteed to be consistent and the data can be stored in different memory locations possibly harming performance. – user3640029 Apr 13 '18 at 17:50
  • @user3640029 could you elaborate a bit :) ? If you explicitly resize aren't you setting them to `0` ? Thereby guaranteeing dimensional correctness? I agree with you about performance :) – Srini Apr 13 '18 at 17:52
  • 1
    The values are all set by default to zero, but my fellow anonymous user is concerned more with the lack of contiguity. In a single `vector` all to the data is in one block but in `vector` of `vector`, the outer `vector` contains a block of many inner `vector`s. Each of the inner `vector`s contains a pointer to its own block of data. These blocks may be nowhere near each other forcing pointer chasing and unnecessary cache misses. This can cause slow-downs of orders of magnitude. Search term for more information: Spatial Locality. – user4581301 Apr 13 '18 at 19:40
  • Thank you! That makes the performance aspect crystal clear :) – Srini Apr 13 '18 at 20:05