Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Использование DWORD как набора флагов 
V
    Опции темы
artsb
Дата 4.2.2009, 00:35 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2280
Регистрация: 17.7.2007
Где: центр Вселенной

Репутация: 39
Всего: 64



Всем привет!

В программе нужно использовать набор флагов (около 10, а потом может и больше). Просто создать кучу bool'ов и взиться с ними - желания нет. Вспомнил как в Билдере и WinAPI используется DWORD для хранения флагов.
Стал разбираться: взвести флаг можно с помощью операции - '|'; проверить взведён или нет - '&'. А вот как его сбросить? И правильно ли я понял две предыдущие операции?
Подскажите, где об этом можно почитать, а то даже не знаю, что в поиске писать... smile


--------------------
Чем отличается умный человек от мудрого?
Умный - выпутается из любой ситуации.
Мудрый - просто в неё не попадёт.
PM MAIL   Вверх
UniBomb
Дата 4.2.2009, 00:58 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок
***
Награды: 1



Профиль
Группа: Завсегдатай
Сообщений: 1754
Регистрация: 24.10.2006
Где: Санкт-Петербург

Репутация: 3
Всего: 97



Ты всё понял неправильно. & - это операция "и", а | - это операция "или". Подерживается чуть ли не всеми компиляторами чуть ли не всех языков. Смысл тут таков - эта операция действует по известной таблице истинности, пораспрашивать о которой ты сможеш у гугла.

Второй момент - если потребуеться больше 8 флагов, то и DWORD ьебя не выручит, используй двухбайтовую переменную (причём тип в принципе не важен).

И в заключение:

Код

unsigned int flags;

//установить бит:
flags |= 1 << 3; //где 3 - это номер бита, подставиш какой нужно

//сбросить бит:
flags &= ~(1 << 4); //где 4 - это номер бита, подставиш какой нужно

//Проверить бит:
if(flags&(1 << 5))
 ;//флаг установлен
else
 ;//флаг сброшен



--------------------
PM MAIL ICQ Skype   Вверх
Comm
Дата 4.2.2009, 01:10 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 269
Регистрация: 31.8.2007
Где: Санкт-Петербург

Репутация: 2
Всего: 1



А что означает цифра "1"  в выражении 
Код

flags |= 1 << 3;



--------------------
=)))))
user posted image
PM MAIL ICQ   Вверх
dumb
Дата 4.2.2009, 03:41 (ссылка) |    (голосов:4) Загрузка ... Загрузка ... Быстрая цитата Цитата


sceloglauxalbifacies
****


Профиль
Группа: Экс. модератор
Сообщений: 2929
Регистрация: 16.6.2006

Репутация: 32
Всего: 158



Цитата(Comm @  4.2.2009,  01:10 Найти цитируемый пост)
А что означает цифра "1"
она означает число 1.

Цитата(UniBomb @  4.2.2009,  00:58 Найти цитируемый пост)
Второй момент - если потребуеться больше 8 флагов, то и DWORD ьебя не выручит, используй двухбайтовую переменную
smile
тоже, бывает, расслабляюсь, но к клавиатуре в такие моменты не тянет... smile
DWORD - 32 бита, "двухбайтовая переменная" - WORD - 16 бит.
PM MAIL   Вверх
UniBomb
Дата 4.2.2009, 09:18 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок
***
Награды: 1



Профиль
Группа: Завсегдатай
Сообщений: 1754
Регистрация: 24.10.2006
Где: Санкт-Петербург

Репутация: 3
Всего: 97



Цитата(dumb @  4.2.2009,  03:41 Найти цитируемый пост)
тоже, бывает, расслабляюсь... DWORD - 32 бита

Сорри, вот тут я ступил))) У меня почему то DWORD всё время вызывает странные ассоциации.  smile 


Цитата(Comm @  4.2.2009,  01:10 Найти цитируемый пост)
А что означает цифра "1"  в выражении 

Выражение "1 << 3" означает число "1", сдвинутое на три бита вправо.



--------------------
PM MAIL ICQ Skype   Вверх
mrbrooks
Дата 4.2.2009, 09:23 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


трололомен
****


Профиль
Группа: Завсегдатай
Сообщений: 4259
Регистрация: 4.10.2006
Где: Дол Гулдур

Репутация: 167
Всего: 306



Цитата(artsb @  4.2.2009,  00:35 Найти цитируемый пост)
Просто создать кучу bool'ов и взиться с ними - желания нет.

как вариант я бы порекомендовал заюзать enum.

в принципе имхо достаточно просто выполнять побитовые операции над DWORD - но он 32 бита, а тебе надо всего 10. Можно обойтись и двухбайтовым типом. Работать либо смещением, либо через std::bitset
PM MAIL   Вверх
artsb
Дата 4.2.2009, 10:39 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2280
Регистрация: 17.7.2007
Где: центр Вселенной

Репутация: 39
Всего: 64



Спасибо за ответы.
Цитата(UniBomb @  4.2.2009,  00:58 Найти цитируемый пост)
Ты всё понял неправильно.

Значит изучение дискретной математики не прошли даром. smile

Но мне хотелось бы это реализовать наподобии как в функции MessageBox:
Код

MessageBox(NULL, "Text", "Caption", MB_OK | MB_ICONINFORMATION);

Дело в том, что эти флаги я использую в классе, а класс в программе. Не хочется открывать прямой доступ к флагам. Хочется реализовать доступ через функции, например:
Код

void SetFlags(DWORD Flags);
void UnSetFlags(DWORD Flags);
bool IsSetFlags(DWORD Flags);

и чтобы устанавливать так:
Код

SetFlags(MY_FLAG1 | MY_FLAG2);


Цитата(mrbrooks @  4.2.2009,  09:23 Найти цитируемый пост)

как вариант я бы порекомендовал заюзать enum.

Можно подробнее. Точнее, то что это перечисление я знаю. Надо вспомнить как с ним работать. smile



Это сообщение отредактировал(а) artsb - 4.2.2009, 10:40


--------------------
Чем отличается умный человек от мудрого?
Умный - выпутается из любой ситуации.
Мудрый - просто в неё не попадёт.
PM MAIL   Вверх
mrbrooks
Дата 4.2.2009, 11:00 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


трололомен
****


Профиль
Группа: Завсегдатай
Сообщений: 4259
Регистрация: 4.10.2006
Где: Дол Гулдур

Репутация: 167
Всего: 306



Цитата(artsb @  4.2.2009,  10:39 Найти цитируемый пост)
Можно подробнее. Точнее, то что это перечисление я знаю. Надо вспомнить как с ним работать. smile


Перечисления особенно хороши со множеством.

Код

enum prop{propA, propB, propC, propD, propE};
Set<prop,propA,propE>pr;
pr << propA << propB; // добавление флагов 
pr >> propB // удаление флага propB
pr.Clear(); //очистка множества


Добавлено через 4 минуты и 20 секунд
для проверки - есть ли данный флаг во множестве - используется метод Contains

Это сообщение отредактировал(а) mrbrooks - 4.2.2009, 11:01
PM MAIL   Вверх
Comm
Дата 4.2.2009, 11:09 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 269
Регистрация: 31.8.2007
Где: Санкт-Петербург

Репутация: 2
Всего: 1



Цитата

она означает число 1.

Остроумно  smile 

Это сообщение отредактировал(а) Comm - 4.2.2009, 11:11


--------------------
=)))))
user posted image
PM MAIL ICQ   Вверх
artsb
Дата 4.2.2009, 18:32 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2280
Регистрация: 17.7.2007
Где: центр Вселенной

Репутация: 39
Всего: 64



Ну с перечислением понятно. А как насчёт первого варианта? Как это можно организовать через функции, например, как у MessageBox.


