2018年01月22日
《その250》 問題演習 p.329演習9-4
新版明解C++中級編 p.329 演習9-4
前回《249》演習9-3 の問題文に ヘッダファイル Array.h のコードを記載してありますが、そのヘッダにある Array<>クラステンプレートは、配列要素を1つの添字でアクセスするもので、1次元配列に相当します。
Array<>クラステンプレートを参考にして、
2つの添字をもつ2次元配列クラステンプレート Matrix<> を作成せよ。
// 解答
// Matrix.h
#ifndef ___ClassTemplate_Matrix
#define ___ClassTemplate_Matrix
template <class Type> class Matrix {
int mm; // 先頭側添字
int nn; // 末尾側添字
Type* vec; // 配列先頭要素へのポインタ
// 添字として適なら true、否なら false
bool is_valid_index(int idx0, int idx1) {
return (idx0 >= 0 && idx0 < mm)
&& (idx1 >= 0 && idx1 < nn);
}
public:
// 添字範囲例外クラス
class IdxRngErr {
const Matrix* ident;
int idx0;
int idx1;
public:
IdxRngErr(const Matrix* x, int i, int j)
: ident(x), idx0(i), idx1(j) { }
int index0() const { return idx0; }
int index1() const { return idx1; }
};
// コンストラクタ
Matrix(
int size0, // 先頭側添字
int size1, // 末尾側添字
const Type& v = Type() // 初期値
) : mm(size0), nn(size1) {
vec = new Type[mm * nn];
for (int i = 0; i < mm; i++)
for(int j = 0; j < nn; j++)
vec[nn * i + j] = v; // 初期値 v
}
// コピーコンストラクタ
Matrix(const Matrix<Type>& x) {
if (&x == this) {
mm = 0;
nn = 0;
vec = NULL;
}
else {
mm = x.mm;
nn = x.nn;
vec = new Type[mm * nn];
for (int i = 0; i < mm * nn ; i++)
vec[i] = x.vec[i];
}
}
// デストラクタ
~Matrix() { delete[] vec; }
// 先頭側添字のゲッタ
int size0() const { return mm; }
// 末尾側添字のゲッタ
int size1() const { return nn; }
// 代入演算子
Matrix& operator=(const Matrix<Type>& x) {
if (&x != this) {
if (mm != x.mm || nn != x.nn) {
delete[] vec;
mm = x.mm;
nn = x.nn;
vec = new Type[mm * nn];
}
for (int i = 0; i < mm * nn; i++)
vec[i] = x.vec[i];
}
return *this;
}
// ゲッタ
Type ary(int i, int j) const {
if (!is_valid_index(i, j))
throw IdxRngErr(this, i, j);
return vec[i * nn + j];
}
// ゲッタ かつ セッタ
Type& ary(int i, int j) {
if (!is_valid_index(i, j))
throw IdxRngErr(this, i, j);
return vec[i * nn + j];
}
};
#endif
// p329_9_4.cpp
#include <iomanip>
#include <iostream>
#include "Matrix.h"
using namespace std;
int main() {
cout << "(1) 初期化と値の表示\n";
Matrix<int> a(2, 3);
for (int i = 0; i < a.size0(); i++) {
for (int j = 0; j < a.size1(); j++)
cout << setw(3) << a.ary(i, j) << " ";
cout << '\n';
}
cout << "\n(2) 値の代入と表示\n";
for (int i = 0; i < a.size0(); i++)
for (int j = 0; j < a.size1(); j++)
a.ary(i, j) = 3 * i + j;
for (int i = 0; i < a.size0(); i++) {
for (int j = 0; j < a.size1(); j++)
cout << setw(3) << a.ary(i, j) << " ";
cout << '\n';
}
cout << "\n(3) コピーコンストラクタ\n";
Matrix<int> b(a);
b.ary(1, 1) = 99; // ary(1, 1) に 99 を代入
for (int i = 0; i < b.size0(); i++) {
for (int j = 0; j < b.size1(); j++)
cout << setw(3) << b.ary(i, j) << " ";
cout << '\n';
}
cout << "\n(4) 代入,添字の確認\n";
Matrix<int> c(5, 6);
cout << "配列 c の先頭側添字 : " << c.size0() << '\n'
<< " 末尾側添字 : " << c.size1() << "\n\n";
c = a;
cout << "配列 c の先頭側添字 : " << c.size0() << '\n'
<< " 末尾側添字 : " << c.size1() << '\n';
cout << "\n(5) 代入後の値を表示\n";
for (int i = 0; i < c.size0(); i++) {
for (int j = 0; j < c.size1(); j++)
cout << setw(3) << c.ary(i, j) << " ";
cout << '\n';
}
cout << "\n(6) 添字エラー\n";
try {
for (int i = 0; i < 5; i++) {
for (int j = 0; j < 6; j++)
cout << setw(3) << c.ary(i, j) << " ";
cout << '\n';
}
}
catch (Matrix<int>::IdxRngErr& e) {
cout << "添字エラー!!\n";
cout << "先頭側添字 : " << e.index0() << '\n'
<< "末尾側添字 : " << e.index1() << "\n\n";
}
}
この記事へのコメント
コメントを書く
この記事へのトラックバックURL
https://fanblogs.jp/tb/7226480
※ブログオーナーが承認したトラックバックのみ表示されます。
この記事へのトラックバック