C/C++ ポインタ入門 > 動的配列クラス 演習問題
(C) by Nobuhide Tsuda
Jan-2014
演習問題
Vector は int 型データを要素として持つ動的配列クラスです。
operator[](ix), at(ix) で要素を参照でき、push_back(d), insert(ix, d), erase(ix) 等で要素を挿入、削除することが出来ます。
要素挿入時にデータ領域の容量が足りなくなると、データ領域が自動的に拡張されます。
上記以外にも、isEmpty(), size() などオブジェクトの状態を返すメンバ関数や、
resize(sz), reserve(sz) などでオブジェクトの状態を変えるメンバ関数を持ちます。
データタイプが int型固定の std::vector と概ね同一です。
Vector は要素を格納する領域を動的に確保し、m_data がそこを指します。
確保したデータ領域サイズは m_capacity に格納されます。
データ領域の頻繁な再確保を避けるために、領域は実際のサイズよりも余分に確保されます。
m_size にデータ領域に実際に格納されている要素数が格納されます。
要素が追加されデータ領域が足りなくなった場合、領域サイズは2倍されてメモリが確保され、
古い領域から新しい領域に要素がコピーされ、古い領域のメモリは解放されます。
- ★下記のクラスを定義するコードを書き、ビルドしてみなさい。
class Vector {
private:
int *m_data; // アロケートされたデータ領域へのポインタ
int m_size; // データ領域に入っている要素数
int m_capacity; // アロケートされたデータ領域サイズ
};
- ★ Vector クラスのオブジェクトを生成するコードを記述、ビルドし、デバッガでオブジェクトが生成されていることを確認しなさい。
- ★ Vector クラスにコンストラクタ Vector() を追加し、メンバ変数を全て 0 に初期化するようにしなさい。
- Vector オブジェクトを生成し、メンバ変数が全て 0 で初期化されていることをデバッガで確認しなさい。
- 解答例
- ★ コンストラクタ Vector() で、サイズを 0、キャパシティを 8 に設定し、m_data のための領域を new で確保しなさい。
- Vector オブジェクトを生成し、メンバ変数が正常に初期化されていることをデバッガで確認しなさい。
- テストコード、
解答例
- ★ Vector クラスにデストラクタ ~Vector() を追加し、m_data を delete するようにしなさい。
- Vector オブジェクトを生成・破棄し、デバッガでデストラクタが呼ばれていることを確認しなさい。
- 解答例
- ★★ Vector クラスにサイズ指定コンストラクタ Vector(int sz, int d = 0) を追加し、
sz 個の要素を持った動的配列を構築可能にしなさい。要素の値は第2引数で指定するものとする。
- Vector v1(5); でオブジェクトを生成し、サイズが5, 要素が全て0に初期化されていることをデバッガで確認しなさい。
- Vector v2(8, 3); でオブジェクトを生成し、サイズが8, 要素が全て3に初期化されていることをデバッガで確認しなさい。
- Vector v3(10, 2); でオブジェクトを生成し、サイズが10, 要素が全て2に初期化されていることをデバッガで確認しなさい。
- テストコード、
解答例
- ★★ Vector クラスにデータ指定コンストラクタ Vector(const int *first, const int *last) を追加し、
初期化データを指定可能にしなさい。
- int d[] = {3, 1, 4, 1}; Vector v(d, d+4); でオブジェクトを生成し、サイズが4, 要素が全て正しく初期化されていることをデバッガで確認しなさい。
ただし、first < last と仮定していよいものとする。
- int d2[] = {3, 1, 4, 1, 5, 9, 2, 6}; Vector v2(d2, d2+8); でオブジェクトを生成し、サイズが8, 要素が全て正しく初期化されていることをデバッガで確認しなさい。
ただし、first < last と仮定していよいものとする。
- テストコード、
解答例
- ★★ Vector クラスにコピーコンストラクタ Vector(const Vector &x) を追加し、
引数オブジェクト x の内容をコピーするようにしなさい。
- int d[] = {3, 1, 4, 1}; Vector v(d, d+4); Vector v2(v) でオブジェクトを生成し、
v2 が、サイズが4, 要素が {3, 1, 4, 1} に初期化されていることをデバッガで確認しなさい。
- テストコード、
解答例
- ★bool isEmpty() const Vector の要素が空かどうかを判定するメンバ関数を実装しなさい。
- Vector クラスのオブジェクト v を生成し、v.isEmpty() が true を返すことを確認しなさい。
- Vector v2(3) を生成し、v2.isEmpty() が false を返すことを確認しなさい。
- テストコード、
解答例
- ★int size() const Vector の要素数を返すメンバ関数を実装しなさい。
- Vector クラスのオブジェクト v を生成し、v.size() が 0 を返すことを確認しなさい。
- Vector v2(3) を生成し、v2.size() が 3 を返すことを確認しなさい。
- テストコード、
解答例
- ★int capacity() const Vector のアロケート済みデータ領域サイズを返すメンバ関数を実装しなさい。
- Vector クラスのオブジェクト v を生成し、v.capacity() が 8 を返すことを確認しなさい。
- Vector v2(10) を生成し、v2.capacity() が 10 以上を返すことを確認しなさい。
- テストコード、
解答例
- ★int front() const 配列の先頭要素を返すメンバ関数を実装しなさい。配列要素が空の場合は -1 を返しなさい
- Vector v; でオブジェクトを生成し、v.front() が -1 を返すことを確認しなさい。
- Vector v2(3); でオブジェクトを生成し、v2.front() が 0 を返すことを確認しなさい。
- int d[] = {3, 2, 1}; Vector v3(d, d+3); でオブジェクトを生成し、v3.front() が 3 を返すことを確認しなさい。
- テストコード、
解答例
- ★int back() const 配列の末尾要素を返すメンバ関数を実装しなさい。配列要素が空の場合は -1 を返しなさい
- Vector v; でオブジェクトを生成し、v.back() が -1 を返すことを確認しなさい。
- Vector v2(3); でオブジェクトを生成し、v2.back() が 0 を返すことを確認しなさい。
- int d[] = {3, 2, 1}; Vector v3(d, d+3); でオブジェクトを生成し、v3.back() が 1 を返すことを確認しなさい。
- テストコード、
解答例
- ★int at(int ix) const ix 番目の要素を返すメンバ関数を実装しなさい。ix が範囲外の場合は -1 を返しなさい。
- int d[] = {3, 1, 4, 1}; Vector v(d, d+4); でオブジェクトを生成し、v.at(0) ~ v.at(3) が {3, 1, 4, 1} 返すことを確認しなさい。
- テストコード、
解答例
- ★int operator[](int ix) const ix 番目の要素を返す [] 演算子をオーバロードしなさい。ix が範囲外の場合は -1 を返しなさい。
- int d[] = {3, 1, 4, 1}; Vector v(d, d+4); でオブジェクトを生成し、v[0] ~ v[3] が {3, 1, 4, 1} を返すことを確認しなさい。
- テストコード、
解答例
- ★void clear() 配列要素数(サイズ)をゼロにするメンバ関数を実装しなさい。
- Vector v(5); v.clear(); を実行し、v のサイズがゼロになっていることを確認しなさい。
- テストコード、
解答例
- ★★★void reserve(int sz) キャパシティが指定サイズ未満の場合は、指定サイズ以上になるようにデータ領域を拡張しなさい。
ただし、キャパシティは常に 2のべき乗の値(8, 16, 32, 64, ...)とする。
- Vector クラスのオブジェクト v を生成し、v.reserve(16); を実行し、キャパシティが 16 になることを確認しなさい。
- v.reserve(20); を実行し、キャパシティが 32 になることを確認しなさい。
- v.reserve(0); を実行し、キャパシティが 32 のままであることを確認しなさい。
- int d[] = {3, 1, 4, 1}; Vector v2(d, d+4); v2.reserve(10); を実行し、v2[0]~v2[3] が {3, 1, 4, 1} であることを確認しなさい。
- テストコード、
解答例
- ★★void resize(int sz) 配列サイズを指定サイズに設定するメンバ関数を実装しなさい。
増えた要素は初期化する必要は無い。sz がマイナスの場合は、サイズを 0 にしなさい。
- Vector クラスのオブジェクト v を生成し、v.resize(16); を実行し、サイズ、キャパシティが 16 になることを確認しなさい。
- v.resize(20); を実行し、サイズが 20、キャパシティが 32 になることを確認しなさい。
- v.resize(-1); を実行し、サイズが 0、キャパシティが 32 になることを確認しなさい。
- テストコード、
解答例
- ★★void push_back(int d) 配列末尾に d を追加するメンバ関数を実装しなさい。
- Vector クラスのオブジェクト v を生成し、v.push_back(10); を実行し、v[0] が10、サイズが 1 になることを確認しなさい。
- 続けて、v.push_back(20); を 10 回実行し、要素が正しく格納されていること、サイズが 11、キャパシティが 16 になることを確認しなさい。
- Vector v2; for(int i = 1; i <= 10; ++i) v2.push_back(i); を実行し、v2[0]~v2[9] が 1~10 であることを確認しなさい。
- テストコード、
解答例
- ★★int pop_back() 配列末尾を削除し(サイズをデクリメント)、それを返すメンバ関数を実装しなさい。
配列要素が無い場合は、-1 を返しなさい
- Vector クラスのオブジェクト v を生成し、v.pop_back() が -1 を、v.size() が 0 を返すことを確認しなさい。
- v.push_back(20); v.push_back(10); を実行し、pop_back(); が 10 を返すことを確認しなさい。
- 再度 pop_back(); を実行し、20 を返すことを確認しなさい。
- テストコード、
解答例
- ★★int &operator[](int ix) ix 番目の要素の参照を返す [] 演算子をオーバロードしなさい。ix の範囲チェックは行わなくてよい。
- Vector v(5); でオブジェクトを生成し、v[0] ~ v[4] に適当な値を代入し、正しく代入されることを確認しなさい。
- テストコード、
解答例
- ★★void swap(Vector &x) オブジェクトの内容全てを x と交換するメンバ関数を実装しなさい。
- Vector v1, v2(5); を生成し、v1.swap(v2); を実行し、中身が入れ替わっていることを確認しなさい。
- int d[] = {3, 1, 4, 1}; Vector v3(d, d+4), v4(10, 5); v3.swap(v4); を実行し、中身が入れ替わっていることを確認しなさい。
- テストコード、
解答例
- ★★void insert(int ix, int d)
ix の位置に要素 d を挿入するメンバ関数を実装しなさい。
ix < 0 の場合は先頭に、ix > size() の場合は末尾に挿入しなさい。
- Vector v(4); v.insert(2, 1); を実行し、データが {0, 0, 1, 0, 0} になっていることを確認しなさい。
- つづけて、v.insert(-1, 2); を実行し、データが {2, 0, 0, 1, 0, 0} になっていることを確認しなさい。
- つづけて、v.insert(10, 3); を実行し、データが {2, 0, 0, 1, 0, 0, 3} になっていることを確認しなさい。
- テストコード、
解答例
- ★★void erase(int ix)
ix 位置の要素を削除し、それ以降のデータを前に移動するメンバ関数を実装しなさい。
ix < 0 または ix >= size() の場合は何も処理をしなくてよい。
- int d[] = {3, 1, 4, 1}; Vector v(d, d+4); v.erase(-1); 実行後、データが {3, 1, 4, 1} のままであることを確認しなさい。
- 続けて、v.erase(4); を実行し、データが {3, 1, 4, 1} のままであることを確認しなさい。
- 続けて、v.erase(1); を実行し、データが {3, 4, 1} であることを確認しなさい。
- 続けて、v.erase(2); を実行し、データが {3, 4} であることを確認しなさい。
- 続けて、v.erase(1); を実行し、データが {3} であることを確認しなさい。
- 続けて、v.erase(0); を実行し、データが空であることを確認しなさい。
- テストコード、
解答例
- ★★void assign(int sz, int d)
配列を要素数 sz、全ての要素の値 d に初期化しなおしなさい。
- Vector v(4); v.assign(2, 1); を実行し、サイズが 2 に、要素がすべて 1 になっていることを確認しなさい。
- つづけて、v.assign(10, 3); を実行し、サイズが 10 になり、要素がすべて 3 になっていることを確認しなさい。
- テストコード、
解答例
前:
|上:C/C++ ポインタ入門
|次: