Перейти к содержимому

Как перебрать enum c

  • автор:

foreach() для enum

Если мощность перечисления известна (а она, разумеется, известна — главное, не забывать подправлять константу при изменении перечисления), то можно, например, так:

const int FruitsCount = 3; public void EnumerateAllFruits() < for (Fruits fruit = 0; (int) fruit < FruitsCount; fruit++) < DoSomething(fruit); >> 

Это сработает, потому как по умолчанию элементам перечисления соответствуют целые числа от 0 до N-1 (если продолжите операцию fruit++, обнаружите, что никакой ошибки не произойдет, а fruit начнёт принимать неименованные значения 3, 4, . )

Как перебрать все елементы enum’a?

Или как проверить, является ли число значением какого-либо елемента enum’a?

#1
22:38, 5 авг 2007

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

#2
22:42, 5 авг 2007

brigadir
enum — это что-то типа создания нового типа данных. а теперь наводящий вопрос: как не зная границы int’а перебрать все его элементы? 😉

#3
22:57, 5 авг 2007

>>enum — это что-то типа создания нового типа данных
его даже типом то назвать нельзя. т.к. осбо с ним не поработашь. одинм слово перечисле и все. 🙂

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

#4
23:34, 5 авг 2007

Никак. Потребуется самостоятельно хранить список всех возможных значений. Вобще слабо себе представляю, зачем может потребоваться перебрать все значения енума. Если нужно сильно, часто и много, то можно сильно облегчить себе жизнь, написав простенький кодо генератор, что то вроде файл со списком значений на входе

11 foo 99 bar 17 dummy

исходник со всеми определениями на выходе.

enum MyEnum < foo=11, dummy=17, bar=99 >; static const int MyEnumNumMembers = 3; static const int MyEnumValues[3] = 11, 17, 99>;

#5
0:08, 6 авг 2007

Массив и непарь себе мозги!
enum — это просто перечисления,если неошибаюсь по научному:»символьная константа»

#6
0:33, 6 авг 2007

В С++ — никак. Или кодогенератор, как сказал Конишуа, или же массив енумов сделать руками-

static MyEnum MyEnumValues[] = ;

и ассерты в каких-то местах, что при использовании енума он есть в массиве (что бы сберечься от забывания).

Есть ещё очень громоздкие трики с препроцессором, которые на самом деле очень неудобная кодогенерация.

  • SimpleProger
  • Постоялец

#7
1:11, 6 авг 2007

всегда недопонимал чем не устраивают структуры.

если надо с энумами так работать.

#8
3:15, 6 авг 2007

SimpleProger
>всегда недопонимал чем не устраивают структуры.
>если надо с энумами так работать.

Структуры громоздки. Вместо того чтобы писать MyGreatestArray[MyAwesomeEnum].myfoobarkinglyAmazingVar нужно писать MyGreatestArray[MyStructSuck.MyAwesomeEnum].myfoobarkinglyAmazingVar.

А вообще, обидно, что в C++ нет какого-то механизма это дело отслеживать. Хотя бы точно бы знать, что при создании энума им точно присвоятся значения 0,1,2.

#9
3:38, 6 авг 2007

>>Структуры громоздки.
при правильной организации кода структуры могут выглядеть гроздо изящней и если еще использовать шаболы.
>>Хотя бы точно бы знать, что при создании энума им точно присвоятся значения 0,1,2
гы. а у тебя были случае когда так создаешь енум и они все разные были??

#10
4:19, 6 авг 2007

>Хотя бы точно бы знать, что при создании энума им точно присвоятся значения 0,1,2.
Это точно.

enum MyEnum < foo, dummy, bar, MyEnum_last >; for ( i = 0; i MyEnum_last; ++i)

Если тип i — это int, то тогда когда надо его надо сконвертировать в MyEnum.
Если тип i — это MyEnum, то инкремент ++i выглядит как (i = (MyEnum)(i + 1), i) и лучше загнать его в отдельную функцию.

#11
10:28, 6 авг 2007

SimpleProger
Не врубился почему ты противопоставляешь енамы структурам.

#12
12:10, 6 авг 2007

_Winnie
>Это точно.

Это гарантируется стандартом? Есть у меня подозрение, что я помню энумы, у которых в результате преобразования в int оказывалось значение 65xxx. Хотя, это мог быть какой-то локальный глюк завязанный на другой глюк.

#13
13:20, 6 авг 2007

jaguard
Гарантируется, точно.


The identifiers in an enumerator-list are declared as constants, and can appear wherever constants are
required. An enumerator-definition with = gives the associated enumerator the value indicated by the
constant-expression. The constant-expression shall be of integral or enumeration type. If the first
enumerator has no initializer, the value of the corresponding constant is zero. An enumerator-definition
without an initializer gives the enumerator the value obtained by increasing the value of the previous
enumeratorby one
.

#14
16:38, 6 авг 2007

бугого а в C# можна)))
*показывает язык*)

Как перебрать enum c

Кроме примитивных типов данных в языке программирования C# есть такой тип как enum или перечисление . Перечисления представляют набор логически связанных констант.

Объявление перечисления происходит с помощью оператора enum :

enum название_перечисления < // значения перечисления значение1, значение2, . значениеN >

После оператора enum идет название перечисления. И затем в фигурных скобках через запятую перечисляются константы перечисления.

Определим простейшее перечисление:

enum DayTime

Здесь определено перечисление DayTime, которое имеет четыре значения: Morning, Afternoon, Evening и Night

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

const DayTime dayTime = DayTime.Morning;

Далее в программе мы можем использовать подобные переменные/константы/параметры как и любые другие:

DayTime dayTime = DayTime.Morning; if(dayTime == DayTime.Morning) Console.WriteLine(«Доброе утро»); else Console.WriteLine(«Привет»); enum DayTime

Хранение состояния

Зачастую переменная перечисления выступает в качестве хранилища состояния, в зависимости от которого производятся некоторые действия:

DayTime now = DayTime.Evening; PrintMessage(now); // Добрый вечер PrintMessage(DayTime.Afternoon); // Добрый день PrintMessage(DayTime.Night); // Доброй ночи void PrintMessage(DayTime dayTime) < switch (dayTime) < case DayTime.Morning: Console.WriteLine("Доброе утро"); break; case DayTime.Afternoon: Console.WriteLine("Добрый день"); break; case DayTime.Evening: Console.WriteLine("Добрый вечер"); break; case DayTime.Night: Console.WriteLine("Доброй ночи"); break; >> enum DayTime

Здесь метод PrintMessage() в качестве параметра принимает значение типа перечисления DayTime и зависимости от этого значения выводит определенное приведение.

DoOperation(10, 5, Operation.Add); // 15 DoOperation(10, 5, Operation.Subtract); // 5 DoOperation(10, 5, Operation.Multiply); // 50 DoOperation(10, 5, Operation.Divide); // 2 void DoOperation(double x, double y, Operation op) < double result = op switch < Operation.Add =>x + y, Operation.Subtract => x — y, Operation.Multiply => x * y, Operation.Divide => x / y >; Console.WriteLine(result); > enum Operation

Здесь определено перечисление Operation, которое представляет арифметические операции. Каждый тип операций определен в виде одной из констант перечисления. И также определен метод DoOperation() , который в качестве параметров принимает два числа и тип операции в виде константы перечисления и в зависимости от этого типа возвращает из конструкции switch результат определенной операции.

Тип и значения констант перечисления

Константы перечисления могут иметь тип. Тип указывается после названия перечисления через двоеточие:

enum Time : byte

Тип перечисления обязательно должен представлять целочисленный тип (byte, sbyte, short, ushort, int, uint, long, ulong). Если тип явным образом не указан, то по умолчанию используется тип int .

Тип влияет на значения, которые могут иметь константы. По умолчанию каждому элементу перечисления присваивается целочисленное значение, причем первый элемент будет иметь значение 0, второй — 1 и так далее. Например, возьмем выше определенное DayTime:

DayTime now = DayTime.Morning; Console.WriteLine((int) now); // 0 Console.WriteLine((int) DayTime.Night); // 3 enum DayTime

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

(int) DayTime.Night // 3

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

DayTime now = 2; // ! Ошибка

Можно также явным образом указать значения элементов, либо указав значение первого элемента:

enum DayTime < Morning = 3, // каждый следующий элемент по умолчанию увеличивается на единицу Afternoon, // этот элемент равен 4 Evening, // 5 Night // 6 >

Но можно и для всех элементов явным образом указать значения:

enum DayTime

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

enum DayTime

Как перебрать enum c

Задача следующая:
Есть перечисление с полностью определенными элементами

 enum LineWeight < kLnWt000 = 0, kLnWt005 = 5, kLnWt009 = 9, kLnWt013 = 13, kLnWt015 = 15, kLnWt018 = 18, kLnWt020 = 20, kLnWt025 = 25, kLnWt030 = 30, kLnWt035 = 35, kLnWt040 = 40, kLnWt050 = 50, kLnWt053 = 53, kLnWt060 = 60, kLnWt070 = 70, kLnWt080 = 80, kLnWt090 = 90, kLnWt100 = 100, kLnWt106 = 106, kLnWt120 = 120, kLnWt140 = 140, kLnWt158 = 158, kLnWt200 = 200, kLnWt211 = 211, kLnWtByLayer = -1, kLnWtByBlock = -2, kLnWtByLwDefault = -3 >;

Мне требуется занести все числовые значения(кроме отрицательных) в массив, с целью дальнейшого его использования.
Например, надо найти приближенное значение:
дано х=51
результат должен быть result=kLnWt050

Я думаю использовать пары или приведение типов. Проблема лишь в том что бы пройтись циклом по элементам и занести из в массив. Как это сделать? Очень не хотелось бы хардкодить.

Re: Цикл по enum. Как пройтись по элементам перечисления?

От: jazzer Skype: enerjazzer
Дата: 02.06.08 08:22
Оценка:

Здравствуйте, DIMEDROLL, Вы писали:

