Консультация № 167241
13.05.2009, 22:06
0.00 руб.
0 6 1
Помогите пожалуйста написать программу!
Задание: Создать класс BitString для работы с битовыми строками не более чем из 100 бит. Битовая строка должна быть представлена массивом типа unsigned char, каждый элемент которого принимает значение 0 или 1. Реальный размер массива задается как аргумент конструктора инициализации. Должны быть реализованы все традиционные операции для работы с битовыми строками: and, or, xor, not. Реализовать сдвиг влево и сдвиг вправо на заданное количество битов!

Для каждой структуры реализовать 3 конструктора: без аргументов, копирования и инициализации. Функции ввода/вывода оформить как дружественные.

Обсуждение

Неизвестный
14.05.2009, 07:07
общий
Вопросик:
Не слишком ли расточительно хранить один бит в байте? Ведь можно паковать их по 8 и соответственно сократить объем этой структуры данных.
Неизвестный
14.05.2009, 07:23
общий
ну впринцепи так и есть, по 8 будет по лучше
Неизвестный
17.05.2009, 11:20
общий
это ответ
Здравствуйте, Azarov88!
Программа. Тестировал в MS VS 2008.
Код:

#include <limits>
#include <stdexcept>
#include <iostream>
#include <vector>
#include <string>
using namespace std;

class bitstring
{
public:
// Тип элемента в котором будут храниться наши данные. int выбран только потому, что современные процессоры
// быстрее работают с 32х битными данными(при условии выравнивания по границе слова), чем с отдельными байтами.
// Если надо Вам unsigned char замените.
typedef unsigned int itemType;
// Конструктор
// value-значение
// length-длина нашей битовои строки(в битах)
bitstring(itemType value = 0, size_t length = _itemSize);
// Конструктор в качестве аргумента принимающий строку символов
bitstring(const string& str, size_t length = _itemSize);
// Битовые операции представлены стандартным набором
// И
bitstring operator&(const bitstring& b) const;
// ИЛИ
bitstring operator|(const bitstring& b) const;
// Исключающее ИЛИ
bitstring operator^(const bitstring& b) const;
// НЕ
bitstring operator~() const;
// Сдвиг влево
bitstring operator<<(unsigned char b) const;
// Сдвиг вправо
bitstring operator>>(unsigned char b) const;
// Индексатор
bool operator[](size_t bit);
// Возвращает размер в битах
size_t length() const;
private:
// Тип вектор для хранения данных
typedef vector<itemType> dataType;
// Количество бит в одном элементе вектора
static const size_t _itemSize = sizeof (itemType)*8;
// Здесь будем хранить число
dataType _data;
// Длина строки в битах
size_t _length;
// Используется внутри класса
bitstring(dataType& data, size_t length);
// Используется для получения маски в для битовых операций

static itemType createMask(size_t length)
{
size_t shift = length % _itemSize;
return ~((shift ? numeric_limits<itemType>::max() : 0) << shift);
}
// Используется внутри класса. Обнуляет лишние биты если длина битовой строки не кратна размеру элемента itemType

void trim()
{
if (_data.size())_data[_data.size() - 1] &= createMask(_length);
}
// Операторы ввода-вывода
friend istream & operator>>(istream& stream, bitstring& b);
friend ostream & operator<<(ostream& stream, const bitstring& b);
};
// Будем использовать для ввода битовых строк

void bitstringInput(string msg, bitstring& res)
{
while (true)
{
cout << msg;
cin >> res;
if (cin.fail())
{
cout << "Ошибочный ввод" << endl;
cin.clear();
cin.ignore(numeric_limits<streamsize>::max(), '\n');
}
else
{
cin.ignore(numeric_limits<streamsize>::max(), '\n');
break;
}
}
}

int main()
{
setlocale(LC_ALL, "russian");
// Объявим 2 битовых строки длиной 64 и 16 бит
bitstring A(0, 64), B(0, 16);
// Вводим их
bitstringInput("Введите A:", A);
bitstringInput("Введите B:", B);
// Пример операций
cout << "A=" << A << endl;
cout << "B=" << B << endl;
cout << "A&B=" << (A & B) << endl;
cout << "A|B=" << (A | B) << endl;
cout << "A^B=" << (A^B) << endl;
cout << "~A=" << (~A) << endl;
cout << "~B=" << (~B) << endl;
cout << "A>>2=" << (A >> 2) << endl;
cout << "B>>7=" << (B >> 7) << endl;
cout << "A<<2=" << (A << 2) << endl;
cout << "B<<7=" << (B << 7) << endl;

#ifdef _WIN32
system("PAUSE");
#endif

return 0;
}

bitstring::bitstring(itemType value, size_t length)
: _length(length)
{
if (_length == 0)_length = _itemSize;
size_t dataLength = _length / _itemSize + (_length % _itemSize ? 1 : 0);
_data.resize(dataLength, 0);
_data[0] = value;
trim();
}

bitstring::bitstring(const string& str, size_t length)
: _length(length)
{
if (_length == 0)_length = str.length();
size_t dataLength = _length / _itemSize + (_length % _itemSize ? 1 : 0);
_data.resize(dataLength, 0);
string::const_reverse_iterator strIt = str.rbegin();
dataType::iterator dataIt = _data.begin();
while (strIt != str.rend() && dataIt != _data.end())
{
size_t bitsCount = 0;
itemType value = 0;
while (strIt != str.rend() && bitsCount < _itemSize)
{
switch (*strIt)
{
case '0':
break;
case '1':
value |= (1 << bitsCount);
break;
default:
_data.clear();
throw invalid_argument("This is not bit String");
}
++bitsCount;
++strIt;
}
*dataIt++ = value;
}
trim();
}

bitstring::bitstring(dataType& data, size_t length)
: _data(data)
, _length(length)
{
if (!_data.size())_data.push_back(0);
if (_length == 0)_length = _itemSize;
size_t dataLength = _length / _itemSize + (_length % _itemSize ? 1 : 0);
_data.resize(dataLength, 0);
trim();
}

bitstring bitstring::operator&(const bitstring& b) const
{
size_t maxBits = max(_length, b._length);
size_t minLen = min(_data.size(), b._data.size());
dataType data(minLen);
for (size_t i = 0; i < minLen; ++i)
{
data[i] = _data[i] & b._data[i];
}
return bitstring(data, maxBits);
}

bitstring bitstring::operator|(const bitstring& b) const
{
size_t maxBits = max(_length, b._length);
size_t minLen = min(_data.size(), b._data.size());
size_t maxLen = max(_data.size(), b._data.size());
dataType data(maxLen);
for (size_t i = 0; i < minLen; ++i)
{
data[i] = _data[i] | b._data[i];
}
const dataType* from = 0;
if (_data.size() > b._data.size())from = &_data;
else if (_data.size() < b._data.size())from = &b._data;
if (from)
{
for (size_t i = minLen; i < maxLen; ++i)
{
data[i] = (*from)[i];
}
}
return bitstring(data, maxBits);
}

bitstring bitstring::operator^(const bitstring& b) const
{
size_t maxBits = max(_length, b._length);
size_t minLen = min(_data.size(), b._data.size());
size_t maxLen = max(_data.size(), b._data.size());
dataType data(maxLen);
for (size_t i = 0; i < minLen; ++i)
{
data[i] = _data[i]^b._data[i];
}
const dataType* from = 0;
if (_data.size() > b._data.size())from = &_data;
else if (_data.size() < b._data.size())from = &b._data;
if (from)
{
for (size_t i = minLen; i < maxLen; ++i)
{
data[i] = (*from)[i]^0;
}
}
return bitstring(data, maxBits);
}

bitstring bitstring::operator~() const
{
dataType data(_data.size());
for (size_t i = 0; i < _data.size(); ++i)
{
data[i] = ~_data[i];
}
return bitstring(data, _length);
}

bitstring bitstring::operator<<(unsigned char b) const
{
dataType data(_data);
int distance = b / _itemSize;
int shift = b % _itemSize;
if (distance)
{
for (size_t i = distance, j = 0; i < data.size(); ++i, ++j)
{
data[i] = data[j];
data[j] = 0;
}
}
itemType carry = 0;
itemType mask = ~(numeric_limits<itemType>::max() >> shift);
for (dataType::iterator it = data.begin(); it != data.end(); ++it)
{
itemType newCarry = ((*it) & mask) >> (_itemSize - shift);
*it = ((*it) << shift) | carry;
carry = newCarry;
}
return bitstring(data, _length);
}

bitstring bitstring::operator>>(unsigned char b) const
{
dataType data(_data);
int distance = b / _itemSize;
int shift = b % _itemSize;
if (distance)
{
for (size_t i = distance, j = 0; i < data.size(); ++i, ++j)
{
data[j] = data[i];
data[i] = 0;
}
}
itemType carry = 0;
itemType mask = ~(numeric_limits<itemType>::max() << shift);
for (dataType::reverse_iterator it = data.rbegin(); it != data.rend(); ++it)
{
itemType newCarry = ((*it) & mask) << (_itemSize - shift);
*it = ((*it) >> shift) | carry;
carry = newCarry;
}
return bitstring(data, _length);
}

bool bitstring::operator[](size_t bit)
{
if (bit < _length)
{
unsigned int itemNo = bit / _itemSize;
unsigned int shift = bit % _itemSize;
itemType mask = 1 << shift;
return (_data[itemNo] & mask) != 0;
}
else throw range_error("bool operator[](unsigned int bit):parameter 'bit' out of range");
}

inline size_t bitstring::length() const
{
return _length;
}

istream & operator>>(istream& stream, bitstring& b)
{
string str;
stream >> str;
bitstring::dataType data;
for (string::const_reverse_iterator it = str.rbegin(); it != str.rend();)
{
size_t bitsCount = 0;
bitstring::itemType value = 0;
while (it != str.rend() && bitsCount < b._itemSize)
{
switch (*it)
{
case '0':
break;
case '1':
value |= (1 << bitsCount);
break;
default:
stream.setstate(ios::badbit);
return stream;
}
++bitsCount;
++it;
}
data.push_back(value);
}
if (b._length == 0)b._length = b._itemSize;
size_t dataLength = b._length / b._itemSize + (b._length % b._itemSize ? 1 : 0);
data.resize(dataLength, 0);
data[data.size() - 1] &= bitstring::createMask(b._length);
b._data = data;
return stream;
}

ostream & operator<<(ostream& stream, const bitstring& b)
{
string res;
for (bitstring::dataType::const_iterator it = b._data.begin(); it != b._data.end(); ++it)
{
unsigned int count = 0;
bitstring::itemType value = *it;
while (count < b._itemSize)
{
if (value & 1)res = '1' + res;
else res = '0' + res;
value >>= 1;
++count;
}
}
if (res.length() > b._length)res.erase(0, res.length() - b._length);
res.erase(0, res.find('1'));
if (res.empty())res = '0';
stream << res;
return stream;
}

Пример работы:
Код:

Введите A:1011010010110101
Введите B:1101101010101010
A=1011010010110101
B=1101101010101010
A&B=1001000010100000
A|B=1111111010111111
A^B=110111000011111
~A=1111111111111111111111111111111111111111111111110100101101001010
~B=10010101010101
A>>2=10110100101101
B>>7=110110101
A<<2=101101001011010100
B<<7=101010100000000
5
Неизвестный
17.05.2009, 13:57
общий
Обратите внимание было
Код:

// Объявим 2 битовых строки длиной 64 и 16 бит
bitstring A(0,5),B(0,9);

Исправил на
Код:

// Объявим 2 битовых строки длиной 64 и 16 бит
bitstring A(0,64),B(0,16);

чтоб соответствовало комментарию.
Это я проводил эксперименты и забыл вернуть на место.
5,9,64,16-это длина битовой строки(в битах). Задавайте какое Вам надо значение.
Неизвестный
17.05.2009, 14:12
общий
Спасибо!
Неизвестный
17.05.2009, 14:27
общий
Немного исправил. Скопируйте код по новой.
Форма ответа