variable length c array - objective-c

I am using objective c to create a struct holding a variable length array. I know you can create an array of length n like so:
double array[n];
And i also believe in c++ you can declare:
vector<double> array;
where you do not have to declare the array length. Is there any way to do something similar in objective c? I am using ARC.
Thanks in advance, Ben

You just need to create an NSMutableArray like-
NSMutableArray *myArray = [NSMutableArray array];
[myArray addObject:....];// Add as many object as you want.
You just need to take care of one thing while creating variable length array, don't add nil as object, as nil is just to signify the end of the variable-length argument list.
EDIT -
Might be following will help you -
In this way you can define objective c data types in struct-
typedef struct{
int numInputs;
__unsafe_unretained NSMutableArray *array;
} Pin;

Related

Objective C Array of Array of Strings

I'm trying to make an array of array of strings so that I can eventually pull out something like ArrayOfArrays[0][1] = "hi".
NSString *ArrayOne[] = {#"hello", #"hi"};
NSString *ArrayTwo[] = {#"goodbye", #"bye"};
NSArray *ArrayOfArrays[] = {#[*ArrayOne, *ArrayTwo]};
However when I try to do this, I get an error: Initializer element is not a compile-time constant.
I've read that this is because I'm creating an array with dynamic values, though it should be static. Not sure how to work around this.
Any advice on making an array of array of strings?
Use NSArray, or rather NSMutableArray if you want to modify it after creation:
NSMutableArray *arrayOne = [#[#"hello", #"hi"] mutableCopy];
NSMutableArray *arrayTwo = [#[#"goodbye", #"bye"] mutableCopy];
NSMutableArray *arrayOfArrays = [#[arrayOne, arrayTwo] mutableCopy];
There are other ways to initialise it, but this is the only way that allows you to use Objective-C literal syntax.
You cannot store plain ol' C arrays within an Objective-C collection class as your code attempts to do.
You wrote:
it should be static
if this is what you want then your use of C arrays is quite valid, you just got the syntax wrong. You can use:
NSString *arrayOfArrays[][2] =
{ {#"hello", #"hi"},
{#"goodbye", #"bye"},
};
Important: The 2 is the number of elements in the inner array, you do not change it when adding further pairs.
This will give you a compile-time static array.
If what you are making is a map from one word to another you might be better off with a dictionary, e.g.:
NSDictionary *wordMap =
#{ #"hello" : #"hi",
#"goodbye" : #"bye"
};
and accessing an element becomes:
wordMap[#"hello"];
Note: the dictionary "constant" here is actually executed code; the C array version can appear as a global or local initialiser, while the dictionary initialisation must be done in a method/function - but it can assign to a global.
HTH
NSArray *array = #[
#[[ #"hello", #"hi" ] mutableCopy],
#[[ #"goodbye", #"bye" ] mutableCopy],
];
NSLog(#"%# is short for %#", array[0][1], array[0][0]);
Output: hi is short for hello

With NSPointerArray, how to iterate over opaque pointers?

I recently discovering these classes like NSMapTable and NSPointerArray, which work like the traditional collections, but also let you store weak references or plain old C pointers. Unfortunately it looks like you can't use the for...in syntax to iterate over non-NSObject pointers. For example:
typedef struct Segment {
CGPoint bottom, top;
} Segment;
...
NSPointerArray *segments = [[NSPointerArray alloc]
initWithOptions:NSPointerFunctionsOpaqueMemory];
...
Segment *s = malloc(sizeof(Segment));
[segments addPointer: s];
...
for (Segment *s in segments) { // nope...
The compiler does not like that last line. The error:
Selector element type 'Segment *' (aka 'struct Segment *') is not a valid object
So, do I need to do this?
for (int i=0, len=segments.count; i<len; i++) {
Segment *seg = [segments pointerAtIndex:i];
...
That's not the end of the world, but I just want to make sure.
(This might be more of theoretical interest.)
NSPointerArray does conform to the NSFastEnumeration protocol, it is only the
for (id object in collection) language construct that cannot be used with arbitrary pointers which
are not Objective-C pointers.
But you can get a whole bunch of pointers from the array by calling the NSFastEnumeration
method countByEnumeratingWithState:objects:count: directly. This is a bit tricky because
that method need not fill the supplied buffer (as explained here: How for in loop works internally - Objective C - Foundation).
Here is a simple example how this would work:
__unsafe_unretained id objs[10];
NSUInteger count = [segments countByEnumeratingWithState:&state
objects:objs count:10];
// Now state.itemsPtr points to an array of pointers:
for (NSUInteger i = 0; i < count; i++) {
Segment *s = (__bridge Segment *)state.itemsPtr[i];
NSLog(#"%p", s);
}
So this does not help to make the code simpler and you probably want to stick with
your explicit loop.
But for large arrays it might improve the performance because the pointers are "fetched"
in batches from the array instead of each pointer separately.
the for (... in ...) syntax won't work in this case because Segment is a struct, not an Objective C object. Your second for loop should work.

Is a variable like "int nameofvariable" an object?

My question is as it is in the title. However, if it isn't an object, how can it then be maintained in NSMutableArray as an object? Because NSMutableArray is only for storing objects or am I wrong? :)
Primitive types, like int, must be wrapped in an object before it can be added to a collection class like NSMutableArray. Try this:
int nameOfVariable = 42;
NSMutableArray *array = ... // the initialized array
[array addObject:#(nameOfVariable)];
The last line is modern syntax that essentially means:
[array addObject:[NSNumber numberWithInt:nameOfVariable]];
Later on, when you need to get the value back, you do:
int someVariable = [array[someIndex] intValue];
No, it is not an object and you can therefore not put it in an NSArray. You have to wrap it in an NSNumber, which is an object and can be put in an NSArray.
An int is a primitive type inherited from C (examples of other primitive types are char, long, float, etc.). These are not Objective-C objects. To add a primitive type to an NSMutableArray or any other Objective-C collection, you must wrap them in an object. For number types like int, you would use NSNumber as follows:
int i = 1;
[array addObject:#(i)]; // #(i) is equivalent to [NSNumber numberWithInt:i]

Object Class Array Casting for a Method in Objective C

I have an object Student with 4 attributes(age,name,department,surname).
and I create an array of that object like this;
Student students[10] blah blah init blah.
then i want to use an Student array as argument for a method;
-(void) displayStudentInArray : (????) studentarray atIndex: (int) index {.....}
'???' are my problem. what do i write there? i ve no idea.
need help. i m new on objective c.
Rather than using C notation the array should be made like this:
NSArray *studentArray = [[NSArray alloc] initWithObjects: student1, student2, student2, ..., nil];
In which case the parameter type will be NSArray
-(void) displayStudentInArray : (NSArray *)studentarray atIndex: (int) index {.....}
The preferred method for creating arrays is using NSArray (or NSMutableArray if you want to modify the array after it is created):
NSArray *array = [[NSArray alloc]initWithObjects:student1, student2...];
Then your method signature would be:
-(void)displayStudentInArray:(NSArray *)studentarray atIndex:(int)index
These answers are correct, but if you really want to use C notation, you just need to add another asterisk to denote a reference to another pointer:
- (void)displayStudentInArray:(Student**)studentArray atIndex:(int)index {
Student* firstStudent = studentArray[1];
//do what you want with the array
}
This is because C arrays are really just pointers to an address in memory. If you wanted a C array for a primitive, it would look like this:
int* arrayOfInts = malloc(yourSize * sizeof(int));
You have an array of objects, but the idea is just the same. You just add one more asterisk to denote that it's a pointer to a pointer to an object.
Student** students = ...
Just write
Student *tempStudent = (array)[0];

How do I convert a c-style char* array to NSArray?

a.H:
-(NSArray *) returnarray:(int) aa
{
unsigned char arry[1000]={"aa","vv","cc","cc","dd"......};
NSArray *tmpary=arry;
return tmpary;
}
a.c:
#include "a.H"
main (){
// how do I call returnarray function to get that array in main class
}
I need that array in main and I need to retain that array function in separate class.
Can someone please provide a code example to do this?
These lines:
unsigned char arry[1000]={"aa", "vv", "cc", "cc", "dd", ...};
NSArray *tmpary=arry;
Should instead be:
unsigned char arry[1000]={"aa", "vv", "cc", "cc", "dd", ...};
NSMutableArray * tmpary = [[NSMutableArray alloc] initWithCapacity: 1000];
for (i = 0; i < 1000; i++)
{
[tmpary addObject: [NSString stringWithCString: arry[i] encoding:NSASCIIStringEncoding]];
}
This is because a C-style array (that is, int arr[10]; for example) are not the same as actual NSArray objects, which are declared as above.
In fact, one has no idea what an NSArray actually is, other than what the methods available to you are, as defined in the documentation. This is in contrast to the C-style array, which you are guaranteed is just a contiguous chunk of memory just for you, big enough to hold the number of elements you requested.
C-style arrays are not NSArray's so your assignment of arry (the definition of which has some typos, at least the unsighned part) is not valid. In addition, you call arry an array of char, but you assign it an array of null-terminated strings.
In general you need to loop and add all the elements of the C-style array to the NSArray.
I'm not sure why you must do it in main. If you want a global you can do it by declaring a global in another file. That said, you CANNOT assign a plain C data array to an objective C NSArray, which is different in nature entirely.