DIM>Задача следующая:
DIM>Есть перечисление с полностью определенными элементами

DIM>

DIM> enum LineWeight DIM> < DIM>kLnWt000 = 0, DIM> kLnWt005 = 5, DIM> kLnWt009 = 9, DIM> kLnWt013 = 13, DIM> kLnWt015 = 15, DIM> kLnWt018 = 18, DIM> kLnWt020 = 20, DIM> kLnWt025 = 25, DIM> kLnWt030 = 30, DIM> kLnWt035 = 35, DIM> kLnWt040 = 40, DIM> kLnWt050 = 50, DIM> kLnWt053 = 53, DIM> kLnWt060 = 60, DIM> kLnWt070 = 70, DIM> kLnWt080 = 80, DIM> kLnWt090 = 90, DIM> kLnWt100 = 100, DIM> kLnWt106 = 106, DIM> kLnWt120 = 120, DIM> kLnWt140 = 140, DIM> kLnWt158 = 158, DIM> kLnWt200 = 200, DIM> kLnWt211 = 211, DIM> kLnWtByLayer = -1, DIM> kLnWtByBlock = -2, DIM> kLnWtByLwDefault = -3 DIM> >; DIM>

DIM>Мне требуется занести все числовые значения(кроме отрицательных) в массив, с целью дальнейшого его использования.
DIM>Например, надо найти приближенное значение:
DIM>дано х=51
DIM>результат должен быть result=kLnWt050

Не очень понял, каким образом у тебя будет производиться поиск.

DIM>Я думаю использовать пары или приведение типов. Проблема лишь в том что бы пройтись циклом по элементам и занести из в массив. Как это сделать? Очень не хотелось бы хардкодить.

Заюзай макросы.
Вызов первого макроса будет генерить енум, а вызов второго с тем же аргументом — массив.

jazzer (Skype: enerjazzer) Ночная тема для RSDN
Автор: jazzer
Дата: 26.11.09

You will always get what you always got If you always do what you always did

Re[2]: Цикл по enum. Как пройтись по элементам перечисления?

От: DIMEDROLL
Дата: 02.06.08 08:35
Оценка:

Здравствуйте, jazzer, Вы писали:

J>Заюзай макросы.
J>Вызов первого макроса будет генерить енум, а вызов второго с тем же аргументом — массив.

Поиск производится будет простым перебором:

int x = 51; double min = ABS (array[0] - x); int minIndex = 0; for(int i = 1; i < array.size(); ++i) < if ( (ABS(array[i] - x) < min ) < min = (ABS(array[i] - x); minIndex = i; >>

Приведи пример макроса. Перечисление из внешней библиотеки, изменять его я не имею права.

Re[3]: Цикл по enum. Как пройтись по элементам перечисления?

От: Аноним
Дата: 02.06.08 08:51
Оценка:

Здравствуйте, DIMEDROLL, Вы писали:

DIM>Перечисление из внешней библиотеки, изменять его я не имею права.

В любом случае тебе придется где-то регистрировать элементы enum.
На самом деле совершенно не важно, сделаешь ли ты это с помощью макро
или руками захордкодишь.
Нету в С++ полной информации о типах и в любом случае придется приделывать что-то,
что в конечном итоге выльется в банальный:

LineWeigh lineWeighRegistry[] =

Re[3]: Цикл по enum. Как пройтись по элементам перечисления?

От: jazzer Skype: enerjazzer
Дата: 02.06.08 09:14
Оценка:

Здравствуйте, DIMEDROLL, Вы писали:

DIM>Поиск производится будет простым перебором:

Понятно.

DIM>Приведи пример макроса. Перечисление из внешней библиотеки, изменять его я не имею права.

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

результат будет такой:

int a[212] = <>; a[0] = 0; a[5] = 5; a[9] = 9; //. и т.д. a[211] = 211;
int a[212] = <>; a[kLnWt000] = kLnWt000; a[kLnWt005] = kLnWt005; //. a[kLnWt211] = kLnWt211;

jazzer (Skype: enerjazzer) Ночная тема для RSDN
Автор: jazzer
Дата: 26.11.09

You will always get what you always got If you always do what you always did

Re[3]: Цикл по enum. Как пройтись по элементам перечисления?

От: Кодт
Дата: 02.06.08 10:44
Оценка:

Здравствуйте, DIMEDROLL, Вы писали:

DIM>Приведи пример макроса. Перечисление из внешней библиотеки, изменять его я не имею права.

Если библиотека не меняется, то проще всего скопипастить имена элементов, а дальше всё просто

static LineWeight const values[] = < kLnWt000, kLnWt005, . >; // сюда копипастим static size_t const num_values = _countof(values); LineWeight getNearest(int value) < LineWeight *p = std::lower_bound(values, values+num_values, value); // если, конечно, значения упорядочены // проверяем краевые условия if(p == values) return *p; if(p == values+num_values) return *(p-1); // в общем случае, выполняется неравенство // *(p-1) < value  if(value-*(p-1) < *p-value) return *(p-1); else return *p; >

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *