Objective C初学者问题,铸造&数据初始化

时间:2011-04-21 20:53:22

标签: objective-c

我是Objective C的新手,为我的第一个项目翻译了Actionscript 2中的现有代码。我一直在努力保持我的数据结构简单,这对我来说意味着类似C的数组和字符串而不是NS类。我有一堆对象,其中包含单字节数据字符 - 它们是拼字游戏图块,类型为“A”到“Z”。我想创建一个字母值数组,使得键/值对易于在代码中可读和修改。

在AS2中就是这样:

//init
letterScore = new Object({E:1, S:1, I:1, A:2, R:2 ... Z:10});

//assigned in 2dArray:
map[0]="WORD".split(); 
map[1]="GRID".split(); 
map[2]="HERE".split(); 
map[3]="!# @".split(); 

tile.letter=map[x][y];

//access
if(tile.letter>='A' && tile.letter<='Z'){
  wordScore+= letterScore[tile.letter];
}

在目标C中,我已经以类似的方式在地图中定义和读取,我的tile.letter数据类型是char。有没有办法获得一个像char:int配对这样简单的数据类型的关联数组?它可以在一行代码中完成,类​​似于上面的AS2 init行吗?我正在阅读的书籍建议我必须将值包装为NSNumber,并在char和NSString之间进行转换以访问它们,这看起来很笨拙,但如果我坚持使用类似C的数组,我会失去键的可读性。在Java中,我可以扩展数组类来处理转换,但书中说在Objective C中这是一个坏主意,所以我完全迷失了。

编辑:我认为要避免人们所建议的持续装箱和拆箱(我使用的是这个术语吗?)并保持可读性,我最好的选择是这个可怕的黑客...

#define ASCII_2_ARRAY -65
int letterScore[]={0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5}; 
//                 A  B  C  D  E  F  G  H  I  J  K  L  M  N  O  P  Q  R  S  T  U  V  W  X  Y  Z.

然后访问只是

score += letterScore[tile.letter + ASCII_2_ARRAY];

这样做是否有不利之处?

3 个答案:

答案 0 :(得分:2)

您可以轻松创建NSDictionary,并以各种方式使用您的数据进行初始化。输入像

这样的大量陈述
NSDictionary *dict = [[NSDictionary alloc] initWithObjectsAndKeys:
                              [NSNumber numberWithInt:1], @"A",
                              ...
                              [NSNumber numberWitHInt:10], @"Z",
                              nil];

肯定会奏效。访问这个很容易,比如说,提取一个字母的值:

int score = [[dict objectForKey:theLetter] intValue];

其中theLetter是您正在评分的单词中的一个字母。

一旦你习惯了Objective-C明显的“冗长”,只用几种基本类型就可以做到非常酷。

答案 1 :(得分:2)

NSDictionaryNSArray虽然令人讨厌,却是这片树林中的“简单数据结构”。我建议您将tile.letter更改为NSStrings

如果您要使用Obj-C和(我假设)Cocoa,您将不得不习惯NSDictionary以及它无法处理非对象类型的事实。如Mark所示,NSString只包含一个字符是没有问题的,您可以输入所需的所有文字NSStrings

如果它看起来很有趣,可以把一个“字符”想象成一个长度为1的字符串。这只是有趣的C语言的反转,其中“字符串”只不过是一些串联字符。


回复你的评论:

// Get a random letter from the alphabet
NSString *alphabet = [[NSString alloc] initWithString:@"ABCDEFGHIJKLMNOPQRSTUVWXYZ"];
NSString *letter = [alphabet substringWithRange:NSMakeRange(random() % ALPHABET_LENGTH, 1)];

/ usr / share / dict / words是2.5MB。这是我现在运行的最小Cocoa应用程序的内存占用量的大约10%(预览,没有打开的文档)。三位压缩可以节省半个兆字节。单击按钮使用大致相同;移动窗口会分配更多。您是否测量 NSString版本的性能?

// Create an NSString with one NSString character
NSString *justOneChar = [NSString stringWithString:@"A"];
// Get a char out of an NSString
char c;
// You can do this if you're sure that the character is ASCII
c = (char)[justOneChar characterAtIndex:0];

// Create an NSString using one char
char c = 'A';
unichar uc = c;
NSString * justOneOtherChar = [NSString stringWithCharacters:&uc length:1];
char oc = (char)[justOneOtherChar characterAtIndex:0];

C字符串也需要以nul结尾。

你也可以让Cocoa处理你的英语词典;看看Dave DeLong的DDFileReader class最初将文本文件放到NSString中,然后如果需要,写出来并使用NSArray的{​​{1}}和-initWithContentsOfFile读取它们:`

答案 2 :(得分:1)

由于

  • 你有一个小阵列
  • 数组大小已修复
  • 数组中的每个元素都可以用基本类型
  • 表示
  • 您对数组元素执行算术运算

你的问题是请求你使用C数组。您使用

的想法
int letterScore[]={0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5}; 
//                 A  B  C  D  E  F  G  H  I  J  K  L  M  N  O  P  Q  R  S  T  U  V  W  X  Y  Z.

足够好了。

正如您所注意到的,主要问题是将字符映射到数组中的位置。通常,您可以使用预处理器宏,如:

#define CHAR2INDEX(x) (x - 'A')

score += letterScore[CHAR2INDEX(tile.letter)];

我同意初始化数组并不像AS那样,但是,C又是一种尝试尽可能简单有效的不同语言。也就是说,有其他方法可以初始化数组。

首先,您可以使用以下内容:

int letterScore[] = {
    ['A' - 'A'] = 0,
    ['B' - 'A'] = 1,
    ['C' - 'A'] = 2,
    …
};

或使用之前的宏

int letterScore[] = {
    [CHAR2INDEX('A')] = 0,
    [CHAR2INDEX('B')] = 1,
    [CHAR2INDEX('C')] = 1,
    …
};

如果浪费65 ints不是问题 - 除非您的目标是严重内存限制的设备,否则不应该这样做 - 您可以拥有一个阵列,其中65个第一个元素未被使用。这会让事情更具可读性。例如:

int letterScore[] = { ['A'] = 0, ['B'] = 1, ['C'] = 2, … };

score += letterScore[tile.letter];