Write a class using a two-dimensional dynamic array - c++

I have a homework assignment. I'm not looking for anyone to do the work for me, I'm just having trouble with one little aspect, although I'd accept advice on other bits as well.
The assignment is:
Write a class using a two-dimensional dynamic array.
The constructor passes in the dimensions of the array. The constructor also intializes all values in the dynamic array to the row index multiplied by the column index.
Swap two columns of the two-dimensional array, where the column indexes are passed in as parameters. Do this just by copying addresses, not values of column elemnets.
Delete a column of the two-dimensional array, where the column index is passed in as a parameter. Do not just use the delete operator on the column array and set the horizontal array element to NULL. Shrink the size of the horizontal array by 1.
Create a print function for the class to print out the values of the two-dimensional array and make sure that your functions are working correctly. After you know that they are working correctly, delete the print function.
I need help understanding how to declare the 2D array in the private section. And, as mentioned, if anyone could give me other hints on how to do it, that would be appreciated.

It's been awhile since I've done C++ development, but if I remember correctly, you'd do something like th efollowing:
int rows = 5;
int cols = 10;
int** array = new int*[rows];
for (int i = 0; i < rows; i++) {
array[i] = new int[cols];
}
I might be mistaken; I see posts to the contrary online where you have to fake 2D arrays with a single dimensional array and change your subscripting:
http://en.allexperts.com/q/C-1040/creating-2D-array-dynamically.htm

This should give you an idea. I haven't tried to compile this code:
class Array {
int **arr;
};
Array::Array(int rows, int cols) {
arr = new int * [rows]; // this will allocate 'rows' many 'int *'s
if (arr) { // to ensure memory was allocated
for (int i = 0; i < rows; i++) {
arr[i] = new int [cols]; // this will allocate 'cols' many 'int's
assert(arr[i]); // to ensure memory was allocated
}
}
}
arr is a pointer to an array of int pointers. arr[i] is a pointer to an array of ints i.e. each arr[i] represents one row in your 2-D array. This should get you started.
If you really want to learn C++, try things yourself and learn how to use a debugger. If you aren't comfortable with a debugger yet, use printfs to find out what is going wrong.

class TwoDimensionalArray {
private:
int **array;
public:
TwoDimensionalArray(const int, const int);
};
TwoDimensionalArray::TwoDimensionalArray(const int rows, const int columns) {
array = new int *[rows];
for (int i = 0; i < rows; i++)
array[i] = new int[columns];
}
int main() {
TwoDimensionalArray *arr1 = new TwoDimensionalArray(5, 10);
return 0;
}

Related

Way to ensure a dynamically allocated matrix is square?

I would like to determine if there is a way to determine whether a dynamically allocated matrix is square (nxn).
The first thing that came to mind was to see if there is a way to find out whether a pointer is about to point to an invalid memory location. But according to these posts:
C++ Is it possible to determine whether a pointer points to a valid object?
Testing pointers for validity (C/C++)
This cannot be done.
The next idea I came up with was to somehow use the sizeof() function to find a pattern with square matrices, but using sizeof() on a pointer will always yield the same value.
I start off by creating a dynamically allocated array to be of size nxn:
int **array = new int*[n]
for(int i = 0; i < n; i++)
array[i] = new int[n];
for(int i = 0; i < n; i++){
for(int j = 0; j < n; j++){
array[i][j] = 0;
}
}
Now I have a populated square matrix of size nxn. Let's say I'm implementing a function to print a square 2D array, but a user has inadvertently created and passed a 2D array of size mxn into my function (accomplished by the code above, except there are more row pointers than elements that comprise the columns, or vice versa), and we're also not sure whether the user has passed a value of n corresponding to n rows or n columns:
bool(int **arr, int n){
for(int rows = 0; rows < n; rows++)
for(int cols = 0; cols < n; cols++)
cout << *(*(arr + rows) + cols) << " ";
// Is our next column value encroaching on unallocated memory?
}
cout << endl;
// Is our next row value out of bounds?
}
}
Is there any way to inform this user (before exiting with a segmentation fault), that this function is for printing square 2D arrays only?
Edit: corrected 3rd line from
array[i] = new int[i]
to
array[i] = new int[n]
There is NO way to find out information about an allocation. The ONLY way you can do that, is to store the information about the matrix dimensions somewhere. Pointers are just pointers. Nothing more, nothing less. If you need something more than a pointer, you'll need to define a type that encapsulates all of that information.
class Matrix2D
{
public:
Matrix2D(int N, int M)
: m_N(N), m_M(M), m_data(new int[N*M]) {}
int N() const { return this->m_N; }
int M() const { return this->m_M; }
int* operator[] (int index) const
{ return m_data + m_M * index; }
private:
int m_N;
int m_M;
int* m_data;
};

