what do the square brackets next to an NSDecimal object mean? - objective-c

Im using core-plot for my graphing component of my iPhone app, and I have been using NSDecimal object a lot.
One of the lines of their code that I have seen is like this:
-(void)plotPoint:(NSDecimal *)plotPoint forPlotAreaViewPoint:(CGPoint)point
{
NSDecimal x;
//do some calculations on x
plotPoint[CPCoordinateX] = x;
}
Where, CPCoordinateX is deinfed as below:
typedef enum _CPCoordinate {
CPCoordinateX = 0, ///< X axis
CPCoordinateY = 1, ///< Y axis
CPCoordinateZ = 2 ///< Z axis
} CPCoordinate;
The line:
plotPoint[CPCoordinateX] = x;
is what I dont understand, how can a NSDecimal be assigned to like this?
In my code, Im trying to call this method, like so:
NSDecimal dec = CPDecimalFromInteger(0);
[plotSpace plotPoint:&dec forPlotAreaViewPoint:point];
NSDecimalNumber *newx = [[NSDecimalNumber alloc] initWithDecimal:dec];
NSDecimal x = dec[CPCoordinateX];
//NSLog(#"converted at: %#", newx);
but Im getting compile errors:
error: subscripted value is neither array nor pointer
Can someone please explain this to me?

plotPoint is a pointer and pointers can be indexed like arrays using the subscript operator:
int array[] = { 1, 2, 3 };
NSLog(#"x=%d, y=%d, z=%d", array[0], array[1], array[2]);
// prints "x=1, y=2, z=3"
int *pointer = array; // implicit conversion to pointer
NSLog(#"x=%d, y=%d, z=%d", pointer[0], pointer[1], pointer[2]);
// also prints "x=1, y=2, z=3"
You can also use those expressions for assignments:
array[0] = 4;
pointer[1] = 5;
But you can only use the subscript operator on arrays or pointers:
NSDecimal dec = CPDecimalFromInteger(0);
dec[0]; // illegal, dec is a single NSDecimal value, not pointer or array
To actually pass a point -plotPoint:forPlotArrayViewPoint: you need a C-style array or a dynamic array of 2 or 3 NSDecimals (according to what dimensions the method expects), e.g.:
NSDecimal decPoint[] = {
CPDecimalFromInteger(0),
CPDecimalFromInteger(0),
CPDecimalFromInteger(0)
};
[plotSpace plotPoint:decPoint forPlotAreaViewPoint:point];
On that array you can now also use the subscript operator:
NSDecimal x = decPoint[CPCoordinateX];

It's a C array.

Related

When accessing my NSMutableArray I get an error message like "Cannot initialize a variable of type 'int' with an rvalue of type 'id'"

I have the following function and I am struggling to get the y value out as an int.
+ (NSMutableArray *) cleanPoints:(NSMutableArray *)pointsArray{
NSMutableArray *mutableArray = [NSMutableArray array];
for(int i = 0; i<pointsArray.count-1; i++){
CLog(#"pointsArray %#", pointsArray[i]); /// here it gives me the correct number, like 345
int y = (int)pointsArray[i]; //// here seems to be the problem
CLog(#"y = %d", y); ///// y is a weird number, like y = 384643392
if (y < 4 || y > -4){
y = 0;
}
//create Array
[mutableArray addObject:#(y)];
}
return mutableArray;
}
If I take out the (int) from the int y = (int)pointsArray[I] line then I get the error "Cannot initialize a variable of type 'int' with an rvalue of type 'id'
This line makes no sense:
int y = (int)pointsArray[i];
It is impossible for an NSArray to contain int values. It can contain only objects, and in Objective-C an int is not an object.
Perhaps you mean
int y = [pointsArray[i] intValue];
(but I’m just guessing that this NSArray contains NSNumber objects; I have no way of knowing, as you have given no information about that)

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]);
}

Using non repeating number value from array for label placement

Updated
I'm trying to draw a random number and not repeat the previous number
NSArray *placement = #[#300,#400,#500,#600,#700];
float placement1 = [placement[arc4random_uniform(5)]floatValue];
float recentdraw;
if (placement1 == recentdraw) {
//float placement1 = [placement[arc4random_uniform(5)]floatValue];
}
else {
placement1 recentdraw;
// den vertikale placering af labelen randomizes nu ved hvert swipe
self.Label.frame = CGRectMake(30, placement1, 400, 500);
placement1 = recentdraw;
};
what I want to do here is under the 'if' part to set the code to repeat itself. I'm very new in coding, so I hope to avoid creating my own method/function - basically just make this as simple as possible
Couldn't find any thread that made me understand this
Use [placement[1] floatValue]. It will return float value of your NSNumber. #400 is the same as [NSNumber numberWithInt:400] and as CGRectMake takes only CGFloat's as parameters you need to convert NSNumber from the array to the float.

Empty float ** for sound samples

I have been attempting to pass and array to a method within DiracLE audio library.
The array looks like this in the debugger
- (OSStatus) readFloatsConsecutive:(SInt64)numFrames intoArray:(float**)audio withOffset:(long)offset
That fills the array up like so
if (audio) {
for (long c = 0; c < mExtAFNumChannels; c++) {
if (!audio[c]) continue; // this executes for both channels
// but doesnt proceed into next for loop
for (long v = 0; v < numFrames; v++) {
if (v < loadedPackets) audio[c][v+offset] = (float)data[v*mExtAFNumChannels+c] / 32768.f;
else audio[c][v+offset] = 0.f;
}
}
}
I call it like this
[reader readFloatsConsecutive:frameCount intoArray:arrayToFill];
arrayToFill being an argument to the current function scope
[self readAudioDataForFile:temp withArray:tempArray];
The array was initially passed into the function like this
// this array was passed into the function as tempArray which is float **tempArray = NULL;
arrayToFill = (float **) malloc ( (frameCount * channelCount) * sizeof( float ));
As I needed to extract audio data from the file in my method I have to malloc the array there and pass it into the dirac function for filling. I malloc like so arrayToFill = (float **) malloc ( (frameCount * channelCount) * sizeof( float )); and then pass it to the dirac function as mentioned before.
This array could be a 2 dimensional or 1 dimensional array depending on channel count
The problem relies on allocation in my opinion.
Allocating a 1 dimensional array would look like:
arrayToFill = (float *) malloc ( (frameCount * channelCount) * sizeof( float ));
and it would be enought.
Allocating a 2 dimensional array would be different though, because you have to allocate even inner arrays. If I understood correctly if you have two channels then the array is bidimensional, you should do something like:
arrayToFill = (float **)calloc(channelCount, sizeof(float*));
for (int i = 0; i < channelCount; ++i)
arrayToFill[i] = (float*)calloc(frameCount, sizeof(float));
This because you need to allocate a pointer to pointer to float. So in the first step you allocate a 2 dimensional array of pointers to float, these pointers are initialized to NULL so you have to loop through it and allocate them separately.
If the channel is inner inside the array (eg. the first index chooses the frame and not the channel) then you should swap dimensions.

Initi and write array in objective-c

In my h file I declare a var that later should be an array:
#interface myClass : CCNode {
CGPoint *mVertices;
}
#end
In my init method:
mVertices = malloc(size * size * sizeof(CGPoint));
mVertices[0][0] = ccp(0,0);
At this last line I get an error Subscripted value is neither array nor pointer.
Why do I get this error and how to solve that problem?
mVertices is a pointer, but you treat it like a two-dimensional array which is not allowed (you may treat it like a one-dimensional array, though).
Creating a dynamic multi-dimensional array in (Objective)-C is tricky insofar as the compiler would need to know the size of all but the first dimension to actually compile where in memory the element is situated.
But you can do the calculation yourself:
mVertices[(row * size) + column] = ccp(row, column);
You might want to define a macro for that:
#define VERTICE_ACCESS(row,colum) mVertices[(row * size) + column]
Your array is not two dimensional. It's just a list of vertices.
If you want to allocate space for a dynamic two dimensional array in C you could do:
CGPoint** mVertices;
NSInteger nrows = 10;
NSInteger ncolumns = 5;
mVertices = calloc(sizeof(CGPoint*), nrows);
if(mVertices == NULL){NSLog(#"Not enough memory to allocate array.");}
for(NSUInteger i = 0; i < nrows; i++)
{
mVertices[i] = calloc(sizeof(CGPoint), ncolumns);
if(mVertices[i] == NULL){NSLog(#"Not enough memory to allocate array.");}
}
mVertices[0][5] = CGPointMake(12.0, 24.0);
mVertices[1][5] = CGPointMake(22.0, 24.0);
mVertices[2][5] = CGPointMake(32.0, 24.0);
mVertices[2][1] = CGPointMake(32.0, 24.0);
for(NSUInteger i = 0; i < nrows; i++)
{
for (int k = 0; k < ncolumns; k++)
{
NSLog(#"Point %#", NSStringFromPoint(NSPointFromCGPoint(mVertices[i][k])));
}
}
I used calloc instead of malloc to get CGPoints initialized with 0.0.