перечислимое сравнение строк

Я должен сравнить перечисление в целом с одной строкой, таким образом, целое содержание перечисления проверяется.

Требуемый что-то как:

NSString *colString = [[NSString aloc] initWithString:@"threeSilver"];


typedef enum {
oneGreen,
twoBlue, 
threeSilver
}numbersAndColours;

if (colString == numbersAndColours) {
//Do cool stuff
}

Но очевидно я не могу сделать этого, возможно, структура... извините, я плохо знаком с C, помогите?

BTW: Я знаю, что NSString не является C, но полагал, что этим вопросом было больше C, чем Obj-C.

Спасибо

5
задан Vladimir 17 January 2010 в 22:12
поделиться

3 ответа

Хорошая идея, если

  • скорость имеет значение

  • Вас не волнует доступность (программы чтения с экрана, считывающие текст ALT изображения и т.д., все, что пропало при использовании спрайтов)

  • Вас не волнует, что миниатюры не будут напечатаны по умолчанию в любом браузере

  • Вы можете сделать это, не став кошмаром обслуживания (Какое изображение снова было на позиции 461?)

Что касается вашего второго вопроса, вероятно, целесообразно поместить все спрайты в одно или очень мало изображений контейнера, чтобы минимизировать время загрузки.

-121--4716585-

C, ObjC и C++ не поддерживают это напрямую, необходимо создать явное сопоставление.

Пример использования простого подхода C:

typedef struct { 
    numbersAndColours num;
    const char* const str;
} entry;

#define ENTRY(x) { x, #x }

numberAndColours toNum(const char* const s) {
    static entry map[] = {
        ENTRY(oneGreen),
        ENTRY(twoBlue),
        ENTRY(threeSilver)
    }; 
    static const unsigned size = sizeof(map) / sizeof(map[0]);

    for(unsigned i=0; i<size; ++i) {
         if(strcmp(map[i].str, s) == 0) 
             return map[i].num;
    }

    return -1; // or some other value thats not in the enumeration
}

#undef ENTRY

// usage:

assert(toNum("oneGreen") == oneGreen); 
assert(toNum("fooBar") == -1);

Basic Objective-C:

#define ENTRY(x) [NSNumber numberWithInt:x], @#x

NSDictionary* dict = [NSDictionary dictionaryWithObjectsAndKeys:
    ENTRY(oneGreen),
    ENTRY(twoBlue),
    ENTRY(threeSilver),
    nil];

#undef ENTRY

if([dict objectForKey:@"oneGreen"]) {
    // ... do stuff 
}
-121--4950858-

В C для этого необходимо записать функцию. По существу, это будет оператор switch .

char* colour_of(enum numbersAndColours c)
{
    switch( c ) {
    case oneGreen:
        return "oneGreen";
        break;
    case twoBlue:
        return "twoBlue";
        break;
    /* ... */
    default:
        return "donno";
    }
}

Функцию можно использовать следующим образом:

{
    char* nac;
    nac = colour_of(numbersAndColours);
    if( strncmp(colString, nac, colStringLen) == 0 )
        /* ... */
}

Если colString не соответствует ни одному из элементов перечисления, она не будет соответствовать numbersAndColours . Нет необходимости сравнивать его со всеми элементами.

3
ответ дан 14 December 2019 в 13:36
поделиться

C, OBJC и C ++ не поддерживают это напрямую, вы должны создать явное отображение.

Пример, использующий простые C:

typedef struct { 
    numbersAndColours num;
    const char* const str;
} entry;

#define ENTRY(x) { x, #x }

numberAndColours toNum(const char* const s) {
    static entry map[] = {
        ENTRY(oneGreen),
        ENTRY(twoBlue),
        ENTRY(threeSilver)
    }; 
    static const unsigned size = sizeof(map) / sizeof(map[0]);

    for(unsigned i=0; i<size; ++i) {
         if(strcmp(map[i].str, s) == 0) 
             return map[i].num;
    }

    return -1; // or some other value thats not in the enumeration
}

#undef ENTRY

// usage:

assert(toNum("oneGreen") == oneGreen); 
assert(toNum("fooBar") == -1);

Основной объективный подход:

#define ENTRY(x) [NSNumber numberWithInt:x], @#x

NSDictionary* dict = [NSDictionary dictionaryWithObjectsAndKeys:
    ENTRY(oneGreen),
    ENTRY(twoBlue),
    ENTRY(threeSilver),
    nil];

#undef ENTRY

if([dict objectForKey:@"oneGreen"]) {
    // ... do stuff 
}
2
ответ дан 14 December 2019 в 13:36
поделиться

Опыт работы с чрезвычайно ограниченной средой встроенной памяти:

  • используйте буферы фиксированного размера. Не используйте указатели или динамическое распределение, так как у них слишком много накладных расходов.
  • Используйте наименьший тип данных int, который работает.
  • Никогда не используйте рекурсию. Всегда используйте закольцовывание.
  • Не передавайте множество функциональных параметров. Используйте вместо этого глобалы.:)
-121--1158377-

Я не видел такого эффекта - я, конечно, никогда не сталкивался с этим как с узким местом.

Вот очень грубый и готовый тест, который показывает (на моей коробке в любом случае) делегаты на самом деле быть быстрее , чем интерфейсы:

using System;
using System.Diagnostics;

interface IFoo
{
    int Foo(int x);
}

class Program : IFoo
{
    const int Iterations = 1000000000;

    public int Foo(int x)
    {
        return x * 3;
    }

    static void Main(string[] args)
    {
        int x = 3;
        IFoo ifoo = new Program();
        Func<int, int> del = ifoo.Foo;
        // Make sure everything's JITted:
        ifoo.Foo(3);
        del(3);

        Stopwatch sw = Stopwatch.StartNew();        
        for (int i = 0; i < Iterations; i++)
        {
            x = ifoo.Foo(x);
        }
        sw.Stop();
        Console.WriteLine("Interface: {0}", sw.ElapsedMilliseconds);

        x = 3;
        sw = Stopwatch.StartNew();        
        for (int i = 0; i < Iterations; i++)
        {
            x = del(x);
        }
        sw.Stop();
        Console.WriteLine("Delegate: {0}", sw.ElapsedMilliseconds);
    }
}

Результаты (.NET 3,5; .NET 4 .0b2 примерно то же самое):

Interface: 5068
Delegate: 4404

Теперь у меня нет особой веры в то, что это означает, что делегаты действительно быстрее, чем интерфейсы... но это убеждает меня, что они не на порядок медленнее. Кроме того, это практически ничего не делает в рамках метода делегата/интерфейса. Очевидно, что стоимость вызова будет все меньше и меньше различаться, так как вы делаете все больше и больше работы на вызов.

Необходимо быть осторожным в том, что вы не создаете нового делегата несколько раз, где вы бы использовали только один экземпляр интерфейса. Это может вызвать проблему, поскольку это спровоцирует сбор мусора и т.д. Если метод экземпляра используется в качестве делегата в цикле, будет более эффективным объявление переменной делегата вне цикла, создание отдельного делегата и его повторное использование. Например:

Func<int, int> del = myInstance.MyMethod;
for (int i = 0; i < 100000; i++)
{
    MethodTakingFunc(del);
}

эффективнее, чем:

for (int i = 0; i < 100000; i++)
{
    MethodTakingFunc(myInstance.MyMethod);
}

Могла ли это быть проблема, которую вы видели?

-121--960468-

Я не уверен, что понимаю, чего вы пытаетесь достичь, но, возможно, вам захочется взглянуть на NSSet . Если значение colString является определенным, кажется, что вы хотите, чтобы ваша программа делала крутые вещи.

NSSet *numbersAndColors = [NSSet setWithObjects:@"oneGreen", @"twoBlue", @"threeSilver", nil];
NSString *colString = [[NSString alloc] initWithString:@"threeSilver"];

if ([numbersAndColors containsObject:colString])
{
    // do cool stuff
}

NSSet быстрее NSSray , когда нужно знать, существует ли конкретный объект, но один важный аспект NSSet заключается в том, что он не поддерживает порядок объектов. Как правило, он используется, когда вы не заботитесь о порядке и хотите просто проверить, существует ли объект в наборе.

1
ответ дан 14 December 2019 в 13:36
поделиться
Другие вопросы по тегам:

Похожие вопросы: