0

I have a class named Calculator. This class accepts a bunch of test scores, and will store each of them into an array. This array is called scoreArray.

I want to declare the array like this, but I'm having trouble with the scope:

int scoreArray[numTestScores];

If I put that code into the @implementation, it doesn't know what numTestScores is, because it hasn't been passed to the class yet.

And if I try to do this:

-(id)init:(int)numTestScores_
{
    if (self = [super init])
    {
        int scoreArray[numTestScores_];
    }
    return self;
}

then the array gets created, but the rest of the class doesn't know what scoreArray is.

How can I make it so that scoreArray is created with length "numTestScores" and has the same scope as if I had put it in the implementation block?

0

3 Answers 3

3

Using a native C array is an unnecessary pain. I'd rather use a NSMutableArray, declaring it as a property.

@property (nonatomic, copy) NSMutableArray *scores;

NSMutableArray automatically manages its memory, so you don't need to declare its size in advance.

Just initialize it as

_scores = [NSMutableArray array];

and then add values to it

[self.scores addObject:@(aResult)]; //assuming that aResult is an integer expression

@(...) wraps the value in a NSNumber since NSArray can only hold objects.

To retrieve a score, you can do

int score = [self.scores[0] intValue];
Sign up to request clarification or add additional context in comments.

2 Comments

"Using a native C array is an unnecessary pain" - using an NSMutableArray is unnecessary complexity.
@H2CO3. Different point of views: I consider NSArray simpler than dealing with explicit memory allocation through a malloc, especially for a beginner. Even though a native array would equally serve the purpose, the use of properties and Foundation collections results in a much cleaner interface, IMO.
1

VLAs (variable-length arrays) only work in contexts where... um... where they make sense. In this case, you will rather want to utilize dynamic memory allocation and an instance variable:

@interface MyClass: NSObject {
    int *array;
    size_t size;
}

// ... etc ...

- (id)initWithSize:(size_t)n
{
    if (self = [super init]) {
        size = n;
        array = malloc(size * sizeof array[0]);
    }

    return self;
}

// free the allocated memory upon destruction
- (void)dealloc
{
    // ...
    free(array);
    // ...
    [super dealloc];
}

As to why it doesn't really make sense to use a variable-length array as an instance variable: instance variables are part of an object. If you declared a VLA inside an object, then the size of the instance would depend on its initialization. That is not something immediately easy to implement, and it is not the way the Objective-C runtime works. (I'm not saying it's impossible, but it would be very, very impractical.)

All classes have their instance size deduced at compile time (well, mostly... nowadays it's rather the initialization of the runtime system), and it can't be changed later. As a consequence, the size of an object cannot vary from initialization to initialization.

Comments

0

On the assumption that you're writing a properly contained object oriented class, the implementation of your set of scores is not important to the outside world. If that is indeed the case, don't create an int array, create an NSMutableArray instead (and if you want to pre-fill numTestScores_ entries to make things easier later, do that, but there shouldn't be a need for it really).

If you must have an array, you will have to allocate it dynamically by declaring scoreArray to be an int * and using malloc. Be careful here though -- you will have to create a dealloc method in your class to free() the array if it has been created.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.