Multi-dimensional primitive integer array - objective-c

I know this code doesn't work, but how could I actually initialize this correctly?:
NSUInteger highestModelID = 34605;
NSUInteger highestColorID = 328;
NSUInteger** modelColors[highestModelID][highestColorID] = malloc(highestModelID * highestColorID * sizeof(NSUInteger));
So having 2 dynamic depths. I have this massive buffer in a multi-dimensional NSMutableDictionary which hogs memory. I would really love to just do this primitive.
Guess it would be even more amazing to make a class out of this to be able to use it on more places where Objective-C dictionaries and even NSMutableArray are really just overkill. Over time I'm really becoming more and more annoyed by using NSNumber for something that would be super light what I'm used to in golang, suddenly making it a major factor in slowing my app down..

You need this:
NSUInteger* modelColors = malloc(highestModelID * highestColorID * sizeof(NSUInteger));
Which you can use like this:
NSUInteger getModelColor(int modelID, int colorID, int highestModelID, NSUInteger* modelColors) {
return modelColors[colorID * highestModelID + modelID];
}
void setModelColor(NSUInteger color, int modelID, int colorID, int highestModelID, NSUInteger* modelColors) {
modelColors[colorID * highestModelID + modelID] = color;
}
Basically this is a 2D array, where modelID indexes the rows, and colorID indexes the columns (assuming row-major layout).

The way of creating it isn't really that different from creating NSArray of NSArrays. You need to alloc array of NSUInteger* first, then alloc each of its elements.
NSUInteger **modelColors;
modelColors = malloc(highestModelID * sizeof(NSUInteger*));
for (int i = 0; i < highestModelID; i++) {
modelColors[i] = malloc(highestColorID * sizeof(NSUInteger));
}

Related

Properly declare 2D array of Ints [duplicate]

