【问题标题】:Objective C - Create a multi-dimensional array with the dimensions specified at initialisationObjective C - 使用初始化时指定的维度创建一个多维数组
【发布时间】:2011-06-26 08:09:15
【问题描述】:

我正在尝试创建一个类,其中二维数组的宽度和高度可以在初始化时使用 init 参数动态创建。

我已经在网上浏览了几个小时,但找不到方法。

使用标准 C 语法[][] 不允许使用变量来声明数组。 在我见过的所有示例中,Objective C 中的可变数组都需要在创建时对对象进行硬编码。

有没有一种方法可以在对象中创建一个二维数组,并使用参数来定义创建时的大小?

希望有人能告诉我我错过了什么......

【问题讨论】:

  • 请原谅我的无知,但Objective-C a proper superset of C99 不是——它支持variable-length arrays——而且“标准 C 语法”应该可以正常工作吗?
  • 我无法让它工作......我试图在实例化点将长度分配给数组,但它找不到变量。可能遗漏了一些明显的东西......
  • 你说得对,C99 支持变长数组,char arr[rowVar] 是有效的。但它不支持多维变长数组,char mularr[rowVar][colVar] 无效但 char matrix[rowVar][10] 有效。

标签: objective-c arrays


【解决方案1】:

您可以通过在NSMutableArray 上写一个类别来轻松做到这一点:

@interface NSMutableArray (MultidimensionalAdditions) 

+ (NSMutableArray *) arrayOfWidth:(NSInteger) width andHeight:(NSInteger) height;

- (id) initWithWidth:(NSInteger) width andHeight:(NSInteger) height;

@end

@implementation NSMutableArray (MultidimensionalAdditions) 

+ (NSMutableArray *) arrayOfWidth:(NSInteger) width andHeight:(NSInteger) height {
   return [[[self alloc] initWithWidth:width andHeight:height] autorelease];
}

- (id) initWithWidth:(NSInteger) width andHeight:(NSInteger) height {
   if((self = [self initWithCapacity:height])) {
      for(int i = 0; i < height; i++) {
         NSMutableArray *inner = [[NSMutableArray alloc] initWithCapacity:width];
         for(int j = 0; j < width; j++)
            [inner addObject:[NSNull null]];
         [self addObject:inner];
         [inner release];
      }
   }
   return self;
}

@end

用法:

NSMutableArray *dynamic_md_array = [NSMutableArray arrayOfWidth:2 andHeight:2];

或者:

NSMutableArray *dynamic_md_array = [[NSMutableArray alloc] initWithWidth:2 andHeight:2];

【讨论】:

  • +1 但为了 DRY 和 Cocoa 编码约定,我会将工厂方法主体更改为:return [[[self alloc] initWithWidth:width andHeight:height] autorelease];
  • @e.James 我不知道为什么我没想到!
  • @Jacob Relkin:不用担心。如果所有代码在第一次尝试时都是完美的,那么这个网站将毫无用处;)
  • 我是否认为您已将此方法添加为类别,因此您不必担心对其进行子类化?这意味着您可以使用标准的可变数组语法创建它?
  • 这是一个想法——在实例 init 中有一个对 super 的调用; NSMutableArray 的上级是没有容量设置的 NSArray。这应该是对自我的呼唤而不是对超级的呼唤吗?
【解决方案2】:

这是另一种方式。当然,这仅适用于 int,但代码可以很容易地更改为其他数据类型。

AOMatrix.h:

#import <Cocoa/Cocoa.h>


@interface AOMatrix : NSObject {

@private
    int* matrix_;
    uint columnCount_;
    uint rowCount_;
}

- (id)initWithRows:(uint)rowCount Columns:(uint)columnCount;

- (uint)rowCount;
- (uint)columnCount;

- (int)valueAtRow:(uint)rowIndex Column:(uint)columnIndex;
- (void)setValue:(int)value atRow:(uint)rowIndex Column:(uint)columnIndex;

@end

AOMatrix.m

#import "AOMatrix.h"

