getting a 2d array with out knowing the size - c++

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.

Related

C++, how can I make an array with length not limited to an integer?

Currently, C++ only allows declaring arrays with length as integers. Is there any way to get around it? I am trying to create a program that generates an array that can potentially reach thousands or even millions in length depending on input, but array declaration limiting to integer-only length is holding me back.
Comment Basically, supposing that I want to create a 2d array with 5 rows and 500,000 columns, I get a segmentation fault.
The prototype for std::array is
template<class T, std::size_t N> struct array;
According to https://en.cppreference.com/w/cpp/types/size_t,
std::size_t can store the maximum size of a theoretically possible
object of any type (including array). A type whose size cannot be
represented by std::size_t is ill-formed (since C++14)
(emphasis mine)
So C++, by definition, cannot express the concept of an object whose size is larger than a std::size_t.
Fortunately, on most platforms std::size_t is going to be 32 bits at a minimum, meaning it can reach not only millions but billions. And if you're on a platform where it's smaller than that then presumably your hardware isn't physically capable of storing larger objects anyway.
UPDATE: In the comments you add
Sorry, I ought to have been more specific. Basically, supposing that I
want to create a 2d array with 5 rows and 500,000 columns, I get a
segmentation fault.
If the problem here were a limitation of the language, you would get a compiler error, not a runtime error.
Since you're getting a runtime error, the problem is with your platform, not the language. In this particular case, the "problem" is that it doesn't give you enough stack space to support multi-megabyte objects in a stack frame. (This is a pretty sensible limitation, if you ask me.) Instead, you'll want to allocate your data on the heap.
I could hand you some code that would just make your problem go away for now, but what you really need to do is read about the stack and heap and understand what they are and how to use them.
#include <iostream>
int main() {
int n = 0;
std::cin >> n;
int *arr = new int[n]; // dynamic declaration of variable length array
for(int i = 0; i < n; ++i)
std::cin >> arr[i]; // read array elements
return 0;
}
EDIT: For 2d array
#include <iostream>
int main() {
int **arr;
int r, c;
std::cin >> r >> c;
// Create an array of row heads
arr = new int *[r];
// Create an 2d array
for (int i = 0; i < r; ++i) arr[i] = new int[c];
// read input in 2d array
for (int i = 0; i < r; ++i)
for (int j = 0; j < c; ++j) std::cin >> arr[i][j];
// print 2d array
for (int i = 0; i < r; ++i)
for (int j = 0; j < c; ++j) std::cout << arr[i][j] << ' ';
return 0;
}
std::vectoris a better choice. You only need push_back or emplace_backto add element into it.
More details:
http://www.cplusplus.com/reference/vector/vector/

Replace dynamic allocation with a static one

I have a project and I have to define an array of arrays of different dimensions (like a triangle) because I am not allowed to use std::vector or other container class. For this, I am using an array of pointers. Normally, I would do this:
int* triangle[n];
for(int i = 0; i < n; i++) {
triangle[i] = new int[i + 1];
for(int j = 0; j <= i; j++) cin >> triangle[i][j];
}
But I must not use dynamic memory! I thought that doing
int* triangle[n];
for(int i = 0; i < n; i++) {
int row[i + 1];
triangle[i] = row;
for(int j = 0; j <= i; j++) cin >> triangle[i][j];
}
would do the trick. But it didn't. Instead, when I iterate over the arrays and print the contents, I get garbage. So, how can I replace a dynamic allocation with a static one?
So, if you want "array of arrays" simplified, your choice is array linearization. It means that instead of 7 arrays of 10 items each you should declare single array of 70 elements. Then, just change nested indexes with a function that calculates resulting shift in linearized array, and viola!
Here you can find one of such examples: How to map the indexes of a matrix to a 1-dimensional array (C++)?
In case you don't know in advance how long is your array, it may be a tough choice to determine preliminary reservation size (for example, STL containers like vector etc. do the same trick: they allocate a chunk of memory then grow the container until free capacity left, then re-allocate bigger chunk moving the data from old to new buffer, and again, and again, and again...)
As #BeyelerStudios pointed out in the comments, at the end of the for loop, the memory allocated for the row array gets freed. When I am trying to print out the contents, I am dereferencing pointers to this freed up memory, so I am getting garbage. Thank you!

C++ passing array by value causing segment fault

Hey everyone I am relearning C++ by doing some hacker rank challenges and am getting a segment fault error. The program should take in the dimensions for the matrix and compute both diagonals, then add them together. I am pretty sure the error is in how the 2d array is passed to the computeMainDiagonal and computeSecondaryDiagonal functions. Thanks for the help !
int ComputeMatrixMainDiagonal(int matrixDimensions, int* matrix){
int rowIndent = 0;
int diagonalValue;
for(int i = 0;i < matrixDimensions;i++){
diagonalValue =+ (&matrix)[i][rowIndent];
rowIndent++;
}
return diagonalValue;
}
int ComputeMatrixSecondaryDiagonal(int matrixDimensions, int* matrix){
int rowIndent = matrixDimensions;
int diagonalValue;
for(int i = matrixDimensions;i > 0;i--){
diagonalValue =+ (&matrix)[i][rowIndent];
rowIndent--;
}
return diagonalValue;
}
int main() {
int matrixDimension;
int differenceAcrossSumsOfDiagonal;
int matrixMainDiagonal;
int matrixSecondaryDiagonal;
int * matrixPointer;
cin >> matrixDimension; //get matrix dimensions
int matrix[matrixDimension][matrixDimension]; //declare new matrix
for(int index = 0; index < matrixDimension;index++ ){ //populate matrix
for(int i = 0; i < matrixDimension;i++){
cin >> matrix[index][i];
}
}
matrixMainDiagonal = ComputeMatrixMainDiagonal(matrixDimension,&matrix[matrixDimension][matrixDimension]);
matrixSecondaryDiagonal = ComputeMatrixSecondaryDiagonal(matrixDimension,&matrix[matrixDimension][matrixDimension]);
differenceAcrossSumsOfDiagonal = (matrixMainDiagonal + matrixSecondaryDiagonal);
cout << differenceAcrossSumsOfDiagonal;
return 0;
}
Your segmentation fault likely occurs because &matrix[matrixDimension][matrixDimension] does not mean what you think it means. Your question title suggests that you think this is a way to pass the array by value (though why you would want to do so escapes me), but pass-by-value vs. pass-by-reference is a matter of how the function is declared, not of how it is called.
The expression &matrix[matrixDimension][matrixDimension] would be the address of the matrixDimensionth element of the matrixDimensionth row of the matrix. This is outside the bounds of the matrix, as the maximum index for an array is one less than the array dimension. Even if you wrote &matrix[matrixDimension - 1][matrixDimension - 1], however, it would not be what you want. You want the address of the first element of the array, which is &matrix[0][0] or simply matrix, though these are inequivalent on account of having different type (corresponding to different senses of what the elements of matrix are).

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.

Write a class using a two-dimensional dynamic array

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;
}