2018年01月25日
《その255》 問題演習 p.336演習9-6
新版明解C++中級編 p.336 演習9-6
Array<bool>型の配列に対して、対話的に処理を行うプログラムを作成せよ。
演習9-5《254》で作成したメンバ関数 get_vsize も利用すること。
// 解答
// Array.h
#ifndef ___ClassTemplate_Array___
#define ___ClassTemplate_Array___
template <class Type> class Array { };
#endif
// BoolArray.h
// template<> class Array<bool>
// 配列クラステンプレートArray<> を bool型に特殊化
#include <limits>
#include "Array.h"
template<> class Array<bool> {
typedef unsigned char BYTE;
static const int CHAR_BITS
= std::numeric_limits<unsigned char>::digits;
// bool型配列の要素数
int nelem;
// bool型配列を格納するためのBYTE型配列の要素数
int velem;
// BYTE型先頭要素へのポインタ
BYTE* vec;
// バイト型配列要素の必要数を算出
static int size_of(int sz) {
return (sz + CHAR_BITS - 1) / CHAR_BITS;
}
public:
// 該当バイト中の該当ビットへの参照を表すクラス
class BitOfByteRef {
BYTE& vec; // 参照先BYTE
int idx; // 参照先BYTE中のビット番号
public:
// コンストラクタ
BitOfByteRef(BYTE& r, int i)
: vec(r), idx(i) { }
// 該当ビットを bool型で返却
operator bool() const { return (vec >> idx) & 1U; }
// 該当ビットに true または false をセット
BitOfByteRef& operator=(bool b) {
if (b)
vec |= 1U << idx;
else
vec &= ~(1U << idx);
return *this;
}
};
// 添字範囲エラー
class IdxRngErr {
const Array* ident;
int index;
public:
IdxRngErr(const Array* p, int i) : ident(p), index(i) { }
int Index() const { return index; }
};
// コンストラクタ
explicit Array(int sz, bool v = bool())
: nelem(sz), velem(size_of(sz)) {
vec = new BYTE[velem];
// 全要素を初期化
for (int i = 0; i < velem; i++)
vec[i] = v;
}
// コピーコンストラクタ
Array(const Array& x) {
if (&x == this) {
nelem = 0;
vec = NULL;
}
else {
nelem = x.nelem;
velem = x.velem;
vec = new BYTE[velem];
for (int i = 0; i < velem; i++)
vec[i] = x.vec[i];
}
}
// デストラクタ
~Array() { delete[] vec; }
// 要素数を返す
int size() const { return nelem; }
// velem のゲッタ
int get_vsize() const {
return velem;
}
// 代入演算子
Array& operator=(const Array& x) {
if (&x != this) {
if (velem != x.velem) {
delete[] vec;
velem = x.velem;
vec = new BYTE[velem];
}
nelem = x.nelem;
for (int i = 0; i < velem; i++)
vec[i] = x.vec[i];
}
return *this;
}
// 添字演算子[]
BitOfByteRef operator[](int i) {
if (i < 0 || i >= nelem)
throw IdxRngErr(this, i);
return BitOfByteRef(
vec[i / CHAR_BITS], (i & (CHAR_BITS - 1))
);
}
// 添字演算子[]
bool operator[](int i) const {
if (i < 0 || i >= nelem)
throw IdxRngErr(this, i);
return
(vec[i / CHAR_BITS] >> (i & (CHAR_BITS - 1)) & 1U)
== 1;
}
};
// p336_9-6.cpp
// Test.cpp
#include <iomanip>
#include <iostream>
#include "Array.h"
#include "BoolArray.h"
using namespace std;
// 1バイトのビット数
const int CHAR_BITS
= std::numeric_limits<unsigned char>::digits;
// メニュー
int menu() {
int n;
cout << "\n 1)bool値セット"
" 2)要素連続表示"
" 3)全要素を表示"
" 4)データ格納状況"
" 5)終了\n";
do {
cout << "番号 : "; cin >> n;
} while (n < 1 || n > 5);
return n;
}
// bool値のセット
void
set(Array<bool>& a) {
int n;
int t;
while (1) {
do {
cout << "添字番号( 完了なら 999 ) : ";
cin >> n;
if (n == 999) goto OUT_1;
} while (n < 0 || n >= a.size());
do {
cout << "true(1) or false(0)";
cin >> t;
} while (t != 0 && t != 1);
if (t) a[n] = true; else a[n] = false;
}
OUT_1:;
}
// 全要素を 0, 1 で連続表示
void print_Array_bool(const Array<bool>& a) {
cout << "◇ 全要素を 0, 1 で連続表示\n";
for (int i = 0; i < a.size(); i++)
cout << (a[i] ? '1' : '0');
cout << '\n';
}
// 全要素を表示
void print_Array_all(const Array<bool>& a) {
cout << "◇ 全要素 ( 1 は true, 0 は false )\n";
int n = 0;
while (1) {
for (int i = 0; i < CHAR_BITS; i++) {
cout << "a[" << setw(2) << n << "] = "
<< a[n] << ' ';
n++;
if (n >= a.size()) {
cout << '\n'; goto OUT_2;
}
}
cout << '\n';
}
OUT_2:;
}
// データ格納場所でのビットの状況
void print_Array_bit(const Array<bool>& a) {
cout << "◇ データ格納場所でのビットの状況\n";
for (int i = 0; i < a.get_vsize(); i++) {
cout << "第" << i + 1 << "番目のバイト : ";
for (int j = CHAR_BITS * (i + 1) - 1;
j >= CHAR_BITS * i; j--)
try { cout << (a[j] ? '1' : '0'); }
catch (Array<bool>::IdxRngErr) {
cout << '0';
}
cout << '\n';
}
}
int main() {
int n;
do {
cout << "◆ bool型配列 a の要素数を入力 : ";
cin >> n;
} while (n < 1);
Array<bool> z(n);
while (1) {
switch (menu()) {
case 1:set(z); break;
case 2:print_Array_bool(z); break;
case 3:print_Array_all(z) ; break;
case 4:print_Array_bit(z) ; break;
default: goto OUT;
}
}
OUT:;
}
この記事へのコメント
コメントを書く
この記事へのトラックバックURL
https://fanblogs.jp/tb/7236430
※ブログオーナーが承認したトラックバックのみ表示されます。
この記事へのトラックバック