#define INITIAL_MATRIX_VALUE 0
#define DEFAULT_ROW_COUNT 4
#define DEFAULT_COLUMN_COUNT 4

/****************************************************************************
 * BIG NOTE:
 * Access values in the matrix_ by matrix_[rowIndex*columnCount+columnIndex]
 ****************************************************************************/
@implementation AOMatrix

- (id)init {
    return [self initWithRows:DEFAULT_ROW_COUNT Columns:DEFAULT_COLUMN_COUNT];
}

- (id)initWithRows:(uint)initRowCount Columns:(uint)initColumnCount {
    self = [super init];
    if(self) {
        rowCount_ = initRowCount;
        columnCount_ = initColumnCount;
        matrix_ = malloc(sizeof(int)*rowCount_*columnCount_);

        uint i;
        for(i = 0; i < rowCount_*columnCount_; ++i) {
            matrix_[i] = INITIAL_MATRIX_VALUE;
        }
//      NSLog(@"matrix_ is %ux%u", rowCount_, columnCount_);
//      NSLog(@"matrix_[0] is at %p", &(matrix_[0]));
//      NSLog(@"matrix_[%u] is at %p", i-1, &(matrix_[i-1]));
    }
    return self;
}

- (void)dealloc {
    free(matrix_);
    [super dealloc];
}

- (uint)rowCount {
    return rowCount_;
}

- (uint)columnCount {
    return columnCount_;
}

- (int)valueAtRow:(uint)rowIndex Column:(uint)columnIndex {
//  NSLog(@"matrix_[%u](%u,%u) is at %p with value %d", rowIndex*columnCount_+columnIndex, rowIndex, columnIndex, &(matrix_[rowIndex*columnCount_+columnIndex]), matrix_[rowIndex*columnCount+columnIndex]);
    return matrix_[rowIndex*columnCount_+columnIndex];
}
- (void)setValue:(int)value atRow:(uint)rowIndex Column:(uint)columnIndex {
    matrix_[rowIndex*columnCount_+columnIndex] = value;
}

@end

【讨论】:

  • 感谢您 - 使用 malloc 确实可以绕过 [] 语法。 dealloc() 可能具有 free() 功能? 'int' 可用于存储对象的 id。我现在正在学习 Objective C,所以我会坚持第一个 - 至少在我弄清楚将对象放置在可变数组中某个位置的语法之后...... :-)
  • 是的。可变长度数组由一些编译器实现,但不是 ANSI C。ANSI C 是否所有自动变量都必须是固定长度的,我认为编译器可以计算将堆栈指针移动到哪里。
【解决方案3】:

这是另一个纯 Objective C 版本

#import foundation.h

@interface ZTwoDimensionalArray : NSObject{

    @package 
    NSMutableArray* _array;
    int _rows, _columns;
}

-(id) initWIthRows:(int)numberOfRows andColumns:(int) numberOfColumns;

-(id) getObjectAtRow:(int) row andColumn:(int)column;

-(void) setObject:(id) anObject atRow:(int) row andColumn:(int)column;
@end



#import "ZTwoDimensionalArray.h"

@implementation ZTwoDimensionalArray

-(id) initWIthRows:(int)numberOfRows andColumns:(int) numberOfColumns{

    if (self = [super init]) {
        _array = [NSMutableArray initWithCapacity:numberOfRows*numberOfColumns];
        _rows = numberOfRows;
        _columns = numberOfColumns;
    }
    return self;
}

-(id) getObjectAtRow:(int) row andColumn:(int)column{

    return [_array objectAtIndex: row*_rows + column];
}

-(void) setObject:(id) anObject atRow:(int) row andColumn:(int)column{

    [_array insertObject:anObject atIndex:row*_rows + column];
}

-(void) dealloc{

    [_array release];
}
@end

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-07-23
    • 2011-04-03
    • 2015-02-26
    • 1970-01-01
    • 2014-05-11
    • 1970-01-01
    • 1970-01-01
    • 2014-12-09
    相关资源
    最近更新 更多