I was trying create a 2d array of pointers based on other. Here is a base 2d array:
double **a = new double*[3];
a[0] = new double[3]{ 1, 2, 3 };
a[1] = new double[3]{ 4, 5, 6 };
a[2] = new double[3]{ 7, 8, 9 };
And I want create a 2x2 matrix which should look like this:
5,6
8,9
Finally, I was trying resolve the problem as follow:
double **b = &a[1];
b[0] = a[1];
b[1] = a[2];
Unfortunately, this code does not work as I expect. In addition, I would like to get access to data using negative indices eg. b[-1][-1] should return 1 value.
With:
double a0[] = { 1, 2, 3 };
double a1[] = { 4, 5, 6 };
double a2[] = { 7, 8, 9 };
double* b0[3] = {&a0[1], &a1[1], &a2[1]};
double** b = &b0[1];
you can access with negative index and do:
for (int i = -1; i != 2; ++i) {
for (int j = -1; j != 2; ++j) {
std::cout << b[i][j] << std::endl;
}
}
This approach cannot work. One property of this kind of 2d array is that &A[k+1] = &A[k]+1, but that relationship does not hold between your desired B[0] and B[1], because those are actually &A[1][1] and &A[2][1], which could be miles apart.
What your code actually does is:
double **b = &a[1]; // all right, b points to part of a[]
b[0] = a[1]; // this assignment does nothing, they're already equal
b[1] = a[2]; // this assignment does nothing, they're already equal
This might help you out some and get you on the right track.
#include <conio.h>
#include <iostream>
struct Vec3 {
union {
double d3[3];
struct {
double x;
double y;
double z;
};
};
double& operator[]( int idx );
};
double& Vec3::operator[]( int idx ) {
return d3[idx];
}
typedef Vec3 Row;
struct Matrix {
union {
Row r[3];
struct {
Row row1;
Row row2;
Row row3;
};
};
Row& operator[]( int idx );
};
Row& Matrix::operator[]( int idx ) {
return r[idx];
}
int main() {
Matrix m;
m.row1.x = 1;
m.row1.y = 2;
m.row1.z = 3;
m.row2.x = 4;
m.row2.y = 5;
m.row2.z = 6;
m.row3.x = 7;
m.row3.y = 8;
m.row3.z = 9;
for ( int i = 0; i < 3; i++ ) {
for ( int j = 0; j < 3; j++ ) {
m[i][j] += 10;
std::cout << m[i][j] << " ";
}
std::cout << std::endl;
}
std::cout << "Press any key to quit" << std::endl;
_getch();
return 0;
}
I did not add any error checking or bounds checking into the overloaded operator I just allowed the user to pass any value into it. This you would have to design to your specific needs. I'm just demonstrating an easy way to create a 2D Array or a Matrix like object using unions to have quick access to the subscript or bracket operator. I show a sample use of creating a 3x3 matrix with each value ranging from 1-9 then I use a double for loop to add 10 to each value then print out the new value within the array using the double brackets. This is all done on the stack which is better then using pointers and creating new memory for each place. If you need to use the heap then you could just assign this matrix class its own pointer and create it on the heap instead of every individual element. Another thing that can be done with this is if you need to use this for say int, float or some other data type you can easily template this class or structure.
As for indexing by a negative value; I have not heard of anyone doing so. This isn't to say that it can not be done, but from what I recall on how pointers & arrays behave with indexing according to their association with memory addressing they are 0 based index. This usually means that if we have a memory block a pointer to a double type variable, this usually means that each block of memory in most cases is 8 bytes wide. The very first element resides in the very first memory address location that is assigned to this variable for both the stack and the heap. If you try to use negative numbers which involve pointer arithmetic you begin to traverse memory that doesn't belong to this declared variable. To try and pull off what you are suggesting might require more than just basic C/C++ code can do, you might have to dive into asm to get something like this to work, especially if you want to avoid using if statements within the overloaded operators.
Related
In order to get more familiar with C++, I have started working on some algebraic problems. Now, I have created an algorithm which generate a combination of numbers, with some constraints, based on an input number:
void abc(const int n) {
std::vector<int> aOut, bOut, cOut; // creating vectors to store values (dynamic int arrays)
for (int a = 9; a <= n - 2; a++) {
for (int b = a + 1; b <= n - 1; b++) {
for (int c = b + 1; c <= n; c++) {
aOut.push_back(a);
bOut.push_back(b);
cOut.push_back(c);
// std::cout << "a = " << a << " b = " << b << " c = " << c << std::endl;
}
}
}
Now, I need to continue working with these vectors, so I need to return them somehow. I have tried to create an int array of the size: int ABC[N][3], where const int N = cOut.size();. This does not work, as N is not accepted as a constant.
I also tried making a counter in the loop where I generate the vectors, which I then transferred to a string which I then transferred to a constant integer - this did not work either.
I tried making a pointer to a constant int, and using it to change the constant in the loop, which did not work either.
I even found a way to calculate the size based on my loops:
const int n = 20;
const int n1 = n - 10; // Manipulating input
const int N = n1*(n1 + 1)*(n1 + 2) / 6; // Size of vectors
And then passing the value to the function as:
void abc(const int n, const int N) { // same code as before }
But nothing works. I am honestly out of ideas (and losing my head). I have browsed trough the forum and google, but without luck. If someone could point me in the right direction, I would be forever grateful.
Of cause the solution includes changing the void to a function that returns the parameters. I added the void as I would like to check if the values were printed correctly.
How about creating an element (container) which encapsulates your 3 vectors as a return element?
The problem you're having is that functions (like Mathemematicians want to) return one value, but this can be any value :).
You could use a class or a struct which will has the vectors as attributes:
struct returnElement { // choose an adequate name
std::vector<int> aOut, bOut, cOut;
};
so now your abc function would return the returnElement struct. It could look something like this:
returnElement abc (const int n) {
returnElement ret; // creating vectors to store values (dynamic int arrays)
for (int a = 9; a <= n - 2; a++) {
for (int b = a + 1; b <= n - 1; b++) {
for (int c = b + 1; c <= n; c++) {
ret.aOut.push_back(a);
ret.bOut.push_back(b);
ret.cOut.push_back(c);
}
}
return ret;
}
Why not have an std::array of std::vector?
std::array<std::vector<int>, 3> abc(int const n)
{
std::array<std::vector<int>, 3> outArray;
for (int a = 9; a <= n - 2; a++)
{
for (int b = a + 1; b <= n - 1; b++)
{
for (int c = b + 1; c <= n; c++)
{
outArray[0].push_back(a);
outArray[1].push_back(b);
outArray[2].push_back(c);
}
}
}
return outArray;
}
To answer your question concerning array sizes,
I have tried to create an int array of the size: int ABC[N][3], where const int N = cOut.size();. This does not work, as N is not accepted as a constant.
The size of an array (whether raw or std::array) must be compile-time constant. If the size is not known at compile-time you must either create a dynamic array (using new) or use an std::vector.
If you know how large the vector is to be, you can reserve space in it for your elements, like so:
std::vector<int> yourVec;
yourVec.reserve(100); // reserve space for 100 ints
or
std::vector<int> yourVec;
yourVec.resize(100, 0); // populates yourVec with 100 ints with value 0
See Choice between vector::resize() and vector::reserve() for the differences between reserve and resize.
I'm currently trying to write a script so that I can add an item to the last index the array has an item in. For example, if I initialized an array int a[5] and a[0], a[1], a[2] all have something, then the integer would be added to a[3]Here is what I have :
int main(){
int a[5];
a[0] = 10;
a[1] = 20;
a[2] = 30;
for (int i = 0; i < 5; i++){
if (a[i] < 0){
a[i] = 40; //Just an example for what it would be like.
}
}
}
I can't help but feel that there is a better way to do this, maybe a different if condition. I want to know if there's another way to check if the next index is empty.
You could use an array index counter. Say, int counter = 0;
Use the counter as an index when you store integers to the array a, like a[counter] = 5 After you add an integer to your array, increment the counter, counter++.
This way you could make sure that the next value being added to the array is always added the way you described in the question
A few things to probably clear up what looks like a misunderstanding around what an array is:
When you declare an array say
int main()
{
int a[5];
for (int i = 0; i < 5; i++)
{
printf("a[%d] = %d", i, a[i]);
}
}
All elements in the array exist already. Namely, you can access a[0] ... a[4] without hitting an error. All values of the array have already been set implicitly and you can see this by seeing the output of the printf. Note that those are values that you haven't set yourself and will vary. If you're curious about why they vary, you can see this: Variable initialization in C++
To set those values explicitly, you can initialize all values in the array to 0 like so:
int main()
{
int a[5] = {0};
for (int i = 0; i < 5; i++)
{
printf("a[%d] = %d", i, a[i]);
}
}
or through use of a static initializer
int main()
{
int a[5] = {1, 2, 3, 4, 5};
for (int i = 0; i < 5; i++)
{
printf("a[%d] = %d", i, a[i]);
}
}
However because all values of the array already exist on creation, there isn't really such a state as "uninitialized array" in C++ as they are . The value of a[3] is either set implicitly or explicitly depending on how you created the array.
std::vector is a dynamically growing array, based on how much space you need. In order to have this effect, std::vector keeps track of how much of the array is "used" through use of a size variable. If you wanted to reimplement that to get an idea of how it might be done, you would probably want a class like:
class MyArray
{
public:
MyArray() : m_size(0)
{
}
void AddVal(int data)
{
if (m_size < 5)
{
m_array[m_size++] = data;
}
}
int GetSize()
{
return m_size;
}
private:
int m_array[5];
int m_size;
}
If you initialize the array to 0, you can check if the value is 0.
Initilize:
int array[5] = {0};
Check for 0:
array[4] == 0;
Assuming I have 2 array of different size i.e
int arr[] = {0,1,2,3,4,5,6,7,8,9};
int *arr2 = new int[5];
I want to shallow copy some of them,
Deep copy equivalent would be
int j =0;
if(!(i%2))
{
arr2[j]=arr[i];
j++;
}
Right now a print of arr2 will output : 0, 2, 4, 6 ,8
The reason I want to shallow copy is because I want arr2 to update with any changes to arr.
That is if I loop and square all the elements in arr
I want arr2 to output : 0, 4, 16, 36 ,64
These 2 arrays are part of the same class, one is my polygonal information, and the other part is data driven. arr is actually 4000+ elements in size, and arr2 is close to 3000. At the moment my algorithm works great with deep copy. but because I need to deep copy 3000 elements per update frame, i am wasting resources and was wondering if i could somehow do this via shallow copy so I don't have to have to update arr2 every frame. The way my code needs it to work, arr actually has repeated values of arr2. arr2 is a list of points that is animated. then the data is duplicated to arr which hold the positional data for vertices. this is because arr contains multiple bezier patches, some of them share one edge or more with another patch. but i want that to be ignored when animating else there are breaks in the surface.
It is important that the copy involves indices like
arr2[j]=arr[i];
because that is how my code is setup.
And that the operation be low load.
You will need an array of integer pointers for that.
int *arr2[5];
for (int i = 0, j = 0; i < 10; i++) {
if (!(i%2)) {
arr2[j]= &arr[i];
j++;
}
}
So you need to set each element of arr2 to point to corresponding element in arr by arr2[j]= &arr[i];
When you need to access element in arr2, you call some thing like: int a = *arr2[j];
Later on let say you change arr[0] to 10 arr[0] = 10; then int a = *arr2[0]; will give you 10.
As an alternative to the pointer array approach, here's a crude C++03 example of how to this programmatically. Which one is better depends on how complex the operator[] here needs to be in the real use case, and how much smaller the 2nd array is (ie. how much extra memory it needs, causing cache misses etc).
#include <iostream>
class c_array_view {
public:
c_array_view(int *array) : array_(array) {}
int& operator[](size_t index) { return array_[index*2]; }
static size_t convert_length(size_t original) { return original / 2; }
private:
int *array_;
};
int main()
{
int arr[] = {0,1,2,3,4,5,6,7,8,9};
size_t arr_len = sizeof arr / sizeof arr[0];
c_array_view arr2(arr);
size_t arr2_len = arr2.convert_length(arr_len);
for(unsigned i = 0; i < arr_len; ++i) {
std::cout << "arr: " << i << " = " << arr[i] << std::endl;
}
std::cout << std::endl;
for(unsigned j = 0; j < arr2_len; ++j) {
std::cout << "arr2: " << j << " = " << arr2[j] << std::endl;
}
std::cout << std::endl;
arr2[2] = 42;
std::cout << "modifeid arr2[2] to 42, now arr[4] = " << arr[4] << std::endl;
return 0;
}
The c_array_view could be turned into a template, a nice general purpose class which would take the mapping function as a C++11 lambda, etc, this just demonstrates the principle.
if you want squares then you should not do arr2[j]=arr[i]. The correct answer would be
arr2[j]=arr[i]*arr[i];
I am a Fortran user and do not know C++ well enough. I need to make some additions into an existing C++ code. I need to create a 2d matrix (say A) of type double whose size (say m x n) is known only during the run. With Fortran this can be done as follows
real*8, allocatable :: A(:,:)
integer :: m, n
read(*,*) m
read(*,*) n
allocate(a(m,n))
A(:,:) = 0.0d0
How do I create a matrix A(m,n), in C++, when m and n are not known at the time of compilation? I believe the operator new in C++ can be useful but not not sure how to implement it with doubles. Also, when I use following in C++
int * x;
x = new int [10];
and check the size of x using sizeof(x)/sizeof(x[0]), I do not have 10, any comments why?
To allocate dynamically a construction similar to 2D array use the following template.
#include <iostream>
int main()
{
int m, n;
std::cout << "Enter the number of rows: ";
std::cin >> m;
std::cout << "Enter the number of columns: ";
std::cin >> n;
double **a = new double * [m];
for ( int i = 0; i < m; i++ ) a[i] = new double[n]();
//...
for ( int i = 0; i < m; i++ ) delete []a[i];
delete []a;
}
Also you can use class std::vector instead of the manually allocated pointers.
#include <iostream>
#include <vector>
int main()
{
int m, n;
std::cout << "Enter the number of rows: ";
std::cin >> m;
std::cout << "Enter the number of columns: ";
std::cin >> n;
std::vector<std::vector<double>> v( m, std::vector<double>( n ) );
//...
}
As for this code snippet
int * x;
x = new int [10];
then x has type int * and x[0] has type int. So if the size of the pointer is equal to 4 and the size of an object of type int is equal also to 4 then sizeof( x ) / sizeof( x[0] ) will yields 1. Pointers do not keep the information whether they point to only a single object or the first object pf some sequence of objects.
I would recommend using std::vector and avoid all the headache of manually allocating and deallocating memory.
Here's an example program:
#include <iostream>
#include <vector>
typedef std::vector<double> Row;
typedef std::vector<Row> Matrix;
void testMatrix(int M, int N)
{
// Create a row with all elements set to 0.0
Row row(N, 0.0);
// Create a matrix with all elements set to 0.0
Matrix matrix(M, row);
// Test accessing the matrix.
for ( int i = 0; i < M; ++i )
{
for ( int j = 0; j < N; ++j )
{
matrix[i][j] = i+j;
std::cout << matrix[i][j] << " ";
}
std::cout << std::endl;
}
}
int main()
{
testMatrix(10, 20);
}
The formal C++ way of doing it would be this:
std::vector<std::vector<int>> a;
This creates container which contains a zero size set of sub-containers. C++11/C++13 provide std::array for fixed-sized containers, but you specified runtime sizing.
We now have to impart our dimensions on this and, unfortunately. Lets assign the top-level:
a.resize(10);
(you can also push or insert elements)
What we now have is a vector of 10 vectors. Unfortunately, they are all independent, so you would need to:
for (size_t i = 0; i < a.size(); ++i) {
a[i].resize(10);
}
We now have a 10x10. We can also use vectors constructor:
std::vector<std::vector<int>> a(xSize, std::vector<int>(ySize)); // assuming you want a[x][y]
Note that vectors are fully dynamic, so we can resize elements as we need:
a[1].push_back(10); // push value '10' onto a[1], creating an 11th element in a[1]
a[2].erase(2); // remove element 2 from a[2], reducing a[2]s size to 9
To get the size of a particular slot:
a.size(); // returns 10
a[1].size(); // returns 11 after the above
a[2].size(); // returns 9 after teh above.
Unfortunately C++ doesn't provide a strong, first-class way to allocate an array that retains size information. But you can always create a simple C-style array on the stack:
int a[10][10];
std::cout << "sizeof a is " << sizeof(a) <<'\n';
But using an allocator, that is placing the data onto the heap, requires /you/ to track size.
int* pointer = new int[10];
At this point, "pointer" is a numeric value, zero to indicate not enough memory was available or the location in memory where the first of your 10 consecutive integer storage spaces are located.
The use of the pointer decorator syntax tells the compiler that this integer value will be used as a pointer to store addresses and so allow pointer operations via the variable.
The important thing here is that all we have is an address, and the original C standard didn't specify how the memory allocator would track size information, and so there is no way to retrieve the size information. (OK, technically there is, but it requires using compiler/os/implementation specific information that is subject to frequent change)
These integers must be treated as a single object when interfacing with the memory allocation system -- you can't, for example:
delete pointer + 5;
to delete the 5th integer. They are a single allocation unit; this notion allows the system to track blocks rather than individual elements.
To delete an array, the C++ syntax is
delete[] pointer;
To allocate a 2-dimensional array, you will need to either:
Flatten the array and handle sizing/offsets yourself:
static const size_t x = 10, y = 10;
int* pointer = new int[x * y];
pointer[0] = 0; // position 0, the 1st element.
pointer[x * 1] = 0; // pointer[1][0]
or you could use
int access_2d_array_element(int* pointer, const size_t xSize, const size_t ySize, size_t x, size_t y)
{
assert(x < xSize && y < ySize);
return pointer[y * xSize + x];
}
That's kind of a pain, so you would probably be steered towards encapsulation:
class Array2D
{
int* m_pointer;
const size_t m_xSize, m_ySize;
public:
Array2D(size_t xSize, size_t ySize)
: m_pointer(new int[xSize * ySize])
, m_xSize(xSize)
, m_ySize(ySize)
{}
int& at(size_t x, size_t y)
{
assert(x < m_xSize && y < m_ySize);
return m_pointer[y * m_xSize + x];
}
// total number of elements.
size_t arrsizeof() const
{
return m_xSize * m_ySize;
}
// total size of all data elements.
size_t sizeof() const
{
// this sizeof syntax makes the code more generic.
return arrsizeof() * sizeof(*m_pointer);
}
~Array2D()
{
delete[] m_pointer;
}
};
Array2D a(10, 10);
a.at(1, 3) = 13;
int x = a.at(1, 3);
Or,
For each Nth dimension (N < dimensions) allocate an array of pointers-to-pointers, only allocating actual ints for the final dimension.
const size_t xSize = 10, ySize = 10;
int* pointer = new int*(x); // the first level of indirection.
for (size_t i = 0; i < x; ++i) {
pointer[i] = new int(y);
}
pointer[0][0] = 0;
for (size_t i = 0; i < x; ++i) {
delete[] pointer[i];
}
delete[] pointer;
This last is more-or-less doing the same work, it just creates more memory fragmentation than the former.
-----------EDIT-----------
To answer the question "why do I not have 10" you're probably compiling in 64-bit mode, which means that "x" is an array of 10 pointers-to-int, and because you're in 64-bit mode, pointers are 64-bits long, while ints are 32 bits.
The C++ equivalent of your Fortran code is:
int cols, rows;
if ( !(std::cin >> cols >> rows) )
// error handling...
std::vector<double> A(cols * rows);
To access an element of this array you would need to write A[r * rows + c] (or you could do it in a column-major fashion, that's up to you).
The element access is a bit clunky, so you could write a class that wraps up holding this vector and provides a 2-D accessor method.
In fact your best bet is to find a free library that already does this, instead of reinventing the wheel. There isn't a standard Matrix class in C++, because somebody would always want a different option (e.g. some would want row-major storage, some column-major, particular operations provided, etc. etc.)
Someone suggested boost::multi_array; that stores all its data contiguously in row-major order and is probably suitable. If you want standard matrix operations consider something like Eigen, again there are a lot of alternatives out there.
If you want to roll your own then it could look like:
struct FortranArray2D // actually easily extensible to any number of dimensions
{
FortranArray2D(size_t n_cols, size_t n_rows)
: n_cols(n_cols), n_rows(n_rows), content(n_cols * n_rows) { }
double &operator()(size_t col, size_t row)
{ return content.at(row * n_rows + col); }
void resize(size_t new_cols, size_t new_rows)
{
FortranArray2D temp(new_cols, new_rows);
// insert some logic to move values from old to new...
*this = std::move(temp);
}
private:
size_t n_rows, n_cols;
std::vector<double> content;
};
Note in particular that by avoiding new you avoid the thousand and one headaches that come with manual memory management. Your class is copyable and movable by default. You could add further methods to replicate any functionality that the Fortran array has which you need.
int ** x;
x = new int* [10];
for(int i = 0; i < 10; i++)
x[i] = new int[5];
Unfortunately you'll have to store the size of matrix somewhere else.
C/C++ won't do it for you. sizeof() works only when compiler knows the size, which is not true in dynamic arrays.
And if you wan to achieve it with something more safe than dynamic arrays:
#include <vector>
// ...
std::vector<std::vector<int>> vect(10, std::vector<int>(5));
vect[3][2] = 1;
What is the accepted/most commonly used way to manipulate dynamic (with all dimensions not known until runtime) multi-dimensional arrays in C and/or C++.
I'm trying to find the cleanest way to accomplish what this Java code does:
public static void main(String[] args){
Scanner sc=new Scanner(System.in);
int rows=sc.nextInt();
int cols=sc.nextInt();
int[][] data=new int[rows][cols];
manipulate(data);
}
public static void manipulate(int[][] data){
for(int i=0;i<data.length;i++)
for(int j=0;j<data[0].length.j++){
System.out.print(data[i][j]);
}
}
(reads from std_in just to clarify that dimensions aren't known until runtime).
Edit:I noticed that this question is pretty popular even though it's pretty old. I don't actually agree with the top voted answer. I think the best choice for C is to use a single-dimensional array as Guge said below "You can alloc rowscolssizeof(int) and access it by table[row*cols+col].".
There is a number of choices with C++, if you really like boost or stl then the answers below might be preferable, but the simplest and probably fastest choice is to use a single dimensional array as in C.
Another viable choice in C and C++ if you want the [][] syntax is lillq's answer down at the bottom is manually building the array with lots of malloc's.
Use boost::multi_array.
As in your example, the only thing you need to know at compile time is the number of dimensions. Here is the first example in the documentation :
#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;
}
Edit: As suggested in the comments, here is a "simple" example application that let you define the multi-dimensional array size at runtime, asking from the console input.
Here is an example output of this example application (compiled with the constant saying it's 3 dimensions) :
Multi-Array test!
Please enter the size of the dimension 0 : 4
Please enter the size of the dimension 1 : 6
Please enter the size of the dimension 2 : 2
Text matrix with 3 dimensions of size (4,6,2) have been created.
Ready!
Type 'help' for the command list.
>read 0.0.0
Text at (0,0,0) :
""
>write 0.0.0 "This is a nice test!"
Text "This is a nice test!" written at position (0,0,0)
>read 0.0.0
Text at (0,0,0) :
"This is a nice test!"
>write 0,0,1 "What a nice day!"
Text "What a nice day!" written at position (0,0,1)
>read 0.0.0
Text at (0,0,0) :
"This is a nice test!"
>read 0.0.1
Text at (0,0,1) :
"What a nice day!"
>write 3,5,1 "This is the last text!"
Text "This is the last text!" written at position (3,5,1)
>read 3,5,1
Text at (3,5,1) :
"This is the last text!"
>exit
The important parts in the code are the main function where we get the dimensions from the user and create the array with :
const unsigned int DIMENSION_COUNT = 3; // dimension count for this test application, change it at will :)
// here is the type of the multi-dimensional (DIMENSION_COUNT dimensions here) array we want to use
// for this example, it own texts
typedef boost::multi_array< std::string , DIMENSION_COUNT > TextMatrix;
// this provide size/index based position for a TextMatrix entry.
typedef std::tr1::array<TextMatrix::index, DIMENSION_COUNT> Position; // note that it can be a boost::array or a simple array
/* This function will allow the user to manipulate the created array
by managing it's commands.
Returns true if the exit command have been called.
*/
bool process_command( const std::string& entry, TextMatrix& text_matrix );
/* Print the position values in the standard output. */
void display_position( const Position& position );
int main()
{
std::cout << "Multi-Array test!" << std::endl;
// get the dimension informations from the user
Position dimensions; // this array will hold the size of each dimension
for( int dimension_idx = 0; dimension_idx < DIMENSION_COUNT; ++dimension_idx )
{
std::cout << "Please enter the size of the dimension "<< dimension_idx <<" : ";
// note that here we should check the type of the entry, but it's a simple example so lets assume we take good numbers
std::cin >> dimensions[dimension_idx];
std::cout << std::endl;
}
// now create the multi-dimensional array with the previously collected informations
TextMatrix text_matrix( dimensions );
std::cout << "Text matrix with " << DIMENSION_COUNT << " dimensions of size ";
display_position( dimensions );
std::cout << " have been created."<< std::endl;
std::cout << std::endl;
std::cout << "Ready!" << std::endl;
std::cout << "Type 'help' for the command list." << std::endl;
std::cin.sync();
// we can now play with it as long as we want
bool wants_to_exit = false;
while( !wants_to_exit )
{
std::cout << std::endl << ">" ;
std::tr1::array< char, 256 > entry_buffer;
std::cin.getline(entry_buffer.data(), entry_buffer.size());
const std::string entry( entry_buffer.data() );
wants_to_exit = process_command( entry, text_matrix );
}
return 0;
}
And you can see that to accede an element in the array, it's really easy : you just use the operator() as in the following functions :
void write_in_text_matrix( TextMatrix& text_matrix, const Position& position, const std::string& text )
{
text_matrix( position ) = text;
std::cout << "Text \"" << text << "\" written at position ";
display_position( position );
std::cout << std::endl;
}
void read_from_text_matrix( const TextMatrix& text_matrix, const Position& position )
{
const std::string& text = text_matrix( position );
std::cout << "Text at ";
display_position(position);
std::cout << " : "<< std::endl;
std::cout << " \"" << text << "\"" << std::endl;
}
Note : I compiled this application in VC9 + SP1 - got just some forgettable warnings.
There are two ways to represent a 2-dimension array in C++. One being more flexible than the other.
Array of arrays
First make an array of pointers, then initialize each pointer with another array.
// First dimension
int** array = new int*[3];
for( int i = 0; i < 3; ++i )
{
// Second dimension
array[i] = new int[4];
}
// You can then access your array data with
for( int i = 0; i < 3; ++i )
{
for( int j = 0; j < 4; ++j )
{
std::cout << array[i][j];
}
}
THe problem with this method is that your second dimension is allocated as many arrays, so does not ease the work of the memory allocator. Your memory is likely to be fragmented resulting in poorer performance. It provides more flexibility though since each array in the second dimension could have a different size.
Big array to hold all values
The trick here is to create a massive array to hold every data you need. The hard part is that you still need the first array of pointers if you want to be able to access the data using the array[i][j] syntax.
int* buffer = new int[3*4];
int** array = new int*[3];
for( int i = 0; i < 3; ++i )
{
array[i] = array + i * 4;
}
The int* array is not mandatory as you could access your data directly in buffer by computing the index in the buffer from the 2-dimension coordinates of the value.
// You can then access your array data with
for( int i = 0; i < 3; ++i )
{
for( int j = 0; j < 4; ++j )
{
const int index = i * 4 + j;
std::cout << buffer[index];
}
}
The RULE to keep in mind
Computer memory is linear and will still be for a long time. Keep in mind that 2-dimension arrays are not natively supported on a computer so the only way is to "linearize" the array into a 1-dimension array.
You can alloc rowscolssizeof(int) and access it by table[row*cols+col].
Here is the easy way to do this in C:
void manipulate(int rows, int cols, int (*data)[cols]) {
for(int i=0; i < rows; i++) {
for(int j=0; j < cols; j++) {
printf("%d ", data[i][j]);
}
printf("\n");
}
}
int main() {
int rows = ...;
int cols = ...;
int (*data)[cols] = malloc(rows*sizeof(*data));
manipulate(rows, cols, data);
free(data);
}
This is perfectly valid since C99, however it is not C++ of any standard: C++ requires the sizes of array types to be compile times constants. In that respect, C++ is now fifteen years behind C. And this situation is not going to change any time soon (the variable length array proposal for C++17 does not come close to the functionality of C99 variable length arrays).
The standard way without using boost is to use std::vector :
std::vector< std::vector<int> > v;
v.resize(rows, std::vector<int>(cols, 42)); // init value is 42
v[row][col] = ...;
That will take care of new / delete the memory you need automatically. But it's rather slow, since std::vector is not primarily designed for using it like that (nesting std::vector into each other). For example, all the memory is not allocated in one block, but separate for each column. Also the rows don't have to be all of the same width. Faster is using a normal vector, and then doing index calculation like col_count * row + col to get at a certain row and col:
std::vector<int> v(col_count * row_count, 42);
v[col_count * row + col) = ...;
But this will loose the capability to index the vector using [x][y]. You also have to store the amount of rows and cols somewhere, while using the nested solution you can get the amount of rows using v.size() and the amount of cols using v[0].size().
Using boost, you can use boost::multi_array, which does exactly what you want (see the other answer).
There is also the raw way using native C++ arrays. This envolves quite some work and is in no way better than the nested vector solution:
int ** rows = new int*[row_count];
for(std::size_t i = 0; i < row_count; i++) {
rows[i] = new int[cols_count];
std::fill(rows[i], rows[i] + cols_count, 42);
}
// use it... rows[row][col] then free it...
for(std::size_t i = 0; i < row_count; i++) {
delete[] rows[i];
}
delete[] rows;
You have to store the amount of columns and rows you created somewhere since you can't receive them from the pointer.
2D C-style arrays in C and C++ are a block of memory of size rows * columns * sizeof(datatype) bytes.
The actual [row][column] dimensions exist only statically at compile time. There's nothing there dynamically at runtime!
So, as others have mentioned, you can implement
int array [ rows ] [ columns ];
As:
int array [ rows * columns ]
Or as:
int * array = malloc ( rows * columns * sizeof(int) );
Next: Declaring a variably sized array. In C this is possible:
int main( int argc, char ** argv )
{
assert( argc > 2 );
int rows = atoi( argv[1] );
int columns = atoi( argv[2] );
assert(rows > 0 && columns > 0);
int data [ rows ] [ columns ]; // Yes, legal!
memset( &data, 0, sizeof(data) );
print( rows, columns, data );
manipulate( rows, columns, data );
print( rows, columns, data );
}
In C you can just pass the variably-sized array around the same as a non-variably-sized array:
void manipulate( int theRows, int theColumns, int theData[theRows][theColumns] )
{
for ( int r = 0; r < theRows; r ++ )
for ( int c = 0; c < theColumns; c ++ )
theData[r][c] = r*10 + c;
}
However, in C++ that is not possible. You need to allocate the array using dynamic allocation, e.g.:
int *array = new int[rows * cols]();
or preferably (with automated memory management)
std::vector<int> array(rows * cols);
Then the functions must be modified to accept 1-dimensional data:
void manipulate( int theRows, int theColumns, int *theData )
{
for ( int r = 0; r < theRows; r ++ )
for ( int c = 0; c < theColumns; c ++ )
theData[r * theColumns + c] = r*10 + c;
}
If you're using C instead of C++ you might want to look at the Array_T abstraction in Dave Hanson's library C Interfaces and Implementations. It's exceptionally clean and well designed. I have my students do a two-dimensional version as an exercise. You could do that or simply write an additional function that does an index mapping, e.g.,
void *Array_get_2d(Array_T a, int width, int height, int i, int j) {
return Array_get(a, j * width, i, j);
}
It is a bit cleaner to have a separate structure where you store the width, the height, and a pointer to the elements.
I recently came across a similar problem. I did not have Boost available. Vectors of vectors turned out to be pretty slow in comparison to plain arrays. Having an array of pointers makes the initialization a lot more laborious, because you have to iterate through every dimension and initialize the pointers, possibly having some pretty unwieldy, cascaded types in the process, possibly with lots of typedefs.
DISCLAIMER: I was not sure if I should post this as an answer, because it only answers part of your question. My apologies for the following:
I did not cover how to read the dimensions from standard input, as other commentators had remarked.
This is primarily for C++.
I have only coded this solution for two dimensions.
I decided to post this anyway, because I see vectors of vectors brought up frequently in reply to questions about multi-dimensional arrays in C++, without anyone mentioning the performance aspects of it (if you care about it).
I also interpreted the core issue of this question to be about how to get dynamic multi-dimensional arrays that can be used with the same ease as the Java example from the question, i.e. without the hassle of having to calculate the indices with a pseudo-multi-dimensional one-dimensional array.
I didn't see compiler extensions mentioned in the other answers, like the ones provided by GCC/G++ to declare multi-dimensional arrays with dynamic bounds the same way you do with static bounds. From what I understand, the question does not restrict the answers to standard C/C++. ISO C99 apparently does support them, but in C++ and prior versions of C they appear to be compiler-specific extensions. See this question: Dynamic arrays in C without malloc?
I came up with a way that people might like for C++, because it's little code, has the ease of use of the built-in static multi-dimensional arrays, and is just as fast.
template <typename T>
class Array2D {
private:
std::unique_ptr<T> managed_array_;
T* array_;
size_t x_, y_;
public:
Array2D(size_t x, size_t y) {
managed_array_.reset(new T[x * y]);
array_ = managed_array_.get();
y_ = y;
}
T* operator[](size_t x) const {
return &array_[x * y_];
}
};
You can use it like this. The dimensions do not
auto a = Array2D<int>(x, y);
a[xi][yi] = 42;
You can add an assertion, at least to all but the last dimension and extend the idea to to more than two dimensions. I have made a post on my blog about alternative ways to get multi-dimensional arrays. I am also much more specific on the relative performance and coding effort there.
Performance of Dynamic Multi-Dimensional Arrays in C++
You could use malloc to accomplish this and still have it accessible through normal array[][] mean, verses the array[rows * cols + cols] method.
main()
{
int i;
int rows;
int cols;
int **array = NULL;
array = malloc(sizeof(int*) * rows);
if (array == NULL)
return 0; // check for malloc fail
for (i = 0; i < rows; i++)
{
array[i] = malloc(sizeof(int) * cols)
if (array[i] == NULL)
return 0; // check for malloc fail
}
// and now you have a dynamically sized array
}
There is no way to determine the length of a given array in C++. The best way would probably be to pass in the length of each dimension of the array, and use that instead of the .length property of the array itself.