Declaring array with user-defined size before the main function - c++

I have a an array int matrix[10][10] as well as other arrays with similar size which is declared before the prototype functions and main function. This 2d array is used by all of the functions. However, I need my program to have a function that asks the user the size of the matrix he wants. So, it's gotta be something like this: int matrix[ROWS][COLUMNS]. I know for sure that I can't place the declare the array inside the main function since this array is used by all the other functions. How do I declare this kind of array?

First of all, it is impossible to declare an array with variable sizes, as they are not legal in C++ (although they are legal in C). So you're out of luck here.
Second, you want the declaration before main. Hence, you have to use either
A dynamic array, defined globally like int** matrix; and initialized in main() as
matrix = new int*[ROWS];
for(size_t i = 0 ; i < ROWS; ++i)
matrix[i] = new int[COLS];
then you'd have to release its memory at the end of the day
for(size_t i = 0; i < ROWS; ++i)
delete[] matrix[i];
delete[] matrix;
or
A standard container like std::vector<>
std::vector<int> matrix; // defined globally
and in main() reserve memory for it, like
matrix.reserve(ROWS*COLUMNS); // reserve memory for M rows
Then you'd need to play around with the indexes, so you can map from pairs of indexes to 1D index, i.e. the "logical" element [i][j] is represented by the index i * COLS + j in matrix.
Of course, you could have used a std::vector<std::vector<int>>, however this approach is faster since the memory is guaranteed to be contiguous (same applies to the first example, where you could have used an int* instead).

Related

different between int **arr =new int [ n]; and int a[i][j]?

I was solving a problem on sum of submatrices, I declared my 2d-array as
int a[i][j] ; //i =number of rows and j = number of columns
my code executed properly. But when I saw the solution
i saw these lines :
int **arr = new int * [n] ;
for (int i = 0 ; i < n ; i++)
{
arr[i]=new int [m];
}
// n -> number of rows and m -> number of columns.
I understand the code. why the solution(given on some random website) is using pointers. If we can do it using the above normal declaration. It will make the code faster or something?
This declaration
int a[i][j] ; //i =number of rows and j = number of columns
requires that the variables i and j would be compile-time constants. Variable length arrays is not a standard C++n feature though some compilers can have their own language extensions that include this feature.
The second problem that exists is if sizes of an array are too big then the compiler can be unable to create such an array with automatic storage duration.
So if i and j are not compile-time constants or are too big then you have to allocated memory dynamically yourself or you can use the standard container std::vector.
If we can do it using the above normal declaration. It will make the code faster or something?
no all in above code you create an array in the stack it will be deleted if the function out of scope it will be removed automatically
the second is created in heap it will still in the heap until u delete it by self
Both ways of array declaration are useful in different use cases. The declaration:
int a[i][j];
declares an array statically and it uses stack memory to store the array or we can say that the memory is allocated at the runtime. This type of array declaration requires you to pass the value 'n' and the size of the array can not be altered after it's been declared. That's where it has a drawback as you can not increase the size if you want to store some more elements. Also if you stored less elements than 'n', then the remaining memory gets wasted.
The other type of declaration:
int *a = new int[n]; //For 1D array
creates a dynamically allocated memory. In other words, in this type of declaration memory allocation takes place only when an element is placed in the array or at the runtime.
This allocation ensures that there is no memory wastage and stores the elements of the array in the heap memory. But in this type of declaration, you also need to deallocate the memory otherwise it may cause memory leaks because C++ has nothing like a garbage collector.

Creating bidimensional array's size with the input values

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;

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 do you delete (or fill with specific values) a static n-dimension array?

const int ROWS = 3;
const int COLUMNS = 4;
void fillArray(double a[ROWS][COLUMNS], double value);
void deleteArray(double a[ROWS][COLUMNS]);
int main () {
double a[ROWS][COLUMNS];
fillArray(a, 0);
deleteArray(a);
}
In C++, how do you delete (or fill with specific values) a static n-dimension array?
In C++ we generally do not use arrays. We use std::vector.
You can use memset or std::fill to fill the array with specific values.
BTW you can use delete on dynamically allocated arrays not on static ones.
memset( a, 0 ,ROWS * COLUMNS * sizeof( double ));
or
std::fill(&a[0][0], &a[0][0]+sizeof(a)/sizeof(double), 0);
You can delete only an object created by new (and that object will be allocated in the heap). What do you mean by "deleting a static POD variable"? It has no sense:
1) It doesn't have any destructor to perform additional tasks before freeing the memory,
2) The stack memory will be "freed" as you exit the current block.
And to set it: either loop, either simple memset(a, 0, sizeof(a)); .
Also, the array in your example is not static.
std::vector is what is generally used for C++ arrays (especially when you're new at it). One of vector's constructors will fill it for you to:
std::vector<type> myVector(initialSize, defaultValue);
If you want multidimensional, you could do a vector of vectors, or boost::multi_array:
boost::multi_array<type, numberOfDimensions> myArray(boost::extents[firstSize][secondSize][thirdSize]);
In that case, you'll need to use the multiple-for-loops approach, because it doesn't seem to have a constructor that does that.
EDIT: Actually you can use std::vector to make a multidimensional array with default values:
std::vector<std::vector<double> > a(3, std::vector<double>(4, 0));
Where 3 is the number of rows, 4 is the number of columns and 0 is the default value.
What it's doing is create a vector of vectors with 3 rows, where the default value for each row is a vector with 4 zeroes.
Filling arrays in C++ is the same as filling them using C, namely nested for loops
int i, j;
for (i = 0; i < ROWS; i++)
for (j = 0; j < COLS; j++)
a[i][j] = 0
Arrays aren't "deleted" but they can use free if they've been allocated on the heap (if they've been allocated on the stack within a function, this is unnecessary).
int i;
for (i = 0; i < ROWS; i++)
free(a[i]);
free(a);
Firstly, the code you posted seems confused. What is it that you think "deleteArray" is supposed to do? 'a' is an auto variable and therefore cannot be deleted or freed.
Secondly, wrap your array in a class. There is a nice one in the FAQ that you can start with, but it can be improved. The first improvement is to use a vector rather than newing a block of memory. Then std::fill can be used to fill the array.
Use std::fill
#include <algorithm>
And then your implementation is simply:
std::fill(&a[0][0], &a[0][0]+sizeof(a)/sizeof(a[0][0], value);
You don't delete the array since it is stack allocated.

Why can't a multidimensional array be allocated with one new call in C++?

In C++ you can easily allocate one dimensional array like this:
T *array=new T[N];
And you can delete it with one statement too:
delete[] array;
The compiler will know the magic how to deallocate the correct number of bytes.
But why can't you alloc 2-dimensional arrays like this?
T *array=new T[N,M];
Or even like this?
T *array=new T[N,M,L];
If you want a multidimensional you have to do it like this:
T **array=new T*[N];
for(int i=0;i<N;i++) array[i]=new T[M];
If you want a fast program that uses matrices (matrix operations, eigenvalue algorithms, etc...) you might want to utilize the cache too for top performance and this requires the data to be in the same place. Using vector<vector<T> > is the same situation. In C you can use variable length arrays on the stack, but you can't allocate them on the heap (and stack space is quite limited), you can do variable length arrays in C++ too, but they won't be present in C++0x.
The only workaround is quite hackish and error-phrone:
T *array=new T[N*M];
for(int i=0;i<N;i++)
for(int j=0;j<M;j++)
{
T[i*N+j]=...;
}
Your workaround of doing T *array=new T[N*M]; is the closest you can get to a true multi-dimensional array. Notice that to locate the elements in this array, you need the value of M (I believe your example is wrong, it should be T[i*M+j]) which is known only at run-time.
When you allocate a 2D array at compile-time, say array[5][10], the value 10 is a constant, so the compiler simply generates code to compute i*10+j. But if you did new T[N,M], the expression i*M+j depends on the value of M at the time the array was allocated. The compiler would need some way to store the value of M along with the actual array itself, and things are only going to get messy from here. I guess this is why they decided not to include such a feature in the language.
As for your workaround, you can always make it less "hackish" by writing a wrapper class that overloads operator (), so that you could do something like array(i, j) = ....
Because multidimensional array is something different then array of arrays/pointers.
use std::vector
Why can't a multidimensional array be allocated with one new call in C++?
Because when the ISO wrote the C++ language standard, they didn't decide to add that feature to the language. I don't know why they decided not to.
If you don't like that, you can create helper functions to allocate/free multidimensional arrays, or you can switch to a language like C# or Java that does support easily allocating multidimensional arrays.
What you can do, however, is allocate an object containing a two-dimensional array off the heap. I would just write a wrapper class for it.
I was thinking about this question last night, and this solution came to me.
T * raw = new T[N*M];
T ** array = new T*[N];
for(int i=0; i<N; i++)
array[i] = raw + i * M;
Now "array" acts just like a contiguous static sized two dimensional array. You just have to take care of deleting both the raw array, and the multi-dimensional array.
I would recommend that you use a Boost::multi_array, from the library of the same name, which provides a simple interface to a multidimensional array. It can be allocated in one line, and at a sufficiently high optimization level is usually as fast as a native array.
Here's some example code from the library's website:
#include "boost/multi_array.hpp"
#include <cassert>
int
main () {
// Create a 3D array that is 3 x 4 x 2
typedef boost::multi_array<double, 3> array_type;
typedef array_type::index index;
array_type A(boost::extents[3][4][2]);
// Assign values to the elements
int values = 0;
for(index i = 0; i != 3; ++i)
for(index j = 0; j != 4; ++j)
for(index k = 0; k != 2; ++k)
A[i][j][k] = values++;
// Verify values
int verify = 0;
for(index i = 0; i != 3; ++i)
for(index j = 0; j != 4; ++j)
for(index k = 0; k != 2; ++k)
assert(A[i][j][k] == verify++);
return 0;
}
Because the comma is an operator.
int a = (3, 5, 7, 9);
The program will evaluate 3, discard the result,
evaluate 5, discard the result,
evaluate 7, discard the result,
evaluate 9, and assign it to a.
Hence the syntax you are looking for can't be use,
and retain backward compatibility to c.