Dynamically allocating memory

I am new to C++ and programming in general so i apologize if this is a trivial question.I am trying to initialize 2 arrays of size [600][600] and type str but my program keeps crashing.I think this is because these 2 arrays exceed the memory limits of the stack.Also,N is given by user so i am not quite sure if i can use new here because it is not a constant expression.
My code:
#include<iostream>
using namespace std;
struct str {
int x;
int y;
int z;
};
int main(){
cin>>N;
str Array1[N][N]; //N can be up to 200
str Array2[N][N];
};
How could i initialize them in heap?I know that for a 1-D array i can use a vector but i don't know if this can somehow be applied to a 2-D array.
How 2-or-more-dimensional arrays work in C++
A 1D array is simple to implement and dereference. Assuming the array name is arr, it only requires one dereference to get access to an element.
Arrays with 2 or more dimensions, whether dynamic or stack-based, require more steps to create and access. To draw an analogy between a matrix and this, if arr is a 2D array and you want access to a specific element, let's say arr[row][col], there are actually 2 dereferences in this step. The first one, arr[row], gives you access to the row-th row of col elements. The second and final one, arr[row][col] reaches the exact element that you need.
Because arr[row][col] requires 2 dereferences for one to gain access, arr is no longer a pointer, but a pointer to pointer. With regards to the above, the first dereference gives you a pointer to a specific row (a 1D array), while the second dereference gives the actual element.
Thus, dynamic 2D arrays require you to have a pointer to pointer.
To allocate a dynamic 2D array with size given at runtime
First, you need to create an array of pointers to pointers to your data type of choice. Since yours is string, one way of doing it is:
std::cin >> N;
std::string **matrix = new string*[N];
You have allocated an array of row pointers. The final step is to loop through all the elements and allocate the columns themselves:
for (int index = 0; index < N; ++index) {
matrix[index] = new string[N];
}
Now you can dereference it just like you would a normal 2D grid:
// assuming you have stored data in the grid
for (int row = 0; row < N; ++row) {
for (int col = 0; col < N; ++col) {
std::cout << matrix[row][col] << std::endl;
}
}
One thing to note: dynamic arrays are more computationally-expensive than their regular, stack-based counterparts. If possible, opt to use STL containers instead, like std::vector.
Edit: To free the matrix, you go "backwards":
// free all the columns
for (int col = 0; col < N; ++col) {
delete [] matrix[col];
}
// free the list of rows
delete [] matrix;
When wanting to allocate a 2D array in C++ using the new operator, you must declare a (*pointer-to-array)[N] and then allocate with new type [N][N];
For example, you can declare and allocate for your Array1 as follows:
#define N 200
struct str {
int x, y, z;
};
int main (void) {
str (*Array1)[N] = new str[N][N]; /* allocate */
/* use Array1 as 2D array */
delete [] Array1; /* free memory */
}
However, ideally, you would want to let the C++ containers library type vector handle the memory management for your. For instance you can:
#include<vector>
..
std::vector <std::vector <str>> Array1;
Then to fill Array1, fill a temporary std::vector<str> tmp; for each row (1D array) of str and then Array1.push_back(tmp); to add the filled tmp vector to your Array1. Your access can still be 2D indexing (e.g. Array1[a][b].x, Array1[a][b].y, ..., but you benefit from auto-memory management provided by the container. Much more robust and less error prone than handling the memory yourself.
Normally, you can initialize memory in heap by using 'new' operator.
Hope this can help you:
// Example program
#include <iostream>
struct str {
int x;
int y;
int z;
};
int main()
{
int N;
std::cin>>N;
str **Array1 = new str*[N]; //N can be up to 200
for (int i = 0; i < N; ++i) {
Array1[i] = new str[N];
}
// set value
for (int row = 0; row < N; ++row) {
for (int col = 0; col < N; ++col) {
Array1[row][col].x=10;
Array1[row][col].y=10;
Array1[row][col].z=10;
}
}
// get value
for (int row = 0; row < N; ++row) {
for (int col = 0; col < N; ++col) {
std::cout << Array1[row][col].x << std::endl;
std::cout << Array1[row][col].y << std::endl;
std::cout << Array1[row][col].z << std::endl;
}
}
}

getting a 2d array with out knowing the size

I'm new to using pointers and I have a problem.
I must get a 2D array of characters from the user and the user is giving me the number of rows and columns and what the array should be filled with.
int rows,col,i,j;
char **array;
int *storage;
cin >> rows >> col;
array = new *int[rows];
storage = new int[rows*col];
for (int i = 0; i < rows; ++i)
array[i] = storage + col * i;
for(i=0;i<rows;i++){
for(j=0;j<col;j++){
cin>>array[i][j];}
}
I wrote the code above for it but it doesn't work.I tried searching for such thing but I didn't find anything.
can you help me to fix the error with this code please?
Array is static so use vector instead i.e std:vector it is dynamic so that
you can enlarge the size of the vector during runtime.

How to create a two dimensional array of given size in C++

I need to create a square matrix of a given size. I know how to create a dynamic one-dimensional array of a given size. Doesn't the same work for two dimensinal arrays like the lines below?
cin>>size;
int* a[][]=new int[size][size]
int* a[][]=new int[size][size]
No, this doesn't work.
main.cpp:4: error: only the first dimension of an allocated array may have dynamic size
new int[size][size];
^~~~
If the size of the rows were fixed then you could do:
// allocate an array with `size` rows and 10 columns
int (*array)[10] = new int[size][10];
In C++ you can't have raw arrays with two dimensions where both dimensions are dynamic. This is because raw array indexing works in terms of pointers; for example, in order to access the second row a pointer to the first needs to be incremented by the size of the row. But when the size of a row is dynamic the array doesn't know that size and so C++ doesn't know how to figure out how to do the pointer increment.
If you want an array with multiple dynamic dimensions, then you need to either structure the array allocations such that C++'s default array indexing logic can handle it (such as the top answers to this duplicate question), or you need to implement the logic for figuring out the appropriate pointer increments yourself.
For an array where each row has the same size I would recommend against using multiple allocations such as those answers suggest, or using a vector of vectors. Using a vector of vectors addresses the difficulty and dangerousness of doing the allocations by hand, but it still uses more memory than necessary and doesn't allow faster memory access patterns.
A different approach, flattening the multi-dimensional array, can make for code as easy to read and write as any other approach, doesn't use extra memory, and can perform much, much better.
A flattened array means you use just a single dimentional array that has the same number of elements as your desired 2D array, and you perform arithmetic for converting between the multi-dimensional indices and the corresponding single dimensional index. With new it looks like:
int *arr = new int[row_count * column_count];
Row i, column j in the 2d array corresponds to arr[column_count*i + j]. arr[n] corresponds to the element at row n/column_count and column n% column_count. For example, in an array with 10 columns, row 0 column 0 corresponds to arr[0]; row 0, column 1 correponds to arr[1]; row 1 column 0 correponds to arr[10]; row 1, column 1 corresponds to arr[11].
You should avoid doing manual memory management using raw new and delete, such as in the case of int *arr = new int[size];. Instead resource management should be wrapped up inside a RAII class. One example of a RAII class for managing dynamically allocated memory is std::vector.
std::vector<int> arr(row_count * column_count);
arr[column_count*i + j]
You can further wrap the logic for computing indices up in another class:
#include <vector>
class Array2d {
std::vector<int> arr;
int columns;
public:
Array2d(int rows, int columns)
: arr(rows * columns)
, columns(columns)
{}
struct Array2dindex { int row; int column; };
int &operator[] (Array2dindex i) {
return arr[columns*i.row + i.column];
}
};
#include <iostream>
int main() {
int size;
std::cin >> size;
Array2d arr(size, size);
for (int i = 0; i < size; ++i) {
for (int j = 0; j < size; ++j) {
arr[{i, j}] = 100;
}
}
for (int i = 0; i < size; ++i) {
for (int j = 0; j < size; ++j) {
std::cout << arr[{i, j}] << ' ';
}
std::cout << '\n';
}
}
If you're using C++11 you can also use std::array.
const int iRows = 3, iCols = 3; // number of rows and columns
std::array<std::array<int, iCols>, iRows> matrix;
// fill with 1,2,3 4,5,6 7,8,9
for(int i=0;i<iRows;++i)
for(int j=0;j<iCols;++j)
matrix[i][j] = i * iCols + j + 1;
This class also allows for bounds checking by using the function
std::array::at
which (just like operator[]) returns a const reference if the array-object is const-qualified or a reference if it is not. Please note that
std::array
is not a variable-sized array-type, like
std::vector
You can use std::vector:
std::vector<std::vector<int*>> a(size, std::vector<int*>(size));
This will create a dynamically allocated 2D array of int* with width and height equal to size.
Or the same with new:
int*** a = new int**[size];
for (size_t i = 0; i < size; ++i)
a[i] = new int*[size];
...
for (size_t i = 0; i < size; ++i)
delete a[i];
delete a;
Note that there's no new[][] operator in C++, you just have to call new[] twice.
However, if you want to do it with new and delete instead of std::vector, you should use smart pointers instead of raw pointers, for example:
std::unique_ptr<std::unique_ptr<int*>[]> a(new std::unique_ptr<int*>[size]);
for (size_t i = 0; i < size; ++i)
a[i].reset(new int*[size]);
...
// No need to call `delete`, std::unique_ptr does it automatically.

Why do we use double pointers to reference a 2D array allocated on the heap?

So the lecture example has the following code
int **a;
a = new int*[10];
for (int i = 0; i < 10; ++i){
a[i] = new int[5];
for (int j = 0; j < 5; ++j){
a[i][j] = i*10+5;
}
}
And I have a few questions about the above code (and multidimensional arrays on the heap in general):
Do we have to initialize every element in the array as shown? Or is it suffice to cut the code after the a[i] = new int [5]?
I know with arrays allocated on the stack, it is illegal to use a variable as the stack size as
cin >> n;
int a[n];
but is it legal for heap-allocated arrays? As in, a = new int[n]?
Why is it a double pointer pointing to this array? Usually for 1D arrays, we used a single pointer as int *a = new int[10]? If I wanted the value of the array element itself, do I deference twice as **a? Or do I still do *a?
So say I have a 2D array of objects of some Class. How would I access the member field var of the ith, jth element? What if I want to invoke the member function of the object in the ith, jth element?
You don't have to initialize every element in the array. If you don't, the contents of the array will be undefined. Alternatively, you can zero-initialize with new int[5]().
a = new int[n] works on the heap because there's actually a run-time call to mark new memory for use as the data a is pointing to. It can't work on the stack because the compiler needs to know how big the stack frame is for any particular function call, so the value must be computable at compile time.
You need a double pointer because a is a pointer to a pointer to an integer. It points to an array of arrays, each of which needs to be dereferenced when accessing the value. You would typically use a[i][j] to access a specific element, which effectively double-deferences.
If the number of columns in the matrix is known at compile time, you can just allocate a matrix:
int nrow = 10; // number of rows assigned at run time
int (*a)[5]; // pointer to array of 5 ints
a = new int[nrow][5]; // allocate matrix
for (int i = 0; i < nrow; ++i) // initialize matrix
for (int j = 0; j < 5; ++j)
a[i][j] = i*nrow+j;
// ...
delete[] a;