--------------------
Чем отличается умный человек от мудрого?
Умный - выпутается из любой ситуации.
Мудрый - просто в неё не попадёт.
PM MAIL   Вверх
Rrader
  Дата 4.2.2009, 19:43 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Inspired =)
***


Профиль
Группа: Экс. модератор
Сообщений: 1535
Регистрация: 7.5.2005

Репутация: 13
Всего: 191



artsb, для этого нужно выполнить одно условие - не допускать перекрытия флагов, математически. А для этого их можно дефинировать так:
Код

#define MY_FLAG_1 (1UL << 0)  
#define MY_FLAG_2 (1UL << 1)
#define MY_FLAG_3 (1UL << 2)
#define MY_FLAG_4 (1UL << 3)
#define MY_FLAG_5 (1UL << 4)
#define MY_FLAG_6 (1UL << 5)
// etc    

Теперь пользуйся ими как обычно:
Код

MyFunc(MY_FLAG_1 | MY_FLAG_3 | MY_FLAG_2 & ~MY_FLAG_2 | MY_FLAG_4);

Для включения флага - OR (|), для исключения - AND NOT (&~)
Для проверки в функции применять можно AND:
Код

void MyFunc(DWORD dwFlags)
{
    if (dwFlags & MY_FLAG_1) ShowMessage("MY_FLAG_1");
    if (dwFlags & MY_FLAG_2) ShowMessage("MY_FLAG_2");
    if (dwFlags & MY_FLAG_3) ShowMessage("MY_FLAG_3");
    if (dwFlags & MY_FLAG_4) ShowMessage("MY_FLAG_4");
}


Это сообщение отредактировал(а) Rrader - 6.2.2009, 06:17


--------------------
Let's do this quickly!
Rest in peace, Vit!
PM MAIL Skype   Вверх
artsb
Дата 5.2.2009, 22:54 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2280
Регистрация: 17.7.2007
Где: центр Вселенной

Репутация: 39
Всего: 64



Спасибо всем за помощь!

Rrader, что значит UL? Здесь:
Код

#define MY_FLAG_1 (1UL << 0) 


Значит, в моём случае функции будут выглядеть так:
Код

#define MY_FLAG1 (1UL << 0)
#define MY_FLAG2 (1UL << 1)
#define MY_FLAG3 (1UL << 2)
#define MY_FLAG4 (1UL << 3)
#define MY_FLAG5 (1UL << 4)

WORD myFlags;

void SetFlags(WORD uFlags)
{
  if(!uFlags) return;
  if(uFlags & MY_FLAG1) myFlags |= MY_FLAG1;
  if(uFlags & MY_FLAG2) myFlags |= MY_FLAG2;
  if(uFlags & MY_FLAG3) myFlags |= MY_FLAG3;
  if(uFlags & MY_FLAG4) myFlags |= MY_FLAG4;
  if(uFlags & MY_FLAG5) myFlags |= MY_FLAG5;
}

void UnSetFlags(WORD uFlags)
{
  if(!uFlags) return;
  if(uFlags & MY_FLAG1) myFlags &= ~MY_FLAG1;
  if(uFlags & MY_FLAG2) myFlags &= ~MY_FLAG2;
  if(uFlags & MY_FLAG3) myFlags &= ~MY_FLAG3;
  if(uFlags & MY_FLAG4) myFlags &= ~MY_FLAG4;
  if(uFlags & MY_FLAG5) myFlags &= ~MY_FLAG5;
}

bool IsSetFlag(WORD uFlag)
{
  return myFlags & uFlag;
}

А используем, например, так:
Код

SetFlags(MY_FLAG2 | MY_FLAG5);
if(IsSetFlag(MY_FLAG4)) ShowMessage("Flag 4");
UnSetFlags(MY_FLAG2 | MY_FLAG4);

ЗЫ надо бы где-то почитать про работу с битами. Смещение там и т.д. Не подскажите, где можно найти статьи про это?

Это сообщение отредактировал(а) artsb - 5.2.2009, 22:56


--------------------
Чем отличается умный человек от мудрого?
Умный - выпутается из любой ситуации.
Мудрый - просто в неё не попадёт.
PM MAIL   Вверх
dumb
Дата 6.2.2009, 00:46 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


sceloglauxalbifacies
****


Профиль
Группа: Экс. модератор
Сообщений: 2929
Регистрация: 16.6.2006

Репутация: 32
Всего: 158



пару замечаний: даже если кол-во флагов меньше 16, не стоит использовать WORD, так как это "неродная" разрядность для 32х-битного кода,  в следствие чего и код разбухает(за счет префиксов, но, надо отметить, разбухает весьма незначительно в текущих реалиях) и скорость снижается(опять же, незначительно).
посему, так будет лучше:
Код

DWORD myFlags;
DWORD SetFlags(DWORD uFlags) 
{  
  return (myFlags |= uFlags);
}
DWORD UnsetFlags(DWORD uFlags)
{
  return (myFlags &= ~uFlags);
}
BOOL IsSetFlags(DWORD uFlags)
{
  return (myFlags & uFlags) == uFlags;
}


Цитата(artsb @  5.2.2009,  22:54 Найти цитируемый пост)
что значит UL?
суффикс, определяющий тип числовой константы. unsigned long. (F1, Предметный указатель, constants, long)

Цитата(artsb @  5.2.2009,  22:54 Найти цитируемый пост)
где можно найти статьи про это?
http://www.google.ru/search?q=двоичная+система+счисления
PM MAIL   Вверх
math64
Дата 6.2.2009, 10:48 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2505
Регистрация: 12.4.2007

Репутация: 4
Всего: 72



Вместо #define можно использовать enum:
Код

enum MY_FLAGS {
 MY_FLAG_1 = (1UL << 0) ,
 MY_FLAG_2 = (1UL << 1),
 MY_FLAG_3 = (1UL << 2),
 MY_FLAG_4 = (1UL << 3),
 MY_FLAG_5 = (1UL << 4),
 MY_FLAG_6 = (1UL << 5)
};

Так удобнее, отладчик будет знать значения флагов и при необходимости можно ограничить видимость флагов разместив их в namespace или в классе.

Добавлено через 3 минуты и 26 секунд
Ещё упрощение кода:
Код

WORD myFlags;

void SetFlags(WORD uFlags)
{
  if(uFlags == 0) return;
  uFlags &= MY_FLAG1 | MY_FLAG2 | MY_FLAG3 | MY_FLAG4 | MY_FLAG5;
  myFlags |= uFlags;
}

PM   Вверх
Rrader
  Дата 6.2.2009, 18:14 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Inspired =)
***


Профиль
Группа: Экс. модератор
Сообщений: 1535
Регистрация: 7.5.2005

Репутация: 13
Всего: 191



math64dumb дело говорит.

Это сообщение отредактировал(а) Rrader - 6.2.2009, 18:15


--------------------
Let's do this quickly!
Rest in peace, Vit!
PM MAIL Skype   Вверх
Ответ в темуСоздание новой темы Создание опроса
Правила форума "С++ Builder"
Rrader

Запрещается!

1. Публиковать ссылки на вскрытые компоненты

2. Обсуждать взлом компонентов и делиться вскрытыми компонентами

  • Литературу по С++ Builder обсуждаем здесь
  • Действия модераторов можно обсудить здесь
  • С просьбами о написании курсовой, реферата и т.п. обращаться сюда
  • Настоятельно рекомендуем заглянуть в DRKB (Delphi Russian Knowledge Base) - крупнейший в рунете сборник материалов по Дельфи


Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Rrader.

 
1 Пользователей читают эту тему (1 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C++ Builder | Следующая тема »


 




[ Время генерации скрипта: 0.1020 ]   [ Использовано запросов: 21 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.