アフィリエイト広告を利用しています

広告

この広告は30日以上更新がないブログに表示されております。
新規記事の投稿を行うことで、非表示にすることが可能です。
posted by fanblog

2018年01月31日

《その268》 問題演習 p.349演習9-9



新版明解C++中級編 p.349 演習9-9
 下記のスタッククラステンプレート SimpleStack<> は、インクルードモデルで実現されています。このクラステンプレートに、以下のメンバ関数を追加せよ。
   Type& peek()  … 頂上のデータを削除することなく返す。
   int capacity() … スタックの容量を返す。
   bool is_full() … スタックが満杯であるかどうかを返す。
   bool is_empty() … スタックが空であるかどうかを返す。
 なお、例外が送出・捕捉されるような利用例のプログラムもあわせて作ること。

// SimpleStack.h
#ifndef ___Class_SimpleStack
#define ___Class_SimpleStack

// スタッククラステンプレート
template<class Type> class SimpleStack {
int size; // スタック容量
int ptr; // スタックポインタ
Type* stk; // 先頭要素へのポインタ

// コピーコンストラクタの無効化
SimpleStack(const SimpleStack<Type>&);

// 代入演算子の無効化
SimpleStack& operator=(const SimpleStack<Type>&);

public:
class Overflow { }; // Overflow例外
class Empty { }; // Empty例外

// コンストラクタ
explicit SimpleStack(int sz);

// デストラクタ
~SimpleStack();

// push
Type& push(const Type& x);

// pop
Type pop();
};

#include "SimpleStackImplementation.h"

#endif




// SimpleStackImplementation.h
#ifndef ___Class_SimpleStackImplementation
#define ___Class_SimpleStackImplementation

// コンストラクタ
template<class Type>
SimpleStack<Type>::SimpleStack(int sz)
: size(sz), ptr(0) {
stk = new Type[size];
}

// デストラクタ
template<class Type>
SimpleStack<Type>::~SimpleStack() {
delete[] stk;
}

// push
template<class Type>
Type& SimpleStack<Type>::push(const Type& x) {
if (ptr >= size)
throw Overflow();
return stk[ptr++] = x;
}

// pop
template<class Type>
Type SimpleStack<Type>::pop() {
if (ptr <= 0)
throw Empty();
return stk[--ptr];
}

#endif



// 解答


// SimpleStack.h
#ifndef ___Class_SimpleStack
#define ___Class_SimpleStack

// スタッククラステンプレート
template<class Type> class SimpleStack {
int size; // スタック容量
int ptr; // スタックポインタ
Type* stk; // 先頭要素へのポインタ

// コピーコンストラクタの無効化
SimpleStack(const SimpleStack<Type>&);

// 代入演算子の無効化
SimpleStack& operator=(const SimpleStack<Type>&);

public:
class Overflow { }; // Overflow例外
class Empty { }; // Empty例外

// コンストラクタ
explicit SimpleStack(int sz);

// デストラクタ
~SimpleStack();

// push
Type& push(const Type& x);

// pop
Type pop();

// ★頂上のデータを削除することなく返す。
Type& peek();

// ★スタックの容量を返す。
int capacity();

// ★スタックが満杯であるかどうかを返す。
bool is_full();

// ★スタックが空であるかどうかを返す。
bool is_empty();
};

#include "SimpleStackImplementation.h"

#endif




// SimpleStackImplementation.h
#ifndef ___Class_SimpleStackImplementation
#define ___Class_SimpleStackImplementation

// コンストラクタ
template<class Type>
SimpleStack<Type>::SimpleStack(int sz)
: size(sz), ptr(0) {
stk = new Type[size];
}

// デストラクタ
template<class Type>
SimpleStack<Type>::~SimpleStack() {
delete[] stk;
}

// push
template<class Type>
Type& SimpleStack<Type>::push(const Type& x) {
if (ptr >= size)
throw Overflow();
return stk[ptr++] = x;
}

// pop
template<class Type>
Type SimpleStack<Type>::pop() {
if (ptr <= 0)
throw Empty();
return stk[--ptr];
}

// ★頂上のデータを削除することなく返す。
template<class Type>
Type& SimpleStack<Type>::peek() {
if (ptr <= 0)
throw Empty();
int temp = ptr - 1;
return stk[temp];
}

// ★スタックの容量を返す。
template<class Type>
int SimpleStack<Type>::capacity() {
return size;
}

