Форум программистов, компьютерный форум, киберфорум
С++ для начинающих
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.57/7: Рейтинг темы: голосов - 7, средняя оценка - 4.57
130 / 25 / 12
Регистрация: 12.08.2015
Сообщений: 221

Интересная задачка с битовыми операторами, флагами, переменными, или "до меня не дошло письмо из штаба"

05.09.2015, 17:53. Показов 1483. Ответов 10
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Дорогие форумчане! Недавно я занялся исправлять пробелы в знании C++ одной замечательной книжкой, которую мне помогли найти! Книжка действительно замечательная. В одной главе, третьей, есть такая задачка, привожу её дословно:

Предположим, необходимо установить в программе переменную режима открытия файла на базе двух атрибутов: типа файла, который может быть текстовым или бинарным и способа открытия файла - для чтения или записи. Используя битовые операторы (& и |) а так же набор флагов, предложите и разработайте метод, позволяющий в одной целочисленной переменной устанавливать любую комбинацию из этих двух атрибутов. Напишите программу, которая установит значение одной целочисленной переменной на основе атрибутов, а затем декодирует и отобразит на экран все установленные флаги.
Чуть ниже я приведу свое решение (хотя оно мне кажется грубым, ужасно не гибким и громоздким), которое к тому же, использует вместо двух битовых операторов (& и |) целых четыре (<<, >>, |, ^).

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
//Переключатель двух атрибутов файла, значения которых сохраняются в одной переменной.
 
#include<iostream>
 
using std::cout;
using std::cin;
using std::endl;
 
 
int attributes = 0;     //Переменная хранения всех флагов
bool txt_bin = 0;       //Флаги атрибутов файла
bool rd_wr = 0;
 
 
bool txt_bin_uncr = 0;       //Флаги атрибутов файла при декодировании
bool rd_wr_uncr= 0;
 
 
int main()
{
    setlocale(LC_ALL, "rus");
    //Блок кодировки атрибутов в одну переменную
    {
        cout << "Введите кодировку файла (0 - если двоичный, 1 - если текстовой): ";   //Ввод флагов
        cin  >> txt_bin;
        cout << "Введите режим чтения\\записи (0 - если чтение, 1 - если запись): ";
        cin  >> rd_wr;
 
        attributes = txt_bin | (rd_wr << 1); //Их слияние в одной переменной
 
        cout << "Запись данных успешно произведена!";
        cout << endl;
    }
 
 
 
    //Блок расшифровки
    {
    if ((attributes >> 1) == 1)
    {
        rd_wr_uncr = attributes ^ 2;  //Отсеиваем передний ненужный флаг при помощи исключающего или, если он == 1
    }
    else
    {
        rd_wr_uncr = attributes; //Или же присваиваем текущее значение, если крайний флаг == 0. (Что тоже верно)
    }
    txt_bin_uncr = attributes >> 1; //Значение крайнего флага получаем при помощи битового смещения и "съедания" первого флага
 
    cout << "Вы установили следующие флаги: "
         << ((txt_bin_uncr == 1)?(" текстовой тип данных (1), "):(" бинарный тип данных (0), "))
         << ((rd_wr_uncr == 1)?(" режим записи (1), "):(" режим чтения (0), "));
    cout << endl;
   system("pause");
    return 0;
}

Итог: Формально задача выполнена, но с нарушением условий (задействовано больше битовых операторов, чем надо, и один не использован)

Уважаемые форумчане, научите пожалуйста, как сделать задачу по условию (используя только & и |), я уже голову себе сломал!
И куда, ну куда тут вообще возможно присобачить долбанное битовое и "&"??? Зачем оно тут надо?
0
Programming
Эксперт
39485 / 9562 / 3019
Регистрация: 12.04.2006
Сообщений: 41,671
Блог
05.09.2015, 17:53
Ответы с готовыми решениями:

интересная штука с переменными... или я чего-то недопонимаю...
exec ('declare @int int select @int=count(*) from Diction where ID in ('+@vals+') print @int') print @int а как получить во втором...

Работа с битовыми операторами
Здравствуйте, С Новым Годом! Решил за новогодние празники познакомиться с языком C++. Попалась на глаза книжка Стефана Р. Дэвиса &quot;С++...

Интересная задачка, или программа принимает одно или два целых числа?
Здравствуйте, программисты! Помогите с задачей! При вызове, программа должна принимать одно ИЛИ два целых числа, если число одно, то...

10
7804 / 6568 / 2988
Регистрация: 14.04.2014
Сообщений: 28,705
05.09.2015, 18:03
Лучший ответ Сообщение было отмечено gledor как решение

Решение

Определи константы для флагов и пользуйся. bool здесь не нужен.
C++
1
2
3
4
5
const int open_txt = 1;
const int open_bin = 2;
 
const int open_read = 4;
const int open_write = 8;
1
Эксперт С++
 Аватар для hoggy
8973 / 4319 / 960
Регистрация: 15.11.2014
Сообщений: 9,760
05.09.2015, 18:13
Цитата Сообщение от gledor Посмотреть сообщение
Чуть ниже я приведу свое решение (хотя оно мне кажется грубым, ужасно не гибким и громоздким), которое к тому же, использует вместо двух битовых операторов (& и |) целых четыре (<<, >>, |, ^).
говнокод.


работу с битами необходимо инкапсулировать в отдельном механизме.
и предоставить моральные читабельные методы работы:

Константа в классе
0
130 / 25 / 12
Регистрация: 12.08.2015
Сообщений: 221
05.09.2015, 18:16  [ТС]
Пффффф.... В издательстве при переводе перепутали главы и упражнения????? У меня глава, называемая принацие решений и циклы в c++.
0
Эксперт С++
 Аватар для hoggy
8973 / 4319 / 960
Регистрация: 15.11.2014
Сообщений: 9,760
05.09.2015, 18:18
Лучший ответ Сообщение было отмечено gledor как решение

Решение

Цитата Сообщение от gledor Посмотреть сообщение
один вопрос остается, куда мне приткнуть битовое & и как избавиться от ^???
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
#pragma once
 
namespace tools
{
    template<class ENUMERATION_TYPE, class INTEGRAL_TYPE = int>
    class TFlag
    {
    public:
        typedef ENUMERATION_TYPE ENUMERATION;
        typedef INTEGRAL_TYPE INTEGRAL;
 
        explicit TFlag(const INTEGRAL startFlag = 0 );
        explicit TFlag(const ENUMERATION startFlag);
        explicit TFlag(const bool, const ENUMERATION startFlag);
        explicit TFlag(const bool, const INTEGRAL startFlag);
 
        ~TFlag();
        
        static const TFlag& CastFrom(const INTEGRAL& src);
        static TFlag& CastFrom(INTEGRAL& src);
        static const ENUMERATION& Cast(const INTEGRAL& src);
        static ENUMERATION& Cast(INTEGRAL& src);
        static const INTEGRAL& Cast(const ENUMERATION& src);
        static INTEGRAL& Cast(ENUMERATION& src);
 
        bool Empty()const { return Cast(mFlags)==0; }
        void Clear() { Cast(mFlags)=0; } 
 
        const ENUMERATION& GetByEnumeration()const  { return mFlags;  } 
        ENUMERATION& GetByEnumeration()             { return mFlags;  } 
 
        const INTEGRAL& GetByIntegral()const  { return Cast(mFlags);  } 
        INTEGRAL& GetByIntegral()             { return Cast(mFlags);  } 
 
        //true, если все указанные флаги включены: флаг1|флаг2|флаг3
        bool Has(const ENUMERATION flag)const { return (Cast(flag) & Cast(mFlags)) == Cast(flag); } 
        bool Has(const INTEGRAL flag)const    { return (flag & Cast(mFlags)) == flag; } 
 
        //true, если хотя бы один из указанных флагов включен: флаг1|флаг2|флаг3
        bool HasAny(const ENUMERATION flag)const { return (Cast(flag) & Cast(mFlags)) != 0; } 
        bool HasAny(const INTEGRAL flag)const    { return (flag & Cast(mFlags)) != 0; } 
 
        //true, если this содержит флаги идентичные указанным
        bool HasOnly(const ENUMERATION flag)const { return operator==(TFlag(flag)); }
        bool HasOnly(const INTEGRAL flag)const    { return operator==(TFlag(flag)); }
 
 
        //если success true, тогда добавит флаги: флаг1|флаг2|флаг3
        void Add(const bool success, const ENUMERATION flag);
        void Add(const bool success, const INTEGRAL flag);
 
        //добавит флаги: флаг1|флаг2|флаг3
        void Add(const ENUMERATION flag)  { Cast(mFlags) |= flag; } 
        void Add(const INTEGRAL flag)     { Cast(mFlags) |= flag; } 
 
        //удалит флаги: флаг1|флаг2|флаг3
        void Del(const ENUMERATION flag)  { Cast(mFlags) &= (~flag); } 
        void Del(const INTEGRAL flag)     { Cast(mFlags) &= (~flag); } 
 
        //сделать включенными только флаги: флаг1|флаг2|флаг3
        void Only(const ENUMERATION flag) { Cast(mFlags)=0; Add(flag); }
        void Only(const INTEGRAL flag)    { Cast(mFlags)=0; Add(flag); }
 
        //из включенных флагов оставит только указанные флаги: флаг1|флаг2|флаг3
        void ValidOnly(const ENUMERATION flag ){ Cast(mFlags) &= flag; } 
        void ValidOnly(const INTEGRAL flag )   { Cast(mFlags) &= flag; } 
 
        // true, если хотя бы один выставлен
        operator bool()const { return !Empty(); }
 
        //true, если флаги идентичны
        bool operator==(const TFlag flag)const { return mFlags==flag.mFlags; }
 
        //true, если флаги не идентичны
        bool operator!=(const TFlag flag)const { return mFlags!=flag.mFlags; }
    private:
        ENUMERATION mFlags;
    };
 
    template<class ENUMERATION, class INTEGRAL>
    TFlag<ENUMERATION, INTEGRAL>::TFlag(const INTEGRAL startFlag)
        :mFlags(Cast(startFlag))
    {}
 
    template<class ENUMERATION, class INTEGRAL>
    TFlag<ENUMERATION, INTEGRAL>::TFlag(const ENUMERATION startFlag)
        :mFlags(startFlag)
    {}
 
    template<class ENUMERATION, class INTEGRAL>
    TFlag<ENUMERATION, INTEGRAL>::TFlag(const bool is_true, const ENUMERATION startFlag)
        :mFlags( is_true? startFlag: ENUMERATION(0) )
    {}
 
    template<class ENUMERATION, class INTEGRAL>
    TFlag<ENUMERATION, INTEGRAL>::TFlag(const bool is_true, const INTEGRAL startFlag)
        :mFlags( is_true? Cast(startFlag): ENUMERATION(0) )
    {}
 
    template<class ENUMERATION, class INTEGRAL>
    TFlag<ENUMERATION, INTEGRAL>::~TFlag() 
    {}
 
    template<class ENUMERATION, class INTEGRAL>
    const TFlag<ENUMERATION, INTEGRAL>& TFlag<ENUMERATION, INTEGRAL>::CastFrom(const INTEGRAL& src)
    {
        return *(reinterpret_cast<const TFlag*>(&src)); 
    }
 
    template<class ENUMERATION, class INTEGRAL>
    TFlag<ENUMERATION, INTEGRAL>& TFlag<ENUMERATION, INTEGRAL>::CastFrom(INTEGRAL& src)
    {
        return *(reinterpret_cast<TFlag*>(&src)); 
    }
 
    template<class ENUMERATION, class INTEGRAL>
    const ENUMERATION& TFlag<ENUMERATION, INTEGRAL>::Cast(const INTEGRAL& src)
    {
        return *(reinterpret_cast<const ENUMERATION*>(&src)); 
    }
 
    template<class ENUMERATION, class INTEGRAL>
    ENUMERATION& TFlag<ENUMERATION, INTEGRAL>::Cast(INTEGRAL& src)
    {
        return *(reinterpret_cast<ENUMERATION*>(&src)); 
    }
 
    template<class ENUMERATION, class INTEGRAL>
    const INTEGRAL& TFlag<ENUMERATION, INTEGRAL>::Cast(const ENUMERATION& src)
    {
        return *(reinterpret_cast<const INTEGRAL*>(&src)); 
    }
 
    template<class ENUMERATION, class INTEGRAL>
    INTEGRAL& TFlag<ENUMERATION, INTEGRAL>::Cast(ENUMERATION& src)
    {
        return *(reinterpret_cast<INTEGRAL*>(&src)); 
    }
 
    template<class ENUMERATION, class INTEGRAL>
    void TFlag<ENUMERATION, INTEGRAL>::Add(const bool success, const ENUMERATION flag)  
    {
        if(success)
            Cast(mFlags) |= flag; 
    }
 
    template<class ENUMERATION, class INTEGRAL>
    void TFlag<ENUMERATION, INTEGRAL>::Add(const bool success, const INTEGRAL flag)  
    {
        if(success)
            Cast(mFlags) |= flag; 
    } 
 
}//namespace tools
 
#if 0
//ИСПОЛЬЗОВАНИЕ:
 
enum eFLAGS { eCLEAR = 0, eONE = 1<<1, eTWO = 1<<2, eTHREE = 1<<3 };
typedef tools::TFlag<eFLAGS> Flag;
 
Flag f(eONE|eTWO);
EXPECT_EQ(eONE|eTWO,    f.GetByEnumeration()    );
EXPECT_EQ(false,        f.Empty()               );
EXPECT_EQ(true,        (f)? true: false         );
EXPECT_EQ(true,         f.Has(eONE)             );
EXPECT_EQ(true,         f.Has(eONE|eTWO)        );
EXPECT_EQ(false,        f.Has(eONE|eTWO|eTHREE) );
EXPECT_EQ(true,         f.HasAny(eONE|eTWO)     );
EXPECT_EQ(true,         f.HasAny(eTWO|eTHREE)   );
EXPECT_EQ(false,        f.HasOnly(eONE)         );
EXPECT_EQ(true,         f.HasOnly(eONE|eTWO)    );
 
f.ValidOnly(eONE);
 
EXPECT_EQ(eONE,   f.GetByEnumeration()  );
EXPECT_EQ(false,  f.Empty()             );
EXPECT_EQ(true,  (f)? true: false       );
EXPECT_EQ(true,   f.Has(eONE)           );
EXPECT_EQ(false,  f.Has(eONE|eTWO)      );
EXPECT_EQ(true,   f.HasAny(eONE|eTWO)   );
EXPECT_EQ(false,  f.HasAny(eTWO|eTHREE) );
EXPECT_EQ(true,   f.HasOnly(eONE)       );
EXPECT_EQ(false,  f.HasOnly(eONE|eTWO)  );
#endif
1
130 / 25 / 12
Регистрация: 12.08.2015
Сообщений: 221
05.09.2015, 18:18  [ТС]
Цитата Сообщение от hoggy Посмотреть сообщение
говнокод.
работу с битами необходимо инкапсулировать в отдельном механизме.
и предоставить моральные читабельные методы работы:
Отчасти согласен. Это наверное потому, что задание дано в тертьей главе книги и просто учит человека работать с операторами, а не писать полноценные программы, поэтому необходим принцип и простота.
0
55 / 56 / 34
Регистрация: 29.12.2012
Сообщений: 478
05.09.2015, 18:20
gledor, а что за книга?
0
Эксперт С++
 Аватар для hoggy
8973 / 4319 / 960
Регистрация: 15.11.2014
Сообщений: 9,760
05.09.2015, 18:25
Цитата Сообщение от gledor Посмотреть сообщение
Отчасти согласен. Это наверное потому, что задание дано в тертьей главе книги и просто учит человека работать с операторами, а не писать полноценные программы, поэтому необходим принцип и простота.
битовые операции тривиальны по своей сути.
но это не причина лепить размазню.

насколько помню буквари - там объясняют, что это такое и с чем это кушать.
но не призывают размазывать по всему коду.
1
7804 / 6568 / 2988
Регистрация: 14.04.2014
Сообщений: 28,705
05.09.2015, 18:40
hoggy, у него размазня, а у тебя что за монстр? Ради четырёх флагов такое склепать...
0
130 / 25 / 12
Регистрация: 12.08.2015
Сообщений: 221
05.09.2015, 18:54  [ТС]
Цитата Сообщение от Черный мечник Посмотреть сообщение
gledor, а что за книга?
Visual C++ 2010 Полный курс.
Айвор Хортон

Visual C++ 2010 BEGINNING
Ivor Horton

X82 Visual C++ 2010: полный курс.:Пер. с англ. - М.: ООО "И.Д.Вильямс" 2011,
1216 стр., илл. - Парал.тит.англ.

ISBN 978-5-8459-1698-3 (рус.)

Эта книга гораздо более толковая, чем какие-либо встречавшиеся до этого. C++ за 21 день- это просто макулатура,как и ряд задачников. Мой мозг до сих пор в царапинах от C++ за 21 день. Никакой еще более свалянной в комок информации я не пропускал через себя.

P.S. Кстати, скорее всего, задачу действительно не туда вообще вставили при переводе на русский, эта задача относится логически и по оглавлению ближе к концу курса C++\IEC, а не к началу. Разумеется, я написал не очень. Но зато хоть как-то работает...

Добавлено через 6 минут
В общем, частично задача решена.
nmcf, Вы мне помогли больше всего, мой код стал более лаконичным, и более близким к условию задачи. Вам плюсик и лучший, на данный момент, ответ.
hoggyВаш ответ тоже хорош, я всегда буду стараться писать код правильно и бережно, и хотя я и не понял процентов 30 от вашего примера, я тоже ставлю вам плюсик!

upd. Ваш пример я тоже вкурил наконец)))
0
Эксперт С++
 Аватар для hoggy
8973 / 4319 / 960
Регистрация: 15.11.2014
Сообщений: 9,760
05.09.2015, 18:55
Цитата Сообщение от nmcf Посмотреть сообщение
а у тебя что за монстр? Ради четырёх флагов такое склепать...
человекочитабельный синтаксис для любого количества флагов,
которые можно упаковать в интегральной переменной любого типа.

это - универсальное решение.

дизайн использования предполагает базироваться на енумах.
что позволяет в отладке увидить красивые человекочитабельные имена.
например: eONE|eTWO, а не непонятные цыферки,
где без битовых операций не понятно, что там за флаги.


кстати, данный "монстр" - имеет тривильную реализацию.
реализацию его методов можно рассматривать как примеры: "а как сделать так, что бы если биты..."
1
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
inter-admin
Эксперт
29715 / 6470 / 2152
Регистрация: 06.03.2009
Сообщений: 28,500
Блог
05.09.2015, 18:55
Помогаю со студенческими работами здесь

написать фильтрацию массива чисел битовыми операторами
Переменная типа Number(целое число) содержит в себе информацию про юзера: 1.пол (м/ж) 2.семейное положение (женат / не женат) ...

Как прикрепить файлы к письму отправляемому функцией mail() и как узнать дошло ли письмо.
Здравствуйте, помогите пожалуйста. Мне нужно прикрепить файлы к письму отправляемому функцией mail(), как это сделать и как узнать дошло...

Задачка на работу с флагами: проверить, есть ли в массиве элемент с заданным значением
Есть задачка: Дан массив с числами. Проверьте, что в этом массиве есть число 5. Если есть - выведите 'да', а если нет - выведите 'нет'. ...

Задачка на файлы. интересная задачка с игрушками
Дан файл Assort, содержащий сведения об игрушках: указываются название игрушки, ее стоимость в рублях и возрастные границы (например,...

Интересная ситуация с переменными
Возникла такая ситуация: $array_test = array('test1' =&gt; 'раз', 'test2' =&gt; 'два', 'test3' =&gt; 'три', 'test4' =&gt; 'четыре'); ...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
11
Ответ Создать тему
Новые блоги и статьи
http://iceja.net/ математические сервисы
iceja 20.01.2026
Обновила свой сайт http:/ / iceja. net/ , приделала Fast Fourier Transform экстраполяцию сигналов. Однако предсказывает далеко не каждый сигнал (см ограничения http:/ / iceja. net/ fourier/ docs ). Также. . .
http://iceja.net/ сервер решения полиномов
iceja 18.01.2026
Выкатила http:/ / iceja. net/ сервер решения полиномов (находит действительные корни полиномов методом Штурма). На сайте документация по API, но скажу прямо VPS слабенький и 200 000 полиномов. . .
Расчёт переходных процессов в цепи постоянного тока
igorrr37 16.01.2026
/ * Дана цепь постоянного тока с R, L, C, k(ключ), U, E, J. Программа составляет систему уравнений по 1 и 2 законам Кирхгофа, решает её и находит переходные токи и напряжения на элементах схемы. . . .
Восстановить юзерскрипты Greasemonkey из бэкапа браузера
damix 15.01.2026
Если восстановить из бэкапа профиль Firefox после переустановки винды, то список юзерскриптов в Greasemonkey будет пустым. Но восстановить их можно так. Для этого понадобится консольная утилита. . .
Сукцессия микоризы: основная теория в виде двух уравнений.
anaschu 11.01.2026
https:/ / rutube. ru/ video/ 7a537f578d808e67a3c6fd818a44a5c4/
WordPad для Windows 11
Jel 10.01.2026
WordPad для Windows 11 — это приложение, которое восстанавливает классический текстовый редактор WordPad в операционной системе Windows 11. После того как Microsoft исключила WordPad из. . .
Classic Notepad for Windows 11
Jel 10.01.2026
Old Classic Notepad for Windows 11 Приложение для Windows 11, позволяющее пользователям вернуть классическую версию текстового редактора «Блокнот» из Windows 10. Программа предоставляет более. . .
Почему дизайн решает?
Neotwalker 09.01.2026
В современном мире, где конкуренция за внимание потребителя достигла пика, дизайн становится мощным инструментом для успеха бренда. Это не просто красивый внешний вид продукта или сайта — это. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru