Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > C/C++: Общие вопросы > исключающие маски


Автор: zss 30.4.2009, 22:36
есть маски
Код

enym MASKS
{
    a = 0x00000001,
    b = 0x00000002,
    c = 0x00000004
}


они приходят в любой комбинации. Но маска "а", должна исключать маски "b" и "с".
То есть, если пришла "a", то "b" и "c" должны сброситься, или если пришла "b" или "c". то должна сброситься "a".

Можно ли их как организовать, чтоб при побитовом сложении осуществлялось это исключение. Или только руками проверять ?

Автор: mes 30.4.2009, 23:07
Цитата(zss @  30.4.2009,  21:36 Найти цитируемый пост)
enym

enum  smile 

Цитата(zss @  30.4.2009,  21:36 Найти цитируемый пост)
они приходят в любой комбинации. Но маска "а", должна исключать маски "b" и "с".
То есть, если пришла "a", то "b" и "c" должны сброситься, или если пришла "b" или "c". то должна сброситься "a".

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

Автор: zss 30.4.2009, 23:09
Цитата(mes @  30.4.2009,  23:07 Найти цитируемый пост)
Присваивайте значение пришедшей маски, и предыдущее значение сбросится

как это так ?

Автор: mes 30.4.2009, 23:22
Цитата(zss @  30.4.2009,  22:09 Найти цитируемый пост)

как это так ? 

Как я понял у Вас есть переменная которая должна быть равна значению одной маски, а не их сочетанию.
Ну так присваивайте нужное значение и все. Или вопрос в чем то другом ? тогда перефразируйте плиз, чтоб можно было понять, чтоб Вам требуется.
Можно попробовать подкрепить вопрос примером.  smile 

Автор: zss 1.5.2009, 00:33
Цитата(mes @  30.4.2009,  23:22 Найти цитируемый пост)
Как я понял у Вас есть переменная которая должна быть равна значению одной маски, а не их сочетанию.

нет - "b" и "с" сочетаться могут

Автор: MAKCim 1.5.2009, 10:09
Цитата(zss @  30.4.2009,  22:36 Найти цитируемый пост)
если пришла "b" или "c"

из-за "или" имхо нельзя

Автор: mes 1.5.2009, 10:16
Цитата(zss @  30.4.2009,  23:33 Найти цитируемый пост)
нет - "b" и "с" сочетаться могут 

ну полностью задачу, так и не хотите осветить.
Можно например 
1. чтоб маска A включала в себя маски B и C, логичнее сказать для задачи использовать не { А, B, C },  а { ABC, B, C }
2. завести дополнительно исключающие маски :
Код

enum Mask
{
    Mask_A = 1 << 0,
    Mask_B = 1 << 1,
    Mask_C = 1 << 2,
    Mask_XA = Mask_B | Mask_C,
    Mask_XB=  Мask_A,
    Mask_XC = Mask_A
};


тогда установка битов по маске будет провoдиться в два действия. 
Код

bits &= ~XA; 
bits |=A;


Цитата(zss @  30.4.2009,  21:36 Найти цитируемый пост)
То есть, если пришла "a", то "b" и "c" 

кстати выражение "пришла маска" имхо, не очень удачнoe, так как сама маска никуда не ходит, 
она сидит себе тихо и проверяет пришедшие значения на нужное сочетание битов. smile


Автор: math64 1.5.2009, 10:29
Код

enum Bit {
bitA, bitB, bitC
};
enum Mask {
maskA = 1 << bitA,
maskB = 1 << bitB,
maskC = 1 << bitC
};

class BitCombination {
static int disables[];
int value;
public:
   BitCombination();
   BitCombination(const BitCombination&);
   BitCombination& operator=(const BitCombination&);
   int Value() { return value; }
   BitCombination& SetBit(Bit bit);
   BitCombination& SetBits(int bits);
   BitCombination& ClrBit(Bit bit);
};

int BitCombination::disables[] = { maskB | maskC, maskA, maskA };
BitCombination& BitCombination::SetBit(Bit bit) {
  value &= ~disables[bit];
  value |= 1 << bit;
  return *this;
}



Добавлено через 6 минут и 24 секунды
Если disables сделать обычным (нестатичным), правила запретов можно менять динамически для каждого экземпляра

Автор: zss 1.5.2009, 13:27
Цитата(mes @  1.5.2009,  10:16 Найти цитируемый пост)
ну полностью задачу, так и не хотите осветить.


ну смысл такой.
Есть генератор файлов. Он поставляет файлы различных типов - либо они архивированные - либо нет. Но в один момент времени он поставляет файлы одного типа. Также в процессе работы он может поменять тип генерируемых файлов.
1. Неизвестный тип
2. Файл открыт
3. Файл архивирован
    3.1. Архивирован Неизвестным архиватором
    3.1. Zip
    3.3. Rar

Задача - описать генератор файлов. Сложность в том, что их одного файла определить этого нельзя.
Нужно накапливать свойства.

Усложняется еще и тем, что для пользователя Zip и Rar это схожие архиваторы (можно разархивировать одним приложением), но типы эти разные. То есть Zip дополняет Rar. Также можно определить, что файл архивирован, но непонятно чем.

У меня получились следующие маски
Код

enum MASKS
{
    UNKNOWN = 0x00000000,
    OPEN         = 0x00000001,
    ARCHIVE    = 0x00000002,
    XXX            = 0x10000002,
    ZIP             = 0x20000002,
    RAR            = 0x40000002
}


и при получении файла осуществляется проверка
Код

if(value != UNKNOWN)
{
    if (value & ARCHIVE)
    {
        m_value &= ~OPEN;
        m_value |= value;
    }
    else m_value = OPEN;
}


1. Если поставлялись закрытые файлы и пришел открытый, то просто меняется тип на OPEN
2. Если поставлялись открытые файлы и пришел закрытый, то сбрасывается флаг OPEN и взводится тип ARCHIVE. Если же известен тип архивации, то побитовая сумма.

Вся сложность в том, что Rar и Zip могут быть вместе, но XXX с ними не должен быть.
То есть возможные ситуации
1. XXX
2. Zip
3. Rar
4. Zip & Rar

Но вот если поставлялись файлы XXX и вдруг пожли Zip или Rar, то может получиться ток
1. XXX & Zip
2. XXX & Rar
3. XXX & Zip & Rar

что неправильно.

Вывод:
1. Хотелось бы избавиться от операций проверки и ограничиться лишь побитовыми операциями.
2. Для этого нужно как-то организовать исключающие маски.

З.Ы. И можно ли это вообще сделать без проверок ?

Добавлено через 4 минуты и 2 секунды
math64, что-то не понял как это решает мою задачу ?

Автор: math64 1.5.2009, 13:59
Твою задачу это не решает, она сложнее.
Можно сделать так:
Код

struct Rule {
int bitsSetted;  // Биты установленные в 1
int bitsCleared;// Биты сброшенные в 1
int bitsToSet;   // Биты, которые нужно установить в 1
int bitsToClear;// Биты, которые нужно сбросить в 1
int bitsCopyed;//  Биты, которые нужно скопировать
}; // Может быть нужны будут дополнительные поля
struct Rule[] rules = {
  // Написание кода заменяется на составление таблицы
  { ARCHIVE, UNKNOWN, ARCHIVE, OPEN, ARCHIVE | ZIP | RAR }
};
const countRules = sizeof(rules)/ sizeof(rules[0]);
// Или использовать array<Rule> rules;
void setBits(int& oldBits, int newBits)
{
   for (int i = 0; i < countRules; i++)
  {
    if ( (~newBits & rules[i].bitsSetted) == 0 &&
         (newBits & rules[i].bitsCleared) == 0 )
    {
      int toCopy = rules[i].bitsToCopy;
      oldBits = (oldbits & ~toCopy) | (newBits & toCopy);
      oldBits |= rules[i].bitsToSet;
      oldBits &= ~rules[i].bitsToClear;
    }
  }
}

Автор: mes 1.5.2009, 14:13
Цитата(zss @  1.5.2009,  12:27 Найти цитируемый пост)
И можно ли это вообще сделать без проверок ? 

можно если не создавать самому себе проблем smile
Цитата(zss @  1.5.2009,  12:27 Найти цитируемый пост)
Усложняется еще и тем, что для пользователя Zip и Rar это схожие архиваторы (можно разархивировать одним приложением), но типы эти разные

а может у пользователя вобще не будет WinRara, или такая версия которая любой архив одинаково легко раскроет smile
А так как файл не знает ничего о приложении которое его будет открывать, он должен хранить только тип алгоритма. (т.е никаких сдвоенных масок)

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

Код

namespace File {
 namespace Archive {
   enum EType { eUnknown, еOpen, eZip, eRar, eXXX };
 } // Archive

  struct Descriptor
  {
      int ArchiveType;
  };
  
  struct Archivator 
  {
      virtual bool CanDecode (const Descriptor&) =0;
  };
} // File

struct WinRar : public File::Archivator
{

        virtual bool CanDecode (const Descriptor& d)  
        { 
            using namespace File::Archive;

            switch (d.ArchiveType)
            {                 
                    case еOpen  : 
                    case eZip   : 
                    case eRar   : return true; 
       
                   default : return false;
            };
        }
};  
}







Автор: math64 1.5.2009, 14:20
Да, с классами код будет понятнее.

Автор: zss 1.5.2009, 14:20
Цитата(mes @  1.5.2009,  14:13 Найти цитируемый пост)
а может у пользователя вобще не будет WinRara, или такая версия которая любой архив одинаково легко раскроет smile
А так как файл не знает ничего о приложении которое его будет открывать, он должен хранить только тип алгоритма. (т.е никаких сдвоенных масок)

я лишь привел надуманный пример. Задача ставится именно для сдвоенных масок.

Добавлено @ 14:21
необходимо различать типы
xxx
rar
zip
zip & rar

Добавлено @ 14:22
xxx к тому же исключающий zip и rar

Автор: mes 1.5.2009, 16:21
Цитата(zss @  1.5.2009,  13:20 Найти цитируемый пост)
я лишь привел надуманный пример. Задача ставится именно для сдвоенных масок.

ну так приводите реальные примеры, что мешает приподнять занавесу таинственности  ? smile

Цитата(zss @  1.5.2009,  13:20 Найти цитируемый пост)
необходимо различать типы

Кому и для чего необходимо ? Поподробней.  smile 



Автор: zss 1.5.2009, 16:26
Цитата(mes @  1.5.2009,  16:21 Найти цитируемый пост)
ну так приводите реальные примеры, что мешает приподнять занавесу таинственности  ? 


Цитата(mes @  1.5.2009,  16:21 Найти цитируемый пост)
Кому и для чего необходимо ? Поподробней. 

ну разве это имеет значение.
Я лишь обозвал тепло - мягким.

На суть это не влияет(и на решение задачи тоже)

Автор: mes 1.5.2009, 16:41
Цитата(zss @  1.5.2009,  15:26 Найти цитируемый пост)
На суть это не влияет(и на решение задачи тоже) 

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

Цитата(mes @  1.5.2009,  15:21 Найти цитируемый пост)
Кому и для чего необходимо ? Поподробней. 

Тут идет вопрос не о программисте или заказачике и не об их личных данных  smile 




Автор: zss 1.5.2009, 16:48
Цитата(mes @  1.5.2009,  16:41 Найти цитируемый пост)
то проявите усердие и поставьте задачу ясно.

задача была поставлена четко.

Есть тип А, B и C. B и C могут существовать вместе как побитовая сумма, а А нет.
Причем А исключает существование В и С. Необходимо реализовать это исключение битовыми операциями.

Вроде все понятно. А пример приводился для наглядности (я уже пожалел, что его привел smile).

