Creating bidimensional array's size with the input values - c++

First of all, happy new year!
So, I'd like to ask if I could use some input values as the size of a bidimensional array, for example:
I'd like to know, if instead of doing this:
const int N = 10;
const int M = 10;
typedef int IntMatrix[N][M];
Let's say that would be the max size of the array I could create, but then the user inputs that the size must have a size of 5x5. I know I could then use 5x5 as a limit when doing stuff, but could I do like the same, but using the input values as the dimension of the Matrix?
Something like:
cin >> N >> M;
And then use that as the MAX size of each dimension.
Thanks for your help!

No. The size of an array must be known at compile time and can not be determined at runtime as described in this tutorial for example. Therefore, the size of the array cannot depend on user input.
What you can do, is allocate an array dynamically and store it's address in a pointer. The size of a dynamic array can be determined at runtime. However, there is a problem. Only the outermost dimension of a dynamically allocated 2D array may be determined at runtime. You have 2 options: Either you allocate a flat array of size NxM where the rows are stored continuously one after the other and you calculate the index using maths. Or, you use an array of pointers and assign each pointer to a dynamically allocated array column. The first option is more efficient.
There is another problem. Dynamic memory management is hard, and it's never a good idea to do it manually even if you know what you're doing. Much less if you don't. There is a container class in the standard library which takes care of memory management of dynamic arrays. It's std::vector. Always use it when you need a dynamic array. Your options stay similar. Either use a flat, NxM size vector, or a vector of vectors.

The array should be dynamically allocatedn because array size should be known at compile-time. You can do this way:
int N,M; // Dimensions
int** intMatrix; // Array of array
std::cin << N << M;
intMatrix = new int*[N]; // Allocate N the row
for(int i=0; i<N; i++){
intMatrix[i] = new int[M]; // For each row, allocate the col
}
// aaaand don't forget to free memory like this:
for(int i=0; i<N; i++){
delete [] intMatrix[i];
}
delete [] intMatrix;

Related

declare and initialize 2d array with unknown size

I take the size of rows n and columns m from the user
I want to make a 2D array (matrix) of the size nxm , initialize it and do some work on it
int main()
{
int m,n;
cin>>m>>n;
const int grow=m;
const int gcol=n;
auto G = new double[grow][gcol](); //GIVES ERROR that grow and gcol must be const
/*int** G = new int*[n];
for (int i = 0; i < n; ++i)
G[i] = new int[n];*/
}
You can always index in a one dimensional array with y * gcol + x to make it effectively work as a two dimensional one. With that you can use a dynamic memory e.g. with a std::vector<double>.
//GIVES ERROR that grow and gcol must be const
No, it does not. Unless your compiler is bad. Read the error again.
It gives an error that gcol must be a constant expression.
You cannot have dynamic arrays of dynamic arrays. It's simply not possible in c++. You can only have dynamic arrays of things that have a static size, known at compile time.
Therefore, you cannot have a 2D array where both dimensions are determined at runtime.
You have 2 alternatives:
Use a dynamic array of pointers to dynamic arrays. Which is what you have there, commented out. A dynamic array of vectors works too.
Use a flat, one dimensional array that contains the rows in succession.
In either case, I recommend using a class to manage the memory. std::vector, perhaps.
Array size is part of the type and needs to be known at compile time. You get it at runtime. Use vectors instead.

How to get the dimensions of a 2d dynamic array of strings in C++?

I have a dynamically populated array of strings in C++:
string** A;
it is populated like this:
A = new string*[size1];
and then:
for (unsigned int i = 0; i < size1; i++)
{
A[i] = new string[size2];
for (unsigned int j = 0; j < size2; j++)
{
A[i][j] = whatever[j];
}
}
elsewhere, I want to find out the dimensions (size1 and size2).
I tries using this:
sizeof(A[i]) / sizeof(A[i][0])
but it doesn't work.
Any ideas ?
Thanks
When you allocate memory via new T[N], the value N is not stored anywhere . If you need to know it later, you will need to keep track of it in your code.
There are pre-existing classes for allocating memory that also remember the length that was allocated. In your code:
vector<vector<string>> A(size1, vector<string>(size2));
// (code to populate...)
then you can access A.size() to get size1, and A[0].size() to get size2.
If the dimensions are known at compile-time you may use array instead of vector.
It is very simple to find the size of a two dimensional (more exactly of one-dimensional dynamically allocated arrays) array. Just declare it like
std::vector<std::vector<std::string>> A;
and use
std::cout << A.size() << std::endl;
As for your approach then you have to store the sizes in some variables when the array is allocated.
If you are learning C++, I would recommend that you learn Classes. With a class you can encapsulate int variables along with your 2D array that you can use to store the dimensions of your array. For example:
class 2Darray{
string **array;
int rows;
int cols;
}
You can then get the dimensions of your 2Darray object anytime by reading these member variables.
vectors will do this for you behind the scenes but its good for you to learn how to do this.
You can't create an array just using pointer operator. Every array is basically a pointer with allocated memory. That's why compiler wants constant before creating array.
Basically; sizeof(A[i]) won't give you the size of array. Because sizeof() function will return the a pointers size which is points to A[i] location. sizeof(A[i]) / sizeof(A[i][1]) will probably give you 1 because you are basically doing sizeof(int)/sizeof(int*)
So you need to store the boundary yourself or use vectors. I would prefer vectors.
Can't get array dimensions through pointer(s)

How to declare dynamic 2D integer array in C++

I've a requirement where I need to take input from user and based on the input length of array would be decided. For e.g.
int row, column;
cin>> row>>column;
int matrix[row][column];
However int matrix[row][column] is not working as compiler is giving an error saying
"Expression must have a constant value"
Also, if someone can guide me as how address of matrix[row][column] assigned to pointer. I know how to do it with static array but not dynamic.
To declare 2d dynamic array you will need pointers of pointers
int row, column;
cin>> row>>column;
int** matrix = new int*[row];
for(int i = 0; i < row; ++i)
matrix[i] = new int[column];
This is because arrays are static in c++ and take a fixed position in the memory.lets say the array has 1000 element. when you declare a static array this means that there is 1000 positions in the memory after each other reserved for your array. If you want to add one more item to the array you will add this item in the end of the reserved array, but if that position has some data for something other than the array, this data will be deleted!!
but when you declare it as pointers, you don't store the elements nested in the memory, but you are storing them in different locations, and each location is stored in the array of pointers, and when you add new elements to the array, compiler will search for empty locations in the memory and will store the new elements there.
Using a 2D array to hold a matrix is a bad idea - especially because of the loop for memory allocations.
Use a 1D array of size rows * columns and access elements with y * columns+x, and store it inside and unique_ptr to avoid commons memory management problems.
Here's what I propose:
uint32_t rows, cols;
std::cin >> rows >> cols; // Check rows and cols are actually numbers
std::unique_ptr<int[]> matrix(new int[rows*cols]);

Incrementally dynamic allocation of memory in C/C++

I have a for-loop that needs to incrementally add columns to a matrix. The size of the rows is known before entering the for-loop, but the size of the columns varies depending on some condition. Following code illustrates the situation:
N = getFeatureVectorSize();
float **fmat; // N rows, dynamic number of cols
for(size_t i = 0; i < getNoObjects(); i++)
{
if(Object[i] == TARGET_OBJECT)
{
float *fv = new float[N];
getObjectFeatureVector(fv);
// How to add fv to fmat?
}
}
Edit 1 This is how I temporary solved my problem:
N = getFeatureVectorSize();
float *fv = new float[N];
float *fmat = NULL;
int col_counter = 0;
for(size_t i = 0; i < getNoObjects(); i++)
{
if(Object[i] == TARGET_OBJECT)
{
getObjectFeatureVector(fv);
fmat = (float *) realloc(fmat, (col_counter+1)*N*sizeof(float));
for(int r=0; r<N; r++) fmat[col_counter*N+r] = fv[r];
col_counter++;
}
}
delete [] fv;
free(fmat);
However, I'm still looking for a way to incrementally allocate memory of a two-dimensional array in C/C++.
To answer your original question
// How to add fv to fmat?
When you use float **fmat you are declaring a pointer to [an array of] pointers. Therefore you have to allocate (and free!) that array before you can use it. Think of it as the row pointer holder:
float **fmat = new float*[N];
Then in your loop you simply do
fmat[i] = fv;
However I suggest you look at the std::vector approach since it won't be significantly slower and will spare you from all those new and delete.
better - use boost::MultiArray as in the top answer here :
How do I best handle dynamic multi-dimensional arrays in C/C++?
trying to dynamically allocate your own matrix type is pain you do not need.
Alternatively - as a low-tech, quick and dirty solution, use a vector of vectors, like this :
C++ vector of vectors
If you want to do this without fancy data structures, you should declare fmat as an array of size N of pointers. For each column, you'll probably have to just guess at a reasonable size to start with. Dynamically allocate an array of that size of floats, and set the appropriate element of fmat to point at that array. If you run out of space (as in, there are more floats to be added to that column), try allocating a new array of twice the previous size. Change the appropriate element of fmat to point to the new array and deallocate the old one.
This technique is a bit ugly and can cause many allocations/deallocations if your predictions aren't good, but I've used it before. If you need dynamic array expansion without using someone else's data structures, this is about as good as you can get.
To elaborate the std::vector approach, this is how it would look like:
// initialize
N = getFeatureVectorSize();
vector<vector<float>> fmat(N);
Now the loop looks the same, you access the rows by saying fmat[i], however there is no pointer to a float. You simply call fmat[i].resize(row_len) to set the size and then assign to it using fmat[i][z] = 1.23.
In your solution I suggest you make getObjectFeatureVector return a vector<float>, so you can just say fmat[i] = getObjectFeatureVector();. Thanks to the C++11 move constructors this will be just as fast as assigning the pointers. Also this solution will solve the problem of getObjectFeatureVector not knowing the size of the array.
Edit: As I understand you don't know the number of columns. No problem:
deque<vector<float>> fmat();
Given this function:
std::vector<float> getObjectFeatureVector();
This is how you add another column:
fmat.push_back(getObjectFeatureVector());
The number of columns is fmat.size() and the number of rows in a column is fmat[i].size().

dynamic allocation of rows of 2D array in c++

In c++, I can create a 2D array with fixed number of columns, say 5, as follows:
char (*c)[5];
then I can allocate memory for rows as follows
c = new char[n][5];
where n can be any variable which can be assigned value even at run time. I would like to know whether and how can I dynamically allocate variable amount of memory to each row with this method. i.e. I want to use first statement as such but can modify the second statement.
Instead of a pointer to an array, you'd make a pointer to a pointer, to be filled with an array of pointers, each element of which is in turn to be filled with an array of chars:
char ** c = new char*[n]; // array of pointers, c points to first element
for (unsigned int i = 0; i != n; ++i)
c[i] = new char[get_size_of_array(i)]; // array of chars, c[i] points to 1st element
A somewhat more C++ data structure would be a std::vector<std::string>.
As you noticed in the comment, dynamic arrays allocated with new[] cannot be resized, since there is no analogue of realloc in C++ (it doesn't make sense with the object model, if you think about it). Therefore, you should always prefer a proper container over any manual attempt at dynamic lifetime management.
In summary: Don't use new. Ever. Use appropriate dynamic containers.
You need to declare c as follows: char** c; then, allocate the major array as follows: c = new char*[n]; and then, allocate each minor array as follows: c[i] = new char[m]
#include <iostream>
using namespace std;
main()
{
int row,col,i,j;
cout<<"Enter row and col\n";
cin>>row>>col;
int *a,(*p)[col]=new (int[row][col]);
for(i=0;i<row;i++)
for(j=0;j<col;j++)
p[i][j]=i+j;
for(i=0;i<row;i++)
for(j=0;j<col;j++)
cout<<i<<" "<<j<<" "<<p[i][j]<<endl;
//printf("%d %d %d\n",i,j,p[i][j]);
}