// ★スタックが満杯であるかどうかを返す。
template<class Type>
bool SimpleStack<Type>::is_full() {
return size == ptr;
}

// ★スタックが空であるかどうかを返す。
template<class Type>
bool SimpleStack<Type>::is_empty() {
return ptr == 0;
}

#endif




// SimpleStackTest.cpp
#include <string>
#include <iostream>
#include "SimpleStack.h"
using namespace std;

void push_it(SimpleStack<char>& s, char c) {
try {
s.push(c);
}
catch (const SimpleStack<char>::Overflow&) {
cout << "\a !満杯の<char>スタックに"
"プッシュしようとしました。\n";
}
}

void pop_it(SimpleStack<char>& s) {
try {
char c = s.pop();
cout << ' ' << c << '\n';
}
catch (const SimpleStack<char>::Empty&) {
cout << "\a !空の<char>スタックから"
"ポップしようとしました。\n";
}
}

void pop_all(SimpleStack<char>& s) {
if (s.is_empty()) {
pop_it(s); goto L;
}
while (!s.is_empty()) {
cout << ' ' << s.pop();
}
cout << '\n';
L:;
}

int main() {
int nn;
cout << "スタックの容量 : "; cin >> nn;
SimpleStack<char> s(nn);
cout << "容量 " << s.capacity()
<< " のスタックを準備しました。\n";

while (1) {
int f; char c;
cout << "◆ 1.push 2.pop 3.文字列をpush "
"4.頂上のデータ 5.全データをpop "
"0.終了 : "; cin >> f;
if (f == 1) {
cout << " 文字 : "; cin >> c;
push_it(s, c);
}
else if (f == 2)
pop_it(s);
else if (f == 3) {
string x;
cout << " 文字列:";
cin >> x;

for (unsigned i = 0; i < x.length(); i++)
push_it(s, x[i]);
}
else if (f == 4)
cout << ' ' << s.peek() << '\n';
else if (f == 5) {
pop_all(s);
}
else break;

if (s.is_full()) cout << " ※満\n";
if (s.is_empty()) cout << " ※空\n";
}
}

f09_0904.png




《その267》 補足(前回《266》の 関数テンプレートに関して)


 前回《266》 演習9-8(3)の問題文にある FixedArrayTest.cpp で、最初に出てくる関数テンプレート print_FixedArray がちゃんと動くのが、初心者の自分にはちょっと不思議な気がしたので、プログラムで確認してみました。


 下記のプログラムでは、
 ・1) クラステンプレート C を使って作成した C型クラスオブジェクト c を、
    関数テンプレート f に渡します。
 ・2) 関数テンプレート f は、そのオブジェクト c を 仮引数 C<T1, T2>& a で受け取ります。

 関数テンプレート f は、この仮引数からの情報だけで T1, T2 の型を決定してくれるんですね。とりあえず理解できました。
初歩的な内容ですみません m(_ _)m

#include <iostream>

template <class Type1, class Type2> class C {
public:
Type1 t1;
Type2 t2;
C(Type1 x, Type2 y) : t1(x), t2(y) { }
};

template <class T1, class T2>
void f(C<T1, T2>& a) {
std::cout << typeid(T1).name() << '\n';
std::cout << typeid(T2).name() << '\n';
std::cout << a.t1 << ' ' << a.t2 << '\n';
}

int main() {
C<char, int> c('a', 100);
f(c);
}

f09_0061.png




 たまに、クリック お願いします m(_ _)m

 AA にほんブログ村 IT技術ブログ C/C++へ

こうすけ:メール kousuke_cpp@outlook.jp

【1】★★C++ 記事目次★★ ← 利用可能です。
・新版明解C++入門編 / 新版明解C++中級編
・その他 C++ 関連記事

【2】★★こうすけ@C#★★
・C# の初歩的な記事


検索
<< 2018年01月 >>
  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      
プロフィール
こうすけさんの画像
こうすけ

 たまに、クリック お願いします m(_ _)m

 AA にほんブログ村 IT技術ブログ C/C++へ

こうすけ:メール kousuke_cpp@outlook.jp

【1】★★C++ 記事目次★★ ← 利用可能です。
・新版明解C++入門編 / 新版明解C++中級編
・その他 C++ 関連記事

【2】★★こうすけ@C#★★
・C# の初歩的な記事


×

この広告は30日以上新しい記事の更新がないブログに表示されております。