Автор: mes 1.5.2009, 16:59
Цитата(zss @  1.5.2009,  15:48 Найти цитируемый пост)
задача была поставлена четко.


Цитата(zss @  1.5.2009,  15:48 Найти цитируемый пост)
Есть тип А, B и C.

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

Цитата(zss @  1.5.2009,  15:48 Найти цитируемый пост)
B и C могут существовать вместе как побитовая сумма, а А нет. Причем А исключает существование В и С. 

тут вроде понятно. Т.е есть битовый набор который может принимать только определенные комбинации.


Цитата(zss @  1.5.2009,  15:48 Найти цитируемый пост)
Необходимо реализовать это исключение битовыми операциями.

А вот тут абсолютно непонятно. 
Вот есть число n. Как именно с ним реализовать это исключение ?  smile 

Наверно имелось ввиду, что при добавлении битовой констаты к набору(т.е при операции OR), исключающие биты должны обнулиться ?
В таком случае ответ был дан  еще тут : http://forum.vingrad.ru/index.php?showtopic=257653&view=findpost&p=1857621


Автор: zss 1.5.2009, 17:06
Цитата(mes @  1.5.2009,  16:59 Найти цитируемый пост)
Наверно имелось ввиду, что при добавлении битовой констаты к набору(т.е при операции OR), исключающие биты должны обнулиться ?

типа того smile терминология для второй страницы топика, я думаю, не совсем уместна.
Ты давно понял что я хочу smile

Автор: mes 1.5.2009, 17:24
Цитата(zss @  1.5.2009,  16:06 Найти цитируемый пост)
Ты давно понял что я хочу smile 


ну так подходит решение или нет ?
Цитата(mes @  1.5.2009,  15:59 Найти цитируемый пост)
 http://forum.vingrad.ru/index.php?showtopic=257653&view=findpost&p=1857621

если нет, то чего в нем не хватает ?

Добавлено через 4 минуты и 51 секунду
Цитата(zss @  1.5.2009,  16:06 Найти цитируемый пост)
Ты давно понял что я хочу smile 

А понял что Вам надо.. сейчас 

Автор: zss 1.5.2009, 17:38
Цитата(mes @  1.5.2009,  17:24 Найти цитируемый пост)

если нет, то чего в нем не хватает ?

то что в данно случае нужно будет проводить проверки.

Код

if (value & Mask_A)
{
   ....
}
else if (value & (Mask_B | Mask_C))
{
   ....
}


а хотелось бы накладывать маску, которая сама контролирует взаимное исключение

Автор: mes 1.5.2009, 17:51
вот опять условным кодом:  
Код

enum EBits { eA, eB, eC, eMax }; // это выражаясь вашей терминологии значения "типов"
const int Mask[]  = { 1<<eA, 1<<eB, 1<<eC }; // это их маски для хранения в контейнере
const int XMask[] = { /* eA */  Mask[eB] | Mask[eC],     // исключающие маски
                      /* eB */  Mask[eA],
                      /* eC */  Mask[eA]  };
void AddBit (int& set, int bit) // процедура корректного добавления "значения типа"  к "набору"
{
    if (bit >= eMax) return;
    set &= ~XMask[bit];
    set |= Mask[bit];
};
bool HasBit (int& set, int bit) // проверка на нахождение в "наборе" нужного значения типа.
{
      if (bit >= eMax) return false;
      return set & Mask[bit];
};

исправлено 

так пойдет ? 

Автор: math64 1.5.2009, 18:07
Выбирай из трёх вариантов:
1. Пиши ifы, как собирался сам.
2. Составляй таблицу Rule rules[], как предлагал я.
Возможно struct Rule будет сложнее, для хранения их можно выбрать какой нибудь контейнер stl, который позволит быстрее найти нужную/-ые запись/-и.
3. Пиши набор классов Archivator, как предложил mes.
4. ЭКЗОТИКА: Выбрать другой язык программирования типа LISP или Prolog или запрограммировать ПЛМ.
Врядли можно придумать что-то ещё.
IMHO, вариант mes лучше