I have the following code which works fine...
int testarr[3][3] = {
{1,1,1},
{1,0,1},
{1,1,1}
};
[self testCall: testarr];
Which calls this function:
- (void)testCall: (int[3][3]) arr {
NSLog(#"cell value is %u",arr[1][1]);
}
I need the array to be of variable length - What is the best way to declare the function?
Using blanks doesn't work:
- (void)testCall: (int[][]) arr {
Thanks for your help.
I would write this as:
- (void) testCall: (int *) aMatrice;
Doing so allows you to avoid multiple mallocs and the math to calculate a single offset in a linear array based on x, y coordinates in a 2D array is trivial. It also avoids the multiple mallocs implied by int** and the limitations of 2D array syntax perpetuated by the language.
So, if you wanted a 4x5 array, you might do:
#define WIDTH 4
#define HEIGHT 5
#define INDEXOF(x,y) ((y*WIDTH) + x)
int *myArray = malloc(sizeof(int) * 5 * ELEMS_PER_ROW);
You could then initialize the array linearly or with a nested for loop:
for(int x=0; x<width; x++)
for(int y=0; y<height; y++)
myArray[INDEXOF(x,y)] = ... some value ...;
And you would pass it to the method like:
[foo testCall: myArray];
Though you might want to also carry along the width and the height or, better yet, create a IntMatrix subclass of NSObject that wraps all of the pointer arithmetic and storage beyond a nice clean API.
(all code typed into SO)
C arrays can't be variable in more than one dimension.
You can't have this:
int testarr[][] = {
{1,1,1},
{1,0,1,2},
{1,1}
};
But you can have this:
int testarr[][3] = {
{1,1,1},
{1,0,1},
{1,1,1},
{4,5,6},
{7,8,9}
}
foo(testarr);
void foo(int param[][3])
{
printf("%d", param[3][1]); // prints 5
}
You can't use int[][] because the size of the second dimension affects how the array is laid out in memory. If you know the second dimension you can use int[][x], otherwise you'll have to use int** which can be accessed just like an array.
Why don't you just use NSArray or NSMutableArray with NSIntegers? Those array classes are of variable length, and much easier to use.
This would result in
- (void)testCall: (NSArray *) arr {
NSLog(#"cell value is %u", [[arr objectAtIndex:1] objectAtIndex:1]);
}
(Of course, you would also have to define testarr using NSArray.)
If you really want to use C arrays, making the method argument a pointer to an int with
- (void)testCall: (int*) arr {
will probably work (with the rest of the code staying the same).
call
int testarr[3][3] = {
{1,1,1},
{1,0,1},
{1,1,1}
};
[self testCall: (int *)testarr];
function
- (void)testCall: (int *) arr
{
int (*V_arr)[3] = (int(*)[3])arr;
NSLog(#"cell value is %u",V_arr[1][1]);
}

2D Array Declaration - Objective C

Is there a way to declare a 2D array of integers in two steps? I am having an issue with scope. This is what I am trying to do:
//I know Java, so this is an example of what I am trying to replicate:
int Array[][];
Array = new int[10][10];
Now, in OBJ-C I want to do something similar, but I cant get the syntax right. Right now I have it in one step, but I cannot use it outside of the If-Statement in which I currently have it:
int Array[10][10]; //This is based on an example I found online, but I need
//to define the size on a seperate line than the allocation
Can anyone help me out with this? I know its probably a more basic question, but you can't use the keyword "new" outside of a message (to my knowledge) and you cant send messages to ints. :(
*EDIT 1:**
My problem is scope related.
//Declare Array Somehow
Array[][] //i know this isn't valid, but I need it without size
//if statement
if(condition)
Array[1][2]
else
Array[3][4]
//I need to access it outside of those IFs
//... later in code
Array[0][0] = 5;
This is my preferred way of creating a 2D array, if you know the size of one of the boundaries:
int (*myArray)[dim2];
myArray = calloc(dim1, sizeof(*myArray));
And it can be freed in one call:
free(myArray);
Unfortunately, one of the bounds MUST be fixed for this to work.
However, if you don't know either of the boundaries, this should work too:
static inline int **create2dArray(int w, int h)
{
size_t size = sizeof(int) * 2 + w * sizeof(int *);
int **arr = malloc(size);
int *sizes = (int *) arr;
sizes[0] = w;
sizes[1] = h;
arr = (int **) (sizes + 2);
for (int i = 0; i < w; i++)
{
arr[i] = calloc(h, sizeof(**arr));
}
return arr;
}
static inline void free2dArray(int **arr)
{
int *sizes = (int *) arr;
int w = sizes[-2];
int h = sizes[-1];
for (int i = 0; i < w; i++)
free(arr[i]);
free(&sizes[-2]);
}
The declaration you showed (e.g. int Array[10][10];) is OK, and will be valid for the scope it was declared to, if you do it in a class scope, then it will be valid for the whole class.
If the size of the array varies, either use dynamic allocation (e.g. malloc and friends) or use NSMutableArray (for non-primitive data types)

Returning a 2D C array of type id in Objective-C

I'm using a 2D C array of ids in my iOS app. Is it possible to return this in an objective-C method? As an alternative solution, I tried to return a pointer to a 2D C array of integers, but I cannot modify the 2D-int array.
- (int (*)[8][8])board:(Piece *)piece
{
int (*layout)[8][8] = malloc(8 * 8 * sizeof(int));
//Cannot modify layout 2D C array
return layout;
}
I have some experience in Objective-C, but none in C. Am I likely to continually run into problems using C 2D arrays, such that I should make a 2D-Array Objective-C class? What is the more typical approach an iOS developer would use?
- (int **)board:(Piece *)piece
{
int **layout = malloc(8 * sizeof(int *));
for(int i=0; i<8; i++)
layout[i] = malloc(8 * sizeof(int));
return layout;
}
Don't forget to free the memory in the end. Also, you could also use a one dimensional array and something like this to access it in a similar way:
#define access(array, x, y) array[y * 8 + x]
There is also now drop in multi-dimensional array class in Objective-C, but you could create a NSArray with other NSArray's inside of it, or, google if someone else did this (I remember at least one implementation but can't recall its name)
After you declare int (*layout)[8][8] = malloc(8 * 8 * sizeof(int));, You can change the values like (*layout)[x][y]=val;. But I recommend you to declare int (*layout)[8], so you can access elements by simply layout[x][y]=val.
Edit: I don't know about Objective-C, but in C, the function I suggested will look like:
int (*newarray())[8] {
int (*l)[8]=malloc(64*sizeof(int));
// You can do stuff like l[2][4]=15 here
return l;
}

Shuffling an array of NSNumbers & converting back to ints

I have an NSMutableArray urlArray of size n, I want to randomly choose 4 of these URLs from the total number of elements in the array.
However I don't want to shuffle urlArray directly, I'd prefer to make an "indexArray" [0 ... (n-1)] & shuffle these, & then use the first 4 elements of the shuffled indexArray to decide which elements I choose from urlArray.
First off I created the indexArray as follows:
for (int i = 0; i < numberOfStems; i++) {
[indexArray addObject:[NSNumber numberWithInteger:i]];
}
This allowed me to shuffle my indexArray, so far so good. Because I used the
[NSNumber numberWithInteger:i] method, the elements in the shuffled indexArray are NSNumbers.
Is there a way to convert the NSNumber objects in indexArray into ints?
I attempted to use the intValue function but this didn't appear to be what I needed.
I also tried creating a c style array but that wasn't so successful either - I'd like to stick with objective-c syntax if possible.
Any ideas? any hints appreciated :)
Why don't you just create a normal c array, shuffle that and then use the first four integers in the array as the for random index?
something like
int* index = malloc(numberOfStems*sizeof(int));
for (int i = 0; i < numberOfStems; ++i)
{
index[i] = i;
}
for (int i = numberOfStems - 1; i > 0; --i)
{
int randomIndex = arc4random() % i;
int tmp = index[i];
index[i] = index[randomIndex];
index[randomIndex] = tmp;
}
now use index to access the URL's
EDITED: updated algorithm (although not really related to OP question)
For a temporary array that stores only integers and gets thrown away after a relatively short task I would definitely prefer a C-style array: this would avoid a great deal of overhead, and is also simple to read.
int *array = (int*)malloc(sizeof(int)*numberOfStems);
for (int i = 0 ; i != numberOfStems ; i++) {
array[i] = i;
}
// Do the shuffle
// Pick first four, and do whatever you need to do
// ...
// Now that you are done with the array, do not forget to free it:
free(array);

objective c array of booleans

I am working on a game that will have a two dimensional board of dots, each with one boolean attribute (occupied/not occupied). I was thinking the best way to accomplish this is to create a simple c array of Booleans. This will be much more efficient than creating a mutablearray. I'm just confused the best way to accomplish this. The trouble is that I don't know the size of the board until I initialize the board object.
The interface looks like this:
#interface TouchBoard : NSObject{
NSInteger height,width;
BOOL dots[10][10];
}
And the implementation like this:
-(id)initWithHeight:(NSInteger)rows Width:(NSInteger)columns{
if ( self = [super init]){
height = rows;
width = columns;
dots[height][width];
}
return self;
}
Trouble is, in the interface, if i try to declare the dots variable with a dynamic number of indices, dots[][], it'll just give me an error.
Obviously I don't know the size of the array until the object is initialized, but after that it's not going to be changing and only its elements will be changing from true/false.
What is the best way to accomplish this?
In your interface, declares:
BOOL ** dots;
Then, you'll need to use malloc, to dynamically allocate memory:
int i;
dots = malloc( rows * sizeof( BOOL * ) );
for( i = 0; i < rows; i++ )
{
dots[ i ] = calloc( columns, sizeof( BOOL ) );
}
Don't forget to free in your dealloc method:
int i;
for( i = 0; i < rows; i++ )
{
free( dots[ i ] );
}
free( dots );