Passing 2d arrays without knowing the size? - c++

Can anyone help me? I want to pass firstMatrix, secondMatrix, and finalMatrix. So far I have this. I could make it a global variable but I still wouldnt know the actual size
int matrixSummation(int firstMatrix[][matrixSize],int secondMatrix[][matrixSize], int finalMatrix[][matrixSize], int matrixSize){
for(int row=0; row< matrixSize; row++){
for(int col=0; col< matrixSize; col++){
finalMatrix[row][col]=firstMatrix[row][col]+secondMatrix[row][col];
}
}
}
int main(int argc, char** argv) {
int matrixSize;
cout << "Enter size of your matrices: " <<endl;
cin >> matrixSize;
int firstMatrix[matrixSize][matrixSize];
int secondMatrix[matrixSize][matrixSize];
int finalMatrix[matrixSize][matrixSize];
cout <<"Enter numbers for the 1st matrix: "<<endl;
for(int row = 0; row < matrixSize; row++){
for(int col=0; col< matrixSize; col++){
cin >> firstMatrix[row][col];
}
}
cout <<"Enter your numbers for the 2nd matrix: "<<endl;
for(int row = 0; row < matrixSize; row++){
for(int col=0; col< matrixSize; col++){
cin >> secondMatrix[row][col];
}
}
matrixSummation(firstMatrix,secondMatrix,finalMatrix,matrixSize);
}

You can use a function template:
template<std::size_t A, std::size_t B>
int matrixSummation(int (&firstMatrix)[A][B], int (&secondMatrix)[A][B], int (&finalMatrix)[A][B])
so that inside your function you can access the number of rows with A and the number of columns with B, without passing sizes around.