Автор: zss 1.5.2009, 19:22
Цитата(mes @  1.5.2009,  17:51 Найти цитируемый пост)
так пойдет ? 

Код

    int value = eA;
    AddBit(value, eB);
    AddBit(value, eC);

value == eC, а должен == eB | eC

Код

    int value = eA;
    AddBit(value, eB | eC);

value == 0, а должен == eB | eC

Автор: mes 1.5.2009, 19:45
Цитата(zss @  1.5.2009,  18:22 Найти цитируемый пост)
value == eC, а должен == eB | eC

из за написания на скорую руку, код содержал глюки - вот подправил

Цитата(zss @  1.5.2009,  18:22 Найти цитируемый пост)
AddBit(value, eB | eC);

А так применять нельзя, так как eB это не маска, а значение типа. 
Чтоб можно было за раз устанавливать оба бита, то можете добавить в список тип eBC с необходимыми масками.
К тому же приведенный код лишь демонстрация  и для заключительной версии требует доработки smile

Добавлено через 5 минут и 25 секунд
Цитата(zss @  1.5.2009,  18:22 Найти цитируемый пост)
 int value = eA;

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

Добавлено через 6 минут и 54 секунды
Поэтому лучше подобные вещи разгружать через типы, а не значения.
Тогда можно будет определить те операции которые требуется и компилятор сам будет следить за коректностью. 

Автор: math64 1.5.2009, 19:54
По коду mes (1.5.2009, 17:51)
Код

void AddBit (int set, int bit) // процедура корректного добавления "значения типа"  к "набору"
{
    if (bit >= eMax) return;
    set &= ~XMask[bit]; // В XMask биты которые нужно снять, а не оставить
    set |= Mask[bit];
};


Код

    int value = eA;
    AddBit(value, eB | eC);

Так нельзя, eВ и eC - номера битов, их нельзя оъбединять по или
Код

    int value = Mask[eA];
    value = AddBits1(value, Mask[eB] | Mask[eC]);

или
Код

    int value = Mask[eA];
    value = AddBits2(value, eB, eC, -1);

Код

int AddBits1(int set, int mask) {
  for (int i = 0; i < eMax; i++)
     if ( (mask & Mask[i]) != 0)
       AddBit(set, i);
  return set;
}
int AddBits2(int set, ...) {
  va_list v;
  va_start(v, mask)
  for (;;) {
    int i = va_arg(v, int); 
    if (i < 0)
      break;
    AddBit(set, i);
  }
  va_end();
  return set;
}


Добавлено через 14 минут и 27 секунд
Вот тебе код без if:
Код

int Table[64];
void InitTable() {
  for(int i = 0; i < 8; i++)
    for (int j = 0; j < 8; j++) {
       Table[i*8+j] = AddBits1(i, j);
    }
}

