Задача C, вопрос начинающего, кастинг и инициализация данных - PullRequest
0 голосов
/ 22 апреля 2011

Я новичок в Objective C, переводя существующий код из Actionscript 2 для моего первого проекта. Я пытался сохранить свои структуры данных простыми, что для меня означает C-подобные массивы и строки, а не классы NS. У меня есть куча объектов, которые содержат один байт символа данных - это плитки скрэббл, типа от «А» до «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 pairing? Можно ли сделать это в 1 строке кода, аналогичной приведенной выше строке инициализации AS2? Книги, которые я читаю, предполагают, что я должен обернуть значения как 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 ]

2 голосов
/ 22 апреля 2011

NSDictionary и NSArray, хотя и раздражающе многословны, являются «простыми структурами данных» в этой глуши леса.Я бы предложил изменить tile.letter s на NSStrings.

Если вы собираетесь использовать Obj-C и (я полагаю) Cocoa, вам придется привыкнуть к NSDictionary итот факт, что он не может обрабатывать не-объектные типы.Нет проблем с 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,5 МБ.Это примерно 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 тоже должны заканчиваться нулем.

Вы также можете разрешить Cocoa обрабатывать ваш словарь английского языка;см. класс DDFileReader Дейва Делонга , чтобы сначала получить текстовый файл в NSString s, затем, если хотите, запишите их и прочитайте, используя NSArray writeToFile:atomically: и -initWithContentsOfFile: `

2 голосов
/ 22 апреля 2011

Вы можете легко создать 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 голос
/ 22 апреля 2011

Начиная с

  • У вас небольшой массив
  • Размер массива фиксирован
  • Каждый элемент в массиве может быть представлен примитивным типом
  • Вы выполняете арифметические операции с элементами массива

Ваша проблема заключается в том, что вы умоляете вас использовать массив 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];
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...