This can't be done. At compile time, the function
int matrixSummation(int firstMatrix[][matrixSize],int secondMatrix[][matrixSize], int finalMatrix[][matrixSize], int matrixSize){
should know the matrix dimesions (atleast the columns).
See here: Passing array with unknown size to function
You can make a 1D array represent your 2d array:
instead of
array[ROW][COL];
use
array[ROW*COL];
And when accessing:
a[r][c]; //r<5,c<5
Use:
a[r*ROW+c];

I have been working on dynamic array size for my image file as well, in the end i just pass the array using int**.
#include <iostream>
using namespace std;
void printMatrix(int** val, int row, int col)
{
int new_val[row][col];
int i, j;
for(i = 0; i < row; i++)
{
for(j = 0; j < col; j++)
{
new_val[i][j] = val[i][j];
cout<<new_val[i][j]<<" ";
}cout<<endl;
}
cout<<"test!"<<endl;
}
int main ()
{
int i, j, k;
int row, col;
row = 3;
col = 5;
int** array = new int*[row];
for(int i = 0; i < row; ++i)
{
array[i] = new int[col];
}
for (i = 0; i < row; i++)
{
for (j = 0; j < col; j++)
{
array[i][j] = k;
k++;
cout << array[i][j]<< " ";
}
cout<<endl;
}
cout<<endl;
printMatrix(array, row, col);
return 0;
}

The root of the problem is that this is not allowed in Standard C++:
cin >> matrixSize;
int firstMatrix[matrixSize][matrixSize];
Some compilers let this pass, so far; however you then run into difficulties when trying to use firstMatrix. For example the problem that you have had trying to pass it to a function.
In fact the reason this is not allowed in Standard C++ is that so far nobody has been able to come up with a proposal that does not run into difficulties sooner or later.
The best course of action would be to declare your arrays differently, in a way that is compatible with Standard C++.
In Standard C++, C-style arrays must have their dimension known at compile-time. Therefore you must use a different container.
The version that is the simplest code to write would look like:
vector< vector<int> > firstMatrix(matrixSize, vector<int>(matrixSize));
which creates a 2-D array with each dimension being matrixSize and then you can access it in the same way you would access a C-style array.
Importantly, you can pass firstMatrix to a function exactly the same way you would pass any other variable, and its sizes can be accessed via member functions of the vector, e.g. firstMatrix.size() is the number of rows, and firstMatrix[0].size() is the number of columns.
That version is a bit less efficient at run-time due to the fact that each row is stored in a separate allocation. To have a contiguous storage you can write:
vector<int> firstMatrix(matrixSize * matrixSize);
Then you simulate the rows and columns within that allocation, for example the previous code's firstMatrix[2][3] would in this solution be firstMatrix[2 * matrixSize + 3].

The big thing here is initializing a dynamically allocated 2-D array. I recommend using "vectors," but I show a pointer approach. There is no need to pass a set value for the size to the function.
int[][] matrixSummation(int firstMatrix[][],int secondMatrix[][]){
if(firstMatrix.length != secondMatrix.length
|| firstMatrix[].length !=secondMatrix[].length)
return NULL;
int **finalMatrix;
finalMatrix= new int*[firstMatrix.length];
for (int i = 0; i < 10; ++i) {
finalMatrix[i] = new int[firstMatrix.length];
//make sure you initialize each int[]__ with proper length.
}
for(int row=0; row< matrixSize; row++){
for(int col=0; col< matrixSize; col++){
finalMatrix[row][col]=firstMatrix[row][col]+secondMatrix[row][col];
}
}
return finalMatrix;
}

Related

Scope of dynamic (multidimm) array when initialized with pointer and new

I'm royally confused right now. I have seen similar questions asked, and my implementation seems to be along the lines of these solutions, but I just can't get it to work.
I need to have a UtilClass that can initialize and dump a multi-dimensional dynamic array. I just want to pass the pointer the the array in BaseClass that I want initialized along with the dims. I chose to use the new keyword instead of malloc(), but I'm worried that the scope of the pointers is limited to the init function and not to the lifetime of the BaseClass (or the array pointer for that matter) and that's why the dump function produces a SEGFAULT.
Here is some code to explain:
// BaseClass.h
#pragma once
include "UtilClass.h"
class BaseClass
{
public:
UtilClass* util{nullptr};
double** array{nullptr};
};
// BaseClass.cpp
#include "BaseClass.h"
BaseClass::BaseClass() {
util = new UtilClass();
util->init(array, 4, 6);
util->dump(array, 4, 6);
}
// UtilClass.h
#pragma once
class UtilClass {
void init(double** array, int rows, int cols);
void dump(double** array, int rows, int cols);
};
// UtilClass.cpp
#include "UtilClass.h"
void UtilClass::init(double **darray, int rows, int cols) {
int i,j;
array = new double*[rows];
for (i = 0; i < rows; i++)
array[i] = new double[cols];
for (i = 0; s < rows; i++)
for (j = 0; a < cols; j++) {
data[i][j] = 1;
std::cout << "Data in array " << data[i][j] << std::endl; // This obviously works
}
}
void dump(double** array, int rows, int cols) {
int i, j;
for (i = 0; i < rows; i++)
for (j = 0; j < cols; j++)
std::cout << array[i][j] << " "; // But this produces a SEGFAULT
std::cout << std::endl;
}
Let me start off with a piece of advice: it's best to reuse existing tools. Consider using std::vector for dynamically-allocated array. This is well tested, optimized and easy to use. Otherwise, you'll need to deal with conundrums of memory management (e.g. deallocate the allocated chunks of memory in the dtor of BaseClass).
Regarding your question: when you call init, you pass the pointer by value. This means that the init method allocates some memory and stores the pointer to it in its local copy of darray. At the end of init this local variable is gone (you lose access to it, leaking whole allocated memory). Change the method to:
void UtilClass::init(double ***array, int rows, int cols) {
int i,j;
*array = new double*[rows];
for (i = 0; i < rows; i++)
(*array)[i] = new double[cols];
for (i = 0; i < rows; i++)
for (j = 0; j < cols; j++) {
(*array)[i][j] = i*j;
std::cout << "Data in array " << (*array)[i][j] << std::endl; // This obviously works
}
}
When calling dump, you need to pass 4 and 6 (and not 5 and 6).

Runtime error : reference binding to null pointer of type 'int' (stl_vector.h) [duplicate]

Clearly this isn't working so the code is wrong, but how do I fix it?
This whole thing could be wrong for all I know lol, but I'm trying to create a multidimensional vector that creates itself during runtime. I get an error: vector subscript out of range.
#include <iostream>
#include <vector>
int main(){
int row = 0, col = 0;
std::cout << "Size of Row: "; std::cin >> row;
std::cout << "Size of Column: "; std::cin >> col;
std::vector<std::vector<int>> td;
td.resize(row * col);
for (int i = 0; i <= row; i++){
for (int j = 0; j <= col; j++){
td[i][j];
}
}
}
When you use
td.resize(row * col);
the first dimension of td will be row*col, but its second dimension are still empty. That's why you got the error.
You should use
td.resize(row); // set first dimension
for (int i=0; i<row; i++) // set each second dimenstion
td[i].resize(col);
or simply
vector<vector<int>> td(row, vector<int>(col)); // has rows, each of them has cols
You need to allocate the appropriate amount of memory to the vector of vectors. Instead of resizing it, you can explicitly set the amount empty rows and columns with the following code.
std::vector< std::vector<int> > td(row+1, std::vector<int>(col+1));
//+1 is needed because the loop you created is <=
Otherwise, you can adjust the loop and do the following:
std::vector< std::vector<int> > td(row, std::vector<int>(col));
for (int i = 0; i < row; i++){
for (int j = 0; j < col; j++){
td[i][j];
}
}
td refers to the outer vector, so your resize creases a vector of row'col empty vectors. You'll need to resize that to just row instead, then your for i loop can say td[i].resize(col) inside to make it two dimensional.

Overflow error when using C++ std::cin, has strange value inside variable (C++11)

For a C++ program, I've implemented 2 functions:
Make1DArray that takes array size as input and creates a 1D array of that size
Make2DArray that takes size of row and column and creates a 2D array of the given row and column sizes
The main function looks like this:
int main()
{
cout << "enter 1d array length: ";
int x;
cin >> x;
Make1DArray(x);
cout << "enter 2d array row size: ";
int nrows, ncols;
cin >> nrows;
cout << "enter 2d array col size: ";
cin >> ncols;
Make2DArray(nrows, ncols);
return 0;
}
When I input x = 10000000000 (10^10), the program outputs does not run the second function and asks for input. The message outputs look like this:
enter 1d array length: 100000000000
enter 2d array row size: enter 2d array col size:
So I checked the values for x, nrow, and ncol and the values were this:
x = 2147483647
nrows = 0
ncols = 32767
I googled a bit and found out that when an overflow error happens, cin would assign x the closest value.
For nrows I understand it might get 0, as an error happened.
What I don't get is why the third variable, ncols is assigned value 32767. I did find out that 32767 is the max value of a short int but I don't know why the variable ncols would get this value.
Could anyone explain me this? Thanks!
ETA: I wasn't sure if I should add the two functions because they're really simple but just in case, they look like this:
void Make1DArray(int arrSize) {
int *arr;
arr = (int *)malloc(arrSize * sizeof(int));
for (int i = 0; i < arrSize; i++)
{
arr[i] = i;
}
}
void Make2DArray(int nrows, int ncols) {
int **arr = (int **)malloc(nrows * sizeof(int *));
for (int i = 0; i < nrows; i++)
arr[i] = (int *)malloc(ncols * sizeof(int));
int count;
for (int i = 0; i < nrows; i++)
for (int j = 0; j < ncols; j++)
{
arr[i][j] = ++count;
}
}
The problem
THe problem is that the first overflow sets the failbit due to the value overflow. The subsequent readings are not performed, leaving nrows and ncols in an undefined state. If you'd initialize theses variables, you'll notice that they wouldn't change.
Solution
Do not use int for holding the size but size_t instead. This should work with your example figures on most compilers.
If you want your code to be bullet proof, check the state on cin to see if input was valid and handle any errors if necessary (including cin.clear() to clear the fail state before resuming reading).
Not related: in the code of your functions (which leak memory by the way), iterate on a size_t as well. And avoid malloc(): in C++ prefer new for dynamically creating objects.

how to create huge 2D arrays in C++

I am trying to create a huge 2D array in c++ like this :
float array[1000000][3];
I have to store some values in this array which has 3 components. This will be done iteratively by two for loops of 1000 loops.
When I try to run this I get an error :
Segmentation fault
Here is a bit of my code :
int m=0,c=0;
float error;int count=0;
array<array<float, 1000000>, 3> errors;
for(int i=0; i<1000; i++){
for(int j=0; j<1000; j++){
error=distance(j+20,m,c,1000-matrix(1,j));
errors[count][0]=error;
errors[count][1]=m;
errors[count][2]=c;
c++;
count++;
}
m++;
c=0;
}
sort(errors.begin(), errors.end());
cout<<errors[0][0]<<endl<<errors[0][1]<<endl<<errors[0][2]<<endl;
The error continues even after commenting out the sort...
matrix(1,j) is a matrix and I am accessing its elements using this method.
I want minimum value of error and the set of values of m and c for which error is minimum.
Is there any way I can achieve this?
Thanks in advance.
You can use array to easily perform your task. Here what you can:
#include<array>
using namespace std;
Then, let create your data array:
const int N = 1000000;
const int M = 3;
array<array<float, N>, M> my_array;
You can fill this newly created array by doing:
for(int i=0; i < N; i++){
for(int j=0; j < M; j++){
my_array[i][j] = 0.0f; // Just for example
}
}
For more information on how to use array library, please see here
If you don't want to use array, you can also proceed as follows:
const int N = 10000000;
const int M = 3;
float *my_array
my_array = new float[N*M]; // give it a memory on the stack
if(my_array == nullptr){
cerr << "ERROR: Out of memory" << endl;
}
for(int i=0; i < N; i++){
for(int j=0; j < M; j++){
*(my_array + i*N + j) = 0.0f; // Just for example
}
}
Make sure you release the memory you acquired by doing:
delete [] my_array;

Passing integers to arrays within functions (without pointers)

I'm trying to create a magic square that will print four different grid sizes (5x5, 7x7, 9x9, 15x15). The error I'm having is the array magsquare within the function tells me it needs a constant integer. (I can't use pointers) This is a class assignment.
#include <iostream>
#include <iomanip>
using namespace std;
void magicSquare(int n){
int magsquare[n][n] = { 0 }; /*THIS is the error with [n][n]*/
int gridsize = n * n;
int row = 0;
int col = n / 2;
for (int i = 1; i <= gridsize; ++i)
{
magsquare[row][col] = i;
row--;
col++;
if (i%n == 0)
{
row += 2;
--col;
}
else
{
if (col == n)
col -= n;
else if (row < 0)
row += n;
}
}
for (int i = 0; i < n; i++){
for (int j = 0; j < n; j++){
cout << setw(3) << right << magsquare[i][j];
}
cout << endl;
}
}
int main(){
int n = 5;
magicSquare(n);
return 0;
}
Indentation may look incorrect, but it's right. Sorry.
The failure is because standard C++ cannot allocate dynamically sized array on the stack, as you are trying to do.
int magsquare[n][n];
As far as magicSquare is concerned n is only known at runtime and for an array to be allocated on the stack it's size must be known at compile time.
Use a 15 x 15 array.
int magsquare[15][15];
As long as you know this is the largest you'll ever need, you should be ok.
Alternatives (which you've already said you can't use)
Use new to declare a 2d array of the required dimensions. (Remember to delete[] it though)
Use std::vector
It may also be a good idea to add a check that n values over 15 or under 1 are rejected, otherwise you'll face undefined behaviour if any values outside of 1-15 are passed into the function.