How should I initialize this multi-dimensional array? - arrays

I have a giant 3-dimensional array that represents my world. It's too big to initialize statically:
alias Cell[128][128][128] World; // <-- The compiler points to this line
Error: index 128 overflow for static array
I tried using World* world but it still errors out with the overflow above. So what I have right now is this ugly mess:
alias Cell[][][] World;
// ...
private World world;
// ...
world.length = WORLD_XDIM;
for (uint x = 0; x < world.length; ++x)
{
world[x].length = WORLD_YDIM;
for (uint y = 0; y < world[x].length; ++y)
{
world[x][y].length = WORLD_ZDIM;
}
}
That works, but it makes me cry a little on the inside. Is there a way to cast the result of calloc to a 3-dimensional array? I've done it with slicing regular arrays, but the 3-D thing is confounding me.

If you want to declare a jagged array (i.e. where each sub-array may have varying length), then you need to use a loop like you're doing, but that's unnecessary for uniform arrays. This is how you initialize a multi-dimensional array which isn't jagged:
auto arr = new Cell[][][](128, 128, 128);
When you put the numbers between the brackets, you're make it a dynamic array of static arrays. So,
auto arr = new Cell[128][128][128];
declares a dynamic array of a static arrays of length 128 of static arrays of length 128. I guess that it would be useful if you actually needed to do that (which I never have), but it definitely trips up newbies on a regular basis.
Personally, to avoid such issues completely, I just never put the numbers in between the brackets, even when declaring a single dimension array:
auto arr = new Cell[](128);
I find the fact that putting the number between the brackets on the first dimension is treated as a dynamic array while putting numbers in any further levels is treated as a static array to be a poor design choice, and I don't know why that's the way that it is, but that's the way that it is. I can understand wanting to be able to create dynamic arrays of static arrays, but it would have been far more consistent to either disallow new Cell[128] or to make it return a Cell[128]* rather than a Cell[] of length 128, but unfortunately, that's not how it works.

Related

Overwriting an existing 2D Array in C

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.

initialize Convex.MaxAtom array Julia

How can I create an Array of Convex.MaxAtoms (or for that matter, other Convex types) with the Convex package? I'm not sure if an Array is the right structure, but what I want to do is initialize something my_array of length n so that I can update each element in a loop like
using Convex
v = Variable(n)
w = Variable(n)
my_array = ...initialized array?...
for i = 1:n
my_array[i] = max(v[i],w[i])
end
I've tried doing
my_array = Convex.MaxAtom[]
for i = 1:n
push!(x, max(v[i], w[i]))
end
but I want to avoid reallocating memory and do it upfront. I feel that I must be missing an important part of Julia in not understanding what types to use to construct this.
In Julia Vector{AnyType}(n) (replace AnyType with a valid type in the application) allocates a vector of uninitialized AnyType elements of length n. More generally, Array{AnyType,3}(2,3,4) would allocate a 3-dimensional tensor of size 2x3x4 and analogously any dimension or shape can be allocated.
For the case in the question, a solution would be:
a = Vector{Convex.MaxAtom}(n)
P.S. the elements are allocated but uninitialized, this is fast, but it may be safer to use fill(some_value, n) or zero(AnyType, n) (which requires zero(AnyType) to be defined).

How do I copy a set of one-dimensional arrays to a two-dimensional array in Processing?

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!

Declaring an array in a loop

Is it possible to declare an array inside a loop. For some reasons I can not declare it before the loop since its length changes. I am wondering if I can re-declare/delete an array within the loop. I am using C++/CLI language.
Native c++ arrays, must have their size determined at compile-time if they are allocated on the stack, and so if you want to use native arrays, you'll have to allocate them with the new operator.
Unrecommended solution:
int rows = 1000;
int arr[] = new int[rows]; //new array with 1000 integers
int rows = 5;
delete arr; //don't forget to delete the previous allocation before re-sizing
int arr[] = new int[rows]; //new array with 5 integers
This however forces you to constantly be aware of allocations and de-allocations. That's why the standard and Microsoft gave you std::vector and cli::array.
The Managed way:
If you want your array to be on the managed heap, use cli::array:
cli::array<int> ^arr= gcnew cli::array<int>(1000); //new array with 1000 integers
Array::Resize(arr, 5); //resize arr to 5 integers
The unmanaged way:
If you want your array to be on the unmanaged heap (native C++), use std::vector:
std::vector<int> arr(1000); //new array with 1000 integers
arr.resize(5); //resize array to 5 integers
You could use Array::Resize method in each iteration (as eladidan says); or you could use a List<> class, add items in each iteration and finally call List<>::ToArray() to get the array you are looking for. Probably the first way would be more efficient but the second one is more convenient.

