How do I point to multi-dimensional array values? - c++

I need some help on multi-dimensional arrays... I cannot find out how to assign a value to an array in a void task, that was created in main.
i tried to find help all over the place, but the longer i keep reading the less i understand
Please help
void addValue(a,b)
{
//somehow assign value to a[2][6] using pointers and such
void main()
{
int dest[7][7] = { 0 };
int a = 2;
int b = 6;
addValue(a,b);
}

Like this:
void addValue( int (*dest)[7], int a, int b )
{
dest[2][6] = 12;
}
int main()
{
int dest[7][7] = { 0 };
addValue(dest, a, b);
}
Consider using std::array instead of C-style arrays; the latter are an anachronism in C++. You can make the 7 a template parameter in addValue if you want to support other dimensions of array.

Related

c++ error "Braces around scalar initializer for type int*"

Error: braces around scalar initializer for type int*
I'm trying to pass an array to the function but I keep getting this error in the initialization step.
How can I fix this?
#include <iostream>
using namespace std;
void func (int *p[4]);
int main()
{
int *p[4]={ {1,4,5},{3,5,6},{6,6,2},{6,5,3}}; //The error appears here
func(p);
return 0;
}
void func (int *p[4])
{
for(int i=0;i<4;i++)
{
for(int j=0;j<1;j++)
{ cout<<p[i][j]; }
}
cout<<" \t";
}
Problem is what is p.
Whit this definition:
int *p[4];
this is 4 element array of pointers to int.
I guessing you wanted this:
int (*p)[3];
pointer to 3 element array of ints.
Also to use initialization you need an array.
Here is working example.
The variable p is an array of pointers. { 1, 4, 5 } is not a pointer.
You need to make p an array of arrays:
int p[4][3] = { ... };
Because of that change, you have to change the func function argument as well, as p will now decay to a pointer to an array, of type int (*)[3] (that is, the argument for func should be int (*p)[3]).
This would work, however you are going to lose array information because they will decay into pointers:
int arr1[] = { 1,4,5 };
int arr2[] = { 3,5,6 };
int arr3[] = { 6,6,2 };
int arr4[] = { 6,5,3 };
int *p[4] = { arr1, arr2, arr3, arr4 };

Organising C++ code

I am looking for some advice on how to organise my C++ code.
I have an int array, side, that I would like to be static in the sense that its value is kept constant between calls. This is because my function foo(), will modify the array side recursively and so I don't want copies to be made of side. Furthermore, the size of side can only be determined at compile time from the size of a vector that is passed into the function bar().
I have thought of the following structure to layout such a problem.
I keep a global int pointer, side, which I can then use to point to the address of my int array and then use the pointer *side within foo to do my modifications.
Please can you give me advise on the layout and organisation of this code? I am quite new to C++ so would appreciate any advice on the below structure.
#include <iostream>
#include <vector>
using namespace std;
int *side;
class A {
public:
int foo(bool);
int bar(vector<int>);
void set_n(int n){ class_n = n;};
private:
int class_n;
};
int A::foo(bool fl)
{
int n = class_n;
for(int i = 0; i < n; i++) {
// modify side[] and then recursively call foo
}
return 0;
}
int A::bar(vector<int> t)
{
int size = t.size();
set_n(size);
int a = foo(true);
int *side_local = new int[size];
for(int i = 0; i < size; i++) {
side_local[i] = 0;
}
side = side_local;
return 0;
}
int main()
{
A a;
vector<int> t = {1, 2, 3};
a.bar(t);
return 0;
}
A recursive call can pass a pointer to itself:
void foo(int *pList)
{
foo(pList); // recursive
}
the same list is then being worked on.
That being said, since foo is inside a class you wouldn't need a global either, but a member variable.
class A
{
int *pMemberList;
...
void foo();
}
now foo can see pMemberList all the time.
BUT ... passing it is probably a better option as in the future your class might house 2 lists that you want to do foo on.

Multi-dimensional array

I need to create a function that has a parameter which is a multi-dimensional array with two dimensions being user-specified, e.g.
int function(int a, int b, int array[a][b])
{
...
}
How would I do that in C++ ?
Are the dimensions known at compile-time? In that case, turn them into template parameters and pass the array by reference:
template<int a, int b>
int function(int(&array)[a][b])
{
...
}
Example client code:
int x[3][7];
function(x);
int y[6][2];
function(y);
Assuming the dimensions are not known at compile time, you emulate a two dimensional array with a one dimensional array:
int& getat(int x, int y, int r, int c, int *array) {return array[y*c+x];}
int function(int a, int b, int *array) {
getat(4, 2, a, b, array) = 32; //array[4,2] = 32
}
or, for safety, wrap it all in a class:
template <class T>
class array2d {
std::vector<T> data;
unsigned cols, rows;
public:
array2d() : data(), cols(0), rows(0) {}
array2d(unsigned c, unsigned r) : data(c*r), cols(c), rows(r) {}
T& operator()(unsigned c, unsigned r) {
assert(c<cols&&r<rows);
return data[r*cols+c];
}
};
or, best yet, use Boost's Multidimensional Array, which will be better than anything mere mortals could write.
I'm not sure if this work, because your question and code are not the same, according to your code the function can have 3 parameters, so this would work:
int function(int a, int b, int** &array)
{
array = new int*[a];
for (int i =0;i<a;i++)
array[i] = new int[b];
// I don't know why you are returning int, probably doing something here....
}
However your question says that your function can take only one parameter, so:
if the dimensions are known at compile time, then Fred's Answer is the best (it charmed me in fact! :) ).
if not, I can't see any possible solution that allows passing more than one user-specified value other than encapsulating all these values in one object.
Like this:
class Foo {
public:
Foo(int d1, int d2)
{ a = d1; b = d2; }
int a,b;
int** array;
};
int function(Foo &f)
{
f.array = new int*[f.a];
for (int i = 0;i<f.a;i++)
f.array[i] = new int[f.b];
// I don't know why you are returning int, probably doing something here....
}
Though I find it a bad idea, in fact the function could be a parameterless method instead:
class Foo {
public:
Foo(int d1, int d2)
{ a = d1; b = d2; }
void Create() // Or could do this right in the Constructor
{
array = new int*[a];
for (int i = 0;i<a;i++)
array[i] = new int[b];
}
private:
int a,b;
int** array;
};
Still this is a bad idea, because you are reinventing the wheel, as there are a perfect class in the STL to do all the work for you:
vector< vector<int> > v; // Now v is a 2D array

Create an array of an array of structs?

this question is regarding the syntax of an array of array of structs.
I have a struct that takes in two ints:
struct point
{
int x, y;
};
I have created another struct that takes in 8 of these structs:
//Creating an Array of Array of structs
struct Arraypoint
{
point variable[8];
};
//Not sure if this is the correct way to do it.
Now, in main, I want to declare an array variable of type Arraypoint with 8 indices, so effectively I will have 8 * 8 = 64 elements of struct point and 128 ints (64 x and 64 y).
Also, how would I access an individual element struct point from the array Arraypoint?
Okay after having declared in main lets say Arraypoint is 2.
Arraypoint arr[2];
How do I initialize the elements without having to type in arr[0].variable[0].x = ... or without using for loops.
Why can't I do the following, it doesn't seem to work.
Arraypoint arr[2] = { {(x,y),(x,y),(x,y),(x,y),(x,y),(x,y),(x,y),(x,y)},
{(x,y),(x,y),(x,y),(x,y),(x,y),(x,y),(x,y),(x,y)} }//xy are rand
I have used curly braces in my code, the error returned is missing braces around initializer for type point and too many initializers for type Arraypoint.
In C++, you'd just write:
Arraypoint arr[8];
An individual point could then be accessed via:
arr[i].variable[j];
More practically, though, you'd probably be better off using e.g.
std::vector<std::vector<point> >
or writing your own class with an overloaded operator(int i, int j). For example:
class PointMatrix
{
private:
std::vector<point> m_points;
public:
PointMatrix() : m_points(64) {}
point& operator()(int i, int j) { return m_points[8 * i + j]; }
const point& operator()(int i, int j) const { return m_points[8 * i + j]; }
};
PointMatrix mat;
m(3, 4).x = 23;
got it: ideone.com/ix3hC. Arraypoint::variable has to have it's own { } pair.
struct point
{
int x, y;
};
#define P {0, 0}
struct Arraypoint
{
point variable[8];
};
#define V { P, P, P, P, P, P, P, P}
#define AP { V } //this is the pair you missed
int main() {
Arraypoint arr[2] = { AP, AP };
}
struct Arraypoint arraypoints[8];
is what you're after, I think. To use them:
int firstx = arraypoints[0].variable[0].x;
This isn't so pretty though
struct point { int x, y; };
struct point[8][8] arraypoints;
Is probably better? Don't know what exactly you're after though.
To create an array of Arraypoints, you can do:
Arraypoint arr[8];
To access an element:
arr[i]
will return the i'th Arraypoint element
arr[i].variable[j]
will return the j'th point in the element
arr[i].variable[j].x
will return the x coordinate of that point.
So I realized why I couldn't declare my array as such,
Arraypoint arr[2] = { {(x,y),(x,y),(x,y),(x,y),(x,y),(x,y),(x,y),(x,y)},
{(x,y),(x,y),(x,y),(x,y),(x,y),(x,y),(x,y),(x,y)} }
//xy are randomn integer values
its because in my struct declaration of Arraypoint, it takes in 8 elements of type point. So
I have to create variables of type point to store(x,y) and then i could store this variable in Array point.
point point1 = {x,y}, ...;
Arraypoint arr[2] = { {point1,point2,point3,point4,point5,....} };
Just for anyone in the future who stumbles across the same problem.

beginner question about arrays in structs in C++

I would like to create a struct and use it inside an other struct as an array. My problem is that I don't know how big array I would like to allocate, I will only know once I am in a function. I mean I would like to use [] instead of a pre-determined constant, like 10000.
I think if you look at my code it would be self-explanatory. Can you help me how to make this code work? Moreover it would help me a lot if you could tell me what is the name of the topic I am asking about (is it dynamic arrays?) and that where can I find articles/tutorials about this topic.
Here is the code with my broken way of thinking about arrays in structs.
#include <iostream>
using namespace std;
struct keyframe {
bool a;
int b;
int c;
};
struct keyframe_file {
const int num_views;
const int num_keyframes;
keyframe keyframes[];
};
int main() {
keyframe_file my_file;
my_file.num_views = 1;
my_file.num_keyframes = 6;
my_file.keyframes = new keyframe[my_file.num_keyframes];
my_file.keyframes[0].a = true;
my_file.keyframes[0].b = 5;
my_file.keyframes[0].c = 9;
return 0;
}
Use a std::vector.
struct keyframe_file {
const int num_views;
const int num_keyframes;
std::vector<keyframe> keyframes;
};
int main() {
keyframe_file frame;
frame.keyframes.resize(...);
}
If it suits your purpose, an STL container (std::vector) is easily one of the best options - the less memory management you have to worry about, the better.
In any case, look at the struct definition Nawaz posted above - that's exactly how it should be. Dynamic arrays in C++ are simply pointers. You have, however, allocated the memory properly in your code, but you haven't freed it (so it's leaking). Since you allocated with new [] you will need to
delete [] my_file.keyframes;
in order to free the memory properly.
Resizing is another issue: with a smart implementation, array resizing can be an amortized O(1) operation which is nice. When you resize, it will always take you O(n) since you need to copy all the elements into a new array of different size, but if you do it half as much, it becomes O(1). That is, double the array each time you need to resize. Here is a very quick example
void resize()
{
if(numOfElementsInArray == sizeOfArray)
{
ArrayType * arr = new ArrayType[sizeOfArray*2]; // Allocate a double size array
for(int i=0;i<sizeOfArray;++i)
currentArray[i] = arr[i];
delete [] currentArray; // Free memory in old array
currentArray = arr; // Set the array to our new one
sizeOfArray *= 2; // Double the size
}
}
NOTE: The example above does not take into account space complexity; that said, if you have 5000 elements, and remove all but 5, this method with not shrink it (which is probably what you will want to do for all practical purposes)
Your code appears to be almost correct, except for two things:
keyframes needs to be a keyframe* rather than a keyframe[]
You forgot to delete the memory you allocated
That is incomplete type. In C++, array must be provided with size, and the size must be known at compile time itself.
You're using new, with which you should be using pointer.
struct keyframe_file {
const int num_views;
const int num_keyframes;
keyframe *keyframes;
};
But std::vector<keyframe> is still a better choice, as #DeadMG already suggested.
By the way, the first two members are const in the struct, that means, they cannot be assigned value, as you're doing in your code. They must be initialized with values you want them to hold. That implies, now with vector, you've to include a constructor, to initialize the struct, as the struct is no more a POD.
struct keyframe_file {
const int num_views; //const member
const int num_keyframes; //const member
std::vector<keyframe> keyframes;
keyframe_file(int nviews, int nkeyframes)
: num_views(nviews), num_keyframes(nkeyframes), keyframes(nkeyframes){}
};
keyframe_file my_file(1,6); //done!
The suggested "Vector" is they safest way to do it.
But if it is only about making your code work (without resizing and stuff) the following should be working:
#include <iostream>
using namespace std;
struct keyframe {
bool a;
int b;
int c;
};
struct keyframe_file {
const int num_views;
const int num_keyframes;
keyframe* keyframes;
};
int main()
{
keyframe_file my_file = {1, 6}; // initialization needed bcause of 'const int'
my_file.keyframes = new keyframe[my_file.num_keyframes];
for (int i = 0; i < my_file.num_keyframes; i++)
{
my_file.keyframes[i].a = true;
my_file.keyframes[i].b = 5 + i;
my_file.keyframes[i].c = 9 - i;
}
return 0;
}
somewhere in your code, when you are done using the array you have to call delete [] my_file.keyframes; as already mentioned.
There's a basic rule when using dynamic arrays in c++, especially when using it inside structs or classes, and it's to delete what you no longer need.
If you want to make your struct dynamic, it's easy, just replace the [] with * and the array will become dynamic, but it's not over yet, there is a lot of work.
You have to construct the array and destory it, and destoroying it is possible and useful noly with destructors, like this:
struct keyframe_file
{
const int num_views;
const int num_keyframes;
keyframe* keyframes;
~keyframe_file() // this is the destructor
{
delete[] keyframes;
}
};
Yet even that code isn't going to work at all, since you are assigning values to constants in variable my_file after creating it, it's illegal in c++, you should then use classes instead.
Using classes with dynamic arrays is very easy and interesting and makes your code very good, you don't have to know too much to do that, just learn what is a constructor, an initializer, destructor, private and public and go on with the following code:
#include <iostream>
using namespace std;
struct keyframe
{
bool a;
int b,c;
};
class keyframe_file
{
public:
keyframe_file(int NV, int NKF):num_keyframes(NKF),num_views(NV)
{
keyframes = new keyframe[num_keyframes];
}
~keyframe_file()
{
delete[] keyframes;
}
private:
const int num_views;
const int num_keyframes;
keyframe* keyframes;
};
int main()
{
keyframe_file my_file(1,6);
return 0;
}
This code works very well, it allows you to assign value to the constants num_views and num_keyframes for one time when creating the object (variable) my_file.
Remember, you are a C++ programmer, be proud of that, and use classes instead of structs and dynamic arrays instead of static ones.
Hope that's useful.
Use pointers and apply to your structure!
int *p;
p = new int;
#include <iostream>
using namespace std;
struct keyframe {
bool a;
int b;
int c;
};
struct keyframe_file {
const int num_views;
const int num_keyframes;
keyframe *keyframes;
};
int main() {
keyframe_file my_file;
my_file.num_views = 1;
my_file.num_keyframes = 6;
for (int i = 0; i < my_file.num_keyframes; i++){
my_file.keyframes = new keyframe; //<---
}
my_file.keyframes[0].a = true;
my_file.keyframes[0].b = 5;
my_file.keyframes[0].c = 9;
return 0;
}