int AddBits3(int set1, int set2) {
  return Table[set1*8+set2);



Автор: KEHT 3.5.2009, 21:16
Код

#include <iostream>
#include <cassert>
using namespace std;
/*Класс T представляет тип маски и требует выполнения следующих условий
    1)Наличие конструктора по умолчанию
    2)Наличие копирующего конструктора
    3)Наличие оператора присваивания
    4)Наличие оператора сравнения
    4)Наличие функций для побитовых операций
*/
/*
Каждому объекту задается disallowed_mask. Если объект, подаваемый на вход содержится в этой маске,
то значения объекта замещается.
*/
template<typename T> class Mask;

template<typename T>
class Mask{
    T mask, disallowed_mask;
public:
    Mask(): mask(), disallowed_mask(){}
    Mask(const Mask &m): mask(m.mask), disallowed_mask(m.disallowed_mask){}
    Mask(T _mask, T _disallowed_mask): mask(_mask), disallowed_mask(_disallowed_mask){}
    Mask& operator=(const Mask &r){
        if(this != &r){
            mask = r.mask;
            disallowed_mask = r.disallowed_mask;
        }
        return *this;
    }
    //Бинарные операторы
    friend const Mask operator|(const Mask &l, const Mask &r){
        if(r.mask == (r.mask & l.disallowed_mask))
            return r;
        else
            return Mask(l.mask | r.mask, l.disallowed_mask);
    }
    Mask& operator|=(const Mask &r){
        if(r.mask == (r.mask & disallowed_mask) && this != &r)
            mask = r.mask;
        else
            mask |= r.mask;
        return *this;
    }
    //Функции доступа
    T get() const{ return mask; }
};

int main(){
    Mask<int> a(1, 4), b(2, 4), c(4, 3);
    
    assert((a | b).get() == 3);
    assert((a | c).get() == 4);
    assert((c | a).get() == 1);
    assert((b | c).get() == 4);
    assert((c | b).get() == 2);
    assert((c | c).get() == 4);
    
    return 0;
}


Минус реализации, что если тебе нужно будет, чтобы 
A = 00000001
B = 00000010
C = 00000011

С замещала B, то придеца указать B запрещающую маску 00000011, а это приведет к блокированию A

Как вариант использовать vector<T>(или другой контейнер) для хранения масок

Автор: math64 4.5.2009, 07:52
Идея неплохая, но в реализации operator |= и operator | есть ошибки, нужно вычислять новую disallowed_mask и mask вычисляется не всегда правильно.
Можно добавить friend T operator |(const T&, const Mask&); чтобы искючить ненужное вычисление disallowed_mask.

Автор: KEHT 4.5.2009, 11:24
Цитата

нужно вычислять новую disallowed_mask

Я исходил из условия задачи, в котором следовало, что объект справа от оператора подается на вход левому, поэтому и disallowed_mask оставлял от левого объекта.
Цитата

mask вычисляется не всегда правильно

Тут да. В данной реализации к типу T предъявляются довольно существенные ограничения. Идеально было бы хранить контейнер со всем запрещенными масками.
Цитата

Можно добавить friend T operator |(const T&, const Mask&); чтобы искючить ненужное вычисление disallowed_mask.

Я так понял, что по условию задачи левый от оператора объект предъявляет требования к правому, поэтому скорее
friend T operator |(const Mask&, const T&);

Автор: J0ker 4.5.2009, 18:26
Код

enum MASKS
{
    UNKNOWN = 0x00000000,
    OPEN         = 0x00000001,
    ARCHIVE    = 0x10000000,
    ZIP             = 0x30000000,
    RAR            = 0x50000000,
    ZIP_RAR     = 0x70000000
}


Автор: zss 4.5.2009, 19:04
J0ker, и как их пользовать ?

Автор: J0ker 4.5.2009, 19:22
Цитата(zss @ 4.5.2009,  19:04)
J0ker, и как их пользовать ?

Код

enum MASKS
{
    UNKNOWN = 0x00000000,
    OPEN         = 0x00000001,
    ARCHIVE    = 0x10000000,
    ZIP             = 0x30000000,
    RAR            = 0x50000000,
    ZIP_RAR     = 0x70000000
}

bool is_open(unsigned int f)
{
    return (f & OPEN) != 0;
}

bool is_archive(unsigned int f)
{
    return (f & ARCHIVE) != 0;
}

bool is_zip(unsigned int f)
{
    return (f & ZIP) == ZIP;
}

bool is_rar(unsigned int f)
{
    return (f & RAR) == RAR;
}

bool is_zip_rar(unsigned int f)
{
    return (f & ZIP_RAR) == ZIP_RAR;
}

unsigned int set_open(unsigned int &f)
{
    return f &= OPEN;
}

unsigned int set_archive(unsigned int &f)
{
    return f &= ARCHIVE;
}

unsigned int set_zip(unsigned int &f)
{
    return f &= ZIP;
}

unsigned int set_rar(unsigned int &f)
{
    return f &= RAR;
}

unsigned int set_zip_rar(unsigned int &f)
{
    return f &= ZIP_RAR;
}

//====================================

unsigned int f = UNKNOWN;

set_zip(f);

if(is_archive(f))
    cout << "archive" << endl;


Автор: mes 4.5.2009, 19:56
zss, ловите идею, может пригодится :
Код

#include <iostream>

struct Type
{
    struct TMeta
    {
        int Mask;
        int XMask;
    };
    virtual TMeta Meta() const =0;
};

struct AType : Type
{
      virtual TMeta Meta() const  { TMeta Meta ={1<<0, 1<<1 | 1<<2 }; return Meta; };
};

struct BType : Type
{
      virtual TMeta Meta() const  { TMeta Meta ={1<<1, 1<<0 }; return Meta; };
};

struct CType : Type
{
      virtual TMeta Meta() const  { TMeta Meta ={1<<2, 1<<0}; return Meta; };
};

class TypeSet
{
    public:
        TypeSet () : set (0) {}

        void Add (const Type& type)
        {
              set &= ~type.Meta().XMask;
              set |=  type.Meta().Mask;
        }
        bool Has (const Type& type)
        {
            return set & type.Meta().Mask;
        }

    private:
        int set;
};

void Test (TypeSet& set, const Type& type)
{
    set.Add (type);
    std::cout <<set.Has(AType())<<" "<<set.Has(BType())<<" "<<set.Has(CType())<<" " << std::endl;
}

int main ()
{
     TypeSet set;

     Test (set, AType());
     Test (set, BType());
     Test (set, CType());
     Test (set, AType());


    system ("pause");
    return 0;
}




блок с 13й по 26ю строку можно записать примерно так :
Код

#define DECLARE_TYPE(name, Mask, XMask)  struct name : Type{ virtual TMeta Meta() const   { return (TMeta){ Mask, XMask }; } };

 DECLARE_TYPE (AType, 1<<0,  1<<1 | 1<<2 )
 DECLARE_TYPE (BType, 1<<1,  1<<0 )
 DECLARE_TYPE (CType, 1<<2,  1<<0 )

#undef DECLARE_TYPE 

подправлено забытое, в связи с  замечанием J0ker'а

Автор: J0ker 4.5.2009, 20:12
6: #undef DECLARE_TYPE

Автор: zss 5.5.2009, 07:02
J0ker, идея хорошая, только у тебя нет исключающего архива.

Автор: math64 5.5.2009, 08:26
Код

struct Type
{
   int Mask;
   int XMask;
};
const Type AType = { 1<<0,  1<<1 | 1<<2 };
const Type BType = { 1<<1,  1<<0 };
const Type CType = { 1<<2,  1<<0 };

с соответствующими упрощениями  TypeSet.

Автор: J0ker 5.5.2009, 09:02
Цитата(zss @ 5.5.2009,  07:02)
J0ker, идея хорошая, только у тебя нет исключающего архива.

то есть?
все комбинации в моем варианте заведомо верны
или вы это имели ввиду:
Код

enum MASKS
{
    UNKNOWN = 0x00000000,
    OPEN         = 0x00000001,
    ARCHIVE    = 0x10000000,
    ZIP             = 0x30000000,
    RAR            = 0x50000000,
    ZIP_RAR     = 0x70000000,
    ARCHIVE_FLAGS = 0x70000000
}

bool is_archive_unknown(unsigned int f)
{
    return (f & ARCHIVE_FLAGS) == ARCHIVE;
}


Автор: Static 5.5.2009, 14:21
Позвольте вопрос...
Код

enum MASKS
{
    UNKNOWN = some_mask1,
    OPEN         = some_mask2,
    ARCHIVE    = some_mask3,   //а вот это действительно нужно?
    ZIP             = some_mask4,
    RAR            = some_mask5,
    XXX     = some_mask6,
}


Ведь если файл zip, rar или unknown_archive - он ведь все равно архив...

Автор: zss 5.5.2009, 14:31
Цитата(J0ker @  5.5.2009,  09:02 Найти цитируемый пост)
то есть?

архив xxx, который не может существовать с zip и rar

Автор: J0ker 5.5.2009, 16:10
Цитата(zss @ 5.5.2009,  14:31)
Цитата(J0ker @  5.5.2009,  09:02 Найти цитируемый пост)
то есть?

архив xxx, который не может существовать с zip и rar

ну как-же нет
ARCHIVE

Автор: zss 5.5.2009, 16:31
Цитата(J0ker @  5.5.2009,  16:10 Найти цитируемый пост)
ну как-же нет
ARCHIVE 

нет - ARCHIVE говорит что он закрыт, но возможно неизвестным архиватором - это не тип архива
а тип - автоматически должен подразумевать архивацию

Автор: J0ker 5.5.2009, 17:01
Цитата(zss @  5.5.2009,  16:31 Найти цитируемый пост)
ARCHIVE говорит что он закрыт, но возможно неизвестным архиватором 

ARCHIVE с учетом не выставленных ZIP и RAR говорит об этом совершенно прямолинейно

Автор: zss 5.5.2009, 17:32
Цитата(J0ker @  5.5.2009,  17:01 Найти цитируемый пост)
ARCHIVE с учетом не выставленных ZIP и RAR говорит об этом совершенно прямолинейно

это понятно. нужно сто 3 архив xxx исключал их. весь вопрос именно в этом

Автор: J0ker 5.5.2009, 17:36
Цитата(zss @  5.5.2009,  17:32 Найти цитируемый пост)
это понятно. нужно сто 3 архив xxx исключал их. весь вопрос именно в этом 

Код

enum MASKS
{
    UNKNOWN = 0x00000000,
    OPEN         = 0x00000001,
    ARCHIVE    = 0x10000000,
    ZIP             = 0x30000000,
    RAR            = 0x50000000,
    ZIP_RAR     = 0x70000000,
    XXX            = 0xF0000000,
    ARCHIVE_FLAGS = 0xF0000000
}

Автор: mes 5.5.2009, 17:41
J0ker,  
Цитата(zss @  1.5.2009,  16:06 Найти цитируемый пост)
Цитата

Наверно имелось ввиду, что при добавлении битовой константы к набору(т.е при операции OR), исключающие биты должны обнулиться ?

типа того smile 




Автор: J0ker 5.5.2009, 17:54
Цитата(mes @ 5.5.2009,  17:41)
J0ker,  
Цитата(zss @  1.5.2009,  16:06 Найти цитируемый пост)
Цитата

Наверно имелось ввиду, что при добавлении битовой константы к набору(т.е при операции OR), исключающие биты должны обнулиться ?

типа того smile 

для этого к флагам прилагаются функции
можно засунуть все это в класс
от битовых флагов в чистом виде такого поведения добиться невозможно

Автор: zss 5.5.2009, 19:57
Цитата(J0ker @  5.5.2009,  17:54 Найти цитируемый пост)
от битовых флагов в чистом виде такого поведения добиться невозможно 

ну mes приводил не плохое решение. наверное на этом и остановимся smile

всем спасибо

Автор: math64 6.5.2009, 12:49

Код

enum Bit {
   Unknown,
   Unpacked, // насколько я понял OPEN - это НЕ ЗАПАКОВАННЫЙ файл
   Archived,
   Rar,
   Zip,
   Other // Запаковано другим архиватором
};

class Set<Bit> set;
class Map<Bit, Set<Bits> > plus, minus;
void AddBit(Set<Bit> set,  Bit bit) {
   set -= minus[bit];
   set += plus[bit];
}

А теперь, какая самая простая реализация Set<Bit>? int (или short, unsigned char...).
А Map<Bit, Set<Bits> >? int[Other+1].
Код

int plus[] = {...};
int minus[] = {...};
void AddBit(int set,  Bit bit) {
   set &= ~minus[bit];
   set |= plus[bit];
}

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)