How to check if "set" in c

If I allocate a C array like this:
int array[ 5 ];
Then, set only one object:
array[ 0 ] = 7;
How can I check whether all the other keys ( array[1], array[2], …) are storing a value? (In this case, of course, they aren't.)
Is there a function like PHP's isset()?
if ( isset(array[ 1 ]) ) ...
There isn't things like this in C. A static array's content is always "set". You could, however, fill in some special value to pretend it is uninitialized, e.g.
// make sure this value isn't really used.
#define UNINITIALIZED 0xcdcdcdcd
int array[5] = {UNINITIALIZED, UNINITIALIZED, UNINITIALIZED, UNINITIALIZED, UNINITIALIZED};
array[0] = 7;
if (array[1] != UNINITIALIZED) {
...
You can't
There values are all undefined (thus random).
You could explicitly zero out all values to start with so you at least have a good starting point. But using magic numbers to detect if an object has been initialized is considered bad practice (but initializing variables is considered good practice).
int array[ 5 ] = {};
But if you want to explicitly check if they have been explicitly set (without using magic numbers) since creation you need to store that information in another structure.
int array[ 5 ] = {}; // Init all to 0
int isSet[ 5 ] = {}; // Init all to 0 (false)
int getVal(int index) {return array[index];}
int isSet(int index) {return isSet[index];}
void setVal(int index,int val) {array[index] = val; isSet[index] = 1; }
In C, all the elements will have values (garbage) at the time of allocation. So you cannot really have a function like what you are asking for.
However, you can by default fill it up with some standard values like 0 or INT_MIN using memset() and then write an isset() code.
I don't know php, but one of two things is going on here
the php array is actually a hash-map (awk does that)
the php array is being filled with nullable types
in either case there is a meaningful concept of "not set" for the values of the array. On the other hand a c array of built in type has some value in every cell at all times. If the array is uninitialized and is automatic or was allocated on the heap those values may be random, but they exist.
To get the php behavior:
Implement (or find a library wit) and use a hashmap instead on an array.
Make it an array of structures which include an isNull field.
Initialize the array to some sentinal value in all cells.
One solution perhaps is to use a separate array of flags. When you assign one of the elements, set the flag in the boolean array.
You can also use pointers. You can use null pointers to represent data which has not been assigned yet. I made an example below:
int * p_array[3] = {NULL,NULL,NULL};
p_array[0] = malloc(sizeof(int));
*p_array[0] = (int)0;
p_array[2] = malloc(sizeof(int));
*p_array[2] = (int)4;
for (int x = 0; x < 3; x++) {
if (p_array[x] != NULL) {
printf("Element at %i is assigned and the value is %i\n",x,*p_array[x]);
}else{
printf("Element at %i is not assigned.\n",x);
}
}
You could make a function which allocates the memory and sets the data and another function which works like the isset function in PHP by testing for NULL for you.
I hope that helps you.
Edit: Make sure the memory is deallocated once you have finished. Another function could be used to deallocate certain elements or the entire array.
I've used NULL pointers before to signify data has not been created yet or needs to be recreated.
An approach I like is to make 2 arrays, one a bit-array flagging which indices of the array are set, and the other containing the actual values. Even in cases where you don't need to know whether an item in the array is "set" or not, it can be a useful optimization. Zeroing a 1-bit-per-element bit array is a lot faster than initializing an 8-byte-per-element array of size_t, especially if the array will remain sparse (mostly unfilled) for its entire lifetime.
One practical example where I used this trick is in a substring search function, using a Boyer-Moore-style bad-character skip table. The table requires 256 entries of type size_t, but only the ones corresponding to characters which actually appear in the needle string need to be filled. A 1kb (or 2kb on 64-bit) memset would dominate cpu usage in the case of very short searches, leading other implementations to throw around heuristics for whether or not to use the table. But instead, I let the skip table go uninitialized, and used a 256-bit bit array (only 32 bytes to feed to memset) to flag which entries are in use.

Resources