I am doing a small C++ Windows Form project with visual studio 2010. My code is getting too large so I have decided to have some functions in header.h files. My problem is I do not know how to make a function to receive/return multi-dimension arrays. Any help appreciated
For managed arrays, you can specify the dimension as the second template parameter to the array keyword:
void TakesArray(array<Object^, 2>^ a)
{
...
}
array<Object^, 2>^ ReturnsArray()
{
}
For raw unmanaged arrays, it's a little complicated. Taking an array looks like:
void TakesArray(SomeType a[5][10])
{
}
But you need to be aware that that's actually equivalent to:
void TakesArray(SomeType (*a)[10])
{
}
Which means that it really takes a pointer to an array of 10 elements. It also means that the size of the second dimension (and higher dimensions, if you add more) is part of the type, but the size of the first dimension is not, which in turn means that you can call it with a 2-dimensional array whose second dimension's size must be 10, and whose first dimension can be of any size.
Returning a raw unmanaged array is even weirder:
void (*ReturnsArray())[10]
{
}
Anyway, there's rarely a need to use that syntax (that's why it's uncommon). A better way is to use an array class such as std::vector:
void TakesArray(const vector<vector<SomeTipe>>& v)
{
}
vector<vector<SomeType>> ReturnsArray()
{
}
Technically that's not a multidimensional array but an array of arrays, but you can use it much like a multidimentional array.
Related
I'm currently writing a project in C, and I need to be able to fill a 2D array with information already stored in another 2D array. In a separate C file, I have this array:
int levelOne[][4] =
{{5,88,128,0},
{153,65,0,0},
{0,144,160,20}}; //First Array
int levelTwo[][4] =
{{5,88,128,0},
{153,65,0,0},
{0,144,160,20}}; //Second Array
And in my main file, I have this variable which I'd like to fill with the information from both of these arrays at different points in my code. (This isn't exactly what I'm doing, but it's the general gist):
#include "arrayFile.c"
void main()
{
int arrayContainer[][4] = levelOne;
while (true)
{
func(arrayContainer);
if(foo)
{
arrayContainer = levelTwo;//Switches to the other array if the conditional is met.
}
}
}
I know this method doesn't work - you can't overwrite items in arrays after they're instantiated. But is there any way to do something like this? I know I'll most likely need to use pointers to do this instead of completely overwriting the array, however there's not a lot of information on the internet about pointers with multidimensional arrays. In this situation, what's best practice?
Also, I don't know exactly how many arrays of 4 there will be, so I wouldn't be able to use a standard 3D array and just switch between indexes, unless there's a way to make a 3D jagged array that I don't know about.
Given the definitions you show, such as they are, all you need is memcpy(arrayContainer, levelTwo, sizeof LevelTwo);.
You should ensure that arrayContainer has sufficient memory to contain the copied data and that LevelTwo, since it is used as the operand of sizeof, is a designator for the actual array, not a pointer. If it is not, replace sizeof LevelTwo with the size of the array.
If you do not need the actual memory filled with data but simply need a way to refer to the contents of the different arrays, make arrayContainer a pointer instead of an array, as with int (*arrayContainer)[4];. Then you can use arrayContainer = levelOne; or arrayContainer = levelTwo; to change which data it points to.
Also, I don't know exactly how many arrays of 4 there will be, so I wouldn't be able to use a standard 3D array and just switch between indexes, unless there's a way to make a 3D jagged array that I don't know about.
It is entirely possible to have a pointer to dynamically allocated memory which is filled with pointers to arrays of four int, and those pointers can be changed at will.
before you mark this as a duplicate please notice that I'm looking for a more general solution for arrays of arbitrary dimensions. I have read many posts here or in forums about making 2D or 3D arrays of integers but these are specific solutions for specific dimensions. I want a general solution for an array of any dimension.
First I need to have a type of intlist as defined below:
typedef struct{
int l // length of the list
int * e // pointer to the first element of the array
}intlist;
this actually fills the gap in C for treating arrays just as pointers. using this type I can pass arrays to functions without worrying about loosing the size.
then in the next step I want to have a mdintlist as multidimensional dynamically allocated arrays. the type definition should be something like this:
typedef struct Mdintlist{
intlist d // dimension of the array
/* second part */
}mdintlist;
there are several options for the second part. on option is that to have a pointer towards a mdintlist of lower dimension like
struct Mdintlist * c;
the other options is to use void pointers:
void * c;
I don't know how to continue it from here.
P.S. one solution could be to allocate just one block of memory and then call the elements using a function. However I would like to call the elements in array form. something like tmpmdintlist.c[1][2][3]...
Hope I have explained clearly what I want.
P.S. This is an ancient post, but for those who may end up here some of my efforts can be seen in the Cplus repo.
You can't! you can only use the function option in c, because there is no way to alter the language semantics. In c++ however you can overload the [] operator, and even though I would never do such an ugly thing (x[1][2][3] is alread y ugly, if you continue adding "dimensions" it gets really ugly), I think it would be possible.
Well, if you separate the pointers and the array lengths, you end up with much less code.
int *one_dem_array;
size_t one_dem_count[1];
int **two_dem_array;
size_t two_dem_count[2];
int ***three_dem_array;
size_t three_dem_count[3];
This way you can still use your preferred notation.
int num_at_pos = three_dem_array[4][2][3];
C newbie here, I need some help: Can anyone explain to (and offer a workaroud) me why this works:
int n=1024;
int32_t data[n];
void synthesize_signal(int32_t *data) {
...//do something with data}
which let me alter data in the function; but this does not?
int n=1024;
int number=1024*16;
int32_t data[n][2][number];
void synthesize_signal(int32_t *data) {
...//do something with data}
The compiler error message is something like it expected int32_t * but got int32_t (*)[2][(sizetype)(number)] instead.
First, passing arrays in C is by reference. So you pass a pointer of some sort, and the function can modify the data in the array. You don't have to worry about passing a pointer to the array. In fact, in C there is no real different between a pointer that happens to be to the being of an array, and the array itself.
In your first version. You making a one-dimensional array data[n], and you are passing it to your function. In the array, you'll using it by saying, something like data[i]. This translates directly to (data + (i sizeof(int32_t)). It is using the size of the elements in the array to find the memory location that is i positions in front of the beginning of your array.
int n=1024;
int number=1024*16;
int32_t data[n][2][number];
void synthesize_signal(int32_t *data)
In the second case, you're setting up a mufti-dimensional array (3D in your case). You setup correctly. The problem is that when you pass it to the function, the only thing that gets passed the address of the being of the array. When it gets used inside the function, you'll do something like
data[i][1][x] = 5;
Internally C is calculating how from the beginning of the array this location is. In order for it to do that, it need to know the dimensions of the array. (Unlike some newer languages, C store any extra data about array lengths or sizes or anything). You just need to change the function signature so it knows the shape/size of array to expect. Because of the way, it calculates array positions, it doesn't need the first dimension.
In this case, change your function signature to look like this:
void synthesize_signal(int32_t data[][2][number]) { ...
Setup the array the same way you are doing the second one above, and just call it you'd expect:
synthesize_signal(data);
This should fix everything for you.
The comments mention some useful information about using more descriptive variable names, and global vs. local variable. All valid comments to keep in mind. I just addressed to code problem you're having in terms of mufti-dimensional arrays.
try
synthesize_signal(int32_t** data)
{
}
Your function also needs to know that data is multi dimensional. You should also consider renaming your data array. I suspect that it is a global variable and using the same name in function can lead to problems.
When you call the function, do it like this:
synthesize_signal(&data[0][0][0]);
I was writing a code that involves handling a 2D array of dimensions [101]X[101] in C. However I am constrained in terms of memory being used at a given point of time.
void manipulate(int grid_recv[101][101])
{
//Something
}
void main()
{
int grid[101][101];
manipulate(grid);
}
So lets say I create an array grid[101][101] in my main() and then pass it for manipulation to another function. Now does the function manipulate() copy the entire matrix grid into grid_recv i.e by this sort of passing am I using twice the amount of memory ( i.e twice the size of grid)?
No. In C, arrays cannot be passed as parameters to functions.
What you actually do is creating a pointer pointing the array. So the extra memory you use it only the size of that pointer created.
I have these arrays of Strings and I want to load them into an Array of Arrays to process them afterwards.
Specifically, here is my code:
leerHTMLs(String[] urls) {
String[][] htmlsArr;
for (int i = 0; i < urls.length; i++) {
String [i][] htmlsArr = loadStrings(urls[i]);
}
}
I get an error, because "String htmlsArr[i][] = loadStrings(urls[i]);" is claearly not a proper way to initialize an array, right? But how can I move these one-dimensional arrays to my multidimensional array?
I've already tried other things except initializing the multidimensional array with a too-big-to-fail number, but that seems like cheating.
well, you said it yourself! It's an array of arrays! That means when you do
htmlsArr[i]
you will get back the element i from this array of arrays, which is of course, an array! When you do
htmlsArr[i][j]
what you get back is the element j in the array which is the element i in the array of arrays called htmlsArr! The final code should look like this:
void leerHTMLs(String[] urls) {
String[][] htmlsArr;
htmlsArr = new String[urls.length][0];
for (int i = 0; i < urls.length; i++) {
htmlsArr[i] = loadStrings(urls[i]);
}
}
So since loadStrings() returns an array of Strings you tell processing to take the output and put it in the element i of array htmlsArr (which is of course an array).
Technically speaking this is not a proper way to do this sort of thing because saying
htmlsArr = new String[urls.length][0];
means make an array with urls.length number of elements and they should all be arrays with 0 number of elements. But then you overwrite the arrays with other arrays with arrays of arbitrary number of elements, specifically as many as loadStrings may give you.
EDIT:
As per Shane's request in the comments, a more proper way to do it is using list in one of the arrays(external or internal one). That is, of course, in my own humble opinion, because since Processing(Java) allows you to do that you might as well consider it proper. The problem is that when you say something in the likes of:
String [][] arr = new String[3][4];
what you mean is essentially a rectangular array sort of like this:
{{ "a","b","c","e" },
{ "p","y","f","n" },
{ "g","q","r","m" }}
that is, an array with three arrays in, each containing four elements. It is merely for reasons of intuition that I consider this an "improper" way. If your array was like this:
{{ "a","b","c","e","k","h","s" },
{ "p","y" },
{ "g","q","r","m" }}
there is no way to intuitively define it in a new String[3][something] way, although you can always use the stretch in my original answer. (by the way it seems you can also define it with an empty parameter like this: new String[3][])
But since you are going to leave the second dimension of your array undefined, you might as well turn to lists which are more fit for the "unknown number of elements" job. Since it seems you can't create an array of lists you will have to create a list of arrays like this:
ArrayList<String []> a = new ArrayList<String []>();
As you can see there is no definition of numbers of elements here. ArrayLists can take as many as you can add to them, and you can arbitrarily add and remove elements. So what the above code says is that you have a list of String arrays which are not yet defined. Then, in the for loop that reads your urls you can just go:
a.add(loadStrings(urls[i]));
and now there is a new String array element in your ArrayList!