2014-01-08 1 views
1

Пусть я перечислил следующий буквальногоВ C, как петлю для каждого из перечисленных буквальных, где литералов do't имеют последовательные значения

enum 
{ 
valueA = 5, 
valueB = 7, 
valueC = 9, 
valueD = 14, 
valueE = 15 
}myEnumType; 

и я хочу Перебери каждый литерал например

for (enumType myValEnum = valueA; myValEnum <= valueE; myValEnum++) 
{ 
    MyFunction(mValEnum); 
} 

будет работать, или я в конечном итоге вызову MyFunction со значениями 5,6,7,8,9,10,11,12,13,14,15?

+0

Я не уверен, но если 'enum' выделяет память смежно, то вы можете использовать указатель на первый элемент' enum' и увеличить его, чтобы получить следующие элементы. –

+4

Что произойдет, если вы попробуете его. – this

+0

@MadHatter 'enum' объявления, подобные размещенному коду, не выделяют * ничего *; они являются псевдонимом типа и не более того. – WhozCraig

ответ

3

Вы не можете этого сделать, нет поддержки для итерации «foreach» по перечислению в C. В принципе, перечисления - это просто псевдонимы целых чисел, с небольшой дополнительной поддержкой.

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

static const myEnumType myEnumMap[] = { valueA, valueB, valueC, valueD, valueE}; 

, то вы можете использовать простую петлю на этот массив:

for(size_t i = 0; i < sizeof myEnumMap/sizeof *myEnumMap; ++i) 
{ 
    const myEnumType ie = myEnumMap[i]; 
    /* process ie */ 
} 

Обратите внимание, что тип myEnumMap является типом вашего перечисления, это не простой «массив целых чисел».

Это недостаток, требующий повторного перечисления перечисления (один раз в собственном определении, затем снова в инициализаторе myEnumMap). Можно обойти это с помощью макро-хитрости (например, X macros), но нет реального удобного/простого способа сделать это.

+0

ОК, это ясно, но мои перечисляемые типы могут содержать 100 элементов. Есть ли процедурный способ присвоить каждому литералу элемент массива без явного ввода вручную в очереди. – ade

0

Вы не можете сделать это с помощью перечисления и петель. Ваш цикл

for (enumType myValEnum = valueA; myValEnum <= valueE; myValEnum++) 
{ 
    MyFunction(mValEnum); 
} 

итерацию от 5 до 15 (5,6,7,8,9,10,11,12,13,14,15). По моим сведениям, указатель на перечисление также не может помочь вам здесь.

2

Непосредственно невозможно пропустить каждый литерал перечисления. Вы можете сделать это косвенно, используя массив целых чисел. Назначьте каждый литерал перечисления элементам массива последовательно, а затем вы можете прокручивать каждый элемент массива.

+0

ОК, это сработало, но есть простой способ присвоения литералов - поскольку мои типы перечислений могут иметь 100 значений. Таким образом, рабочий путь благодаря вам до сих пор (как сделать это как выделенный код здесь, поскольку форматирование не так?): \t int myArray [4] = {valueA, valueB, valueC, valueD}; \t for (int i = 0; i <4; i ++), то есть мне пришлось явно назначать каждое значение по очереди - как это сделать в цикле? – ade

+0

:-(Я не могу найти лучший способ обойти. – iGRJ

1

Я не уверен, если это полезно, но я имел следующие мысли:

Мы должны сохранить возможные значения enum где-то, потому что эта информация не существует в памяти, так что нам нужно что-то как массив с возможными значениями:

enum { 
    valueA = 5, 
    valueB = 7, 
    valueC = 9, 
    valueD = 14, 
    valueE = 15 
} myEnumType; 

const int myEnumTypeArr[] = { 5, 7, 9, 14, 15 }; 

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

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

Так, может быть следующее полезным: Вы можете использовать массив для значений и enum константы в качестве индексов:

enum { valueA, valueB, valueC, dummy } myEnumType; // dummy must stay at last position 
const int myEnumTypeArr[] = { 5, 7, 9 }; 

так что вы используете myEnumTypeArr[valueA], а не valueA непосредственно (с недостатком, что это уже не является константа, например, не может быть использовано в качестве case этикетки) и, возможно, что-то вроде этого (несколько некрасивого, хотя)

static_assert(sizeof myEnumTypeArr/sizeof *myEnumTypeArr == dummy); 

предотвратить вышеупомянутую ошибку.

НТН