演習問題14解答例

問1 加算を行う関数テンプレート
問2 配列データのソートを行うクラステンプレート
問3 vector の使用例
問4 set の使用例
問5 map の使用例
問6 set とクラス

[問1]整数( int ),実数( double ),及び,文字列(クラスとして定義)の加算を行う関数テンプレート plus と,それらの結果の出力を行う関数 print を定義せよ.ただし,文字列の加算とは,文字列の連結を意味するものとする.
/******************************/
/* int, double, char * の加算 */
/*      coded by Y.Suganuma   */
/******************************/
#include <iostream>
#include <string.h>
/*
     クラスMojiの定義
*/
class Moji {
		char *str;
	public:
		Moji(char *);         // コンストラクタ(メモリ確保)
		Moji(const Moji &);   // コンストラクタ(初期化)
		~Moji()	{ delete [] str; }   // デストラクタ
		Moji &operator= (const Moji &);              // = のオーバーロード
	friend Moji operator + (Moji &, Moji &);         // + のオーバーロード
	friend ostream& operator << (ostream&, Moji);    // << のオーバーロード
};
                    // コンストラクタ(メモリの確保)
Moji::Moji(char *s)
{
	str = new char [strlen(s)+1];
	strcpy(str, s);
}
                    // コンストラクタ(初期化)
Moji::Moji(const Moji &b)
{
	str = new char [strlen(b.str)+1];
	strcpy(str, b.str);
}
                    // +のオーバーロード
Moji operator + (Moji &a, Moji &b)
{
	char *s = strcat(a.str, b.str);
	Moji c(s);
	return c;
}
                    // =のオーバーロード
Moji& Moji::operator= (const Moji &b)
{
	if (&b == this)
		return *this;
	else {
		delete [] str;
		str = new char [strlen(b.str)+1];
		strcpy(str, b.str);
		return *this;
	}
}
                    // << のオーバーロード
ostream& operator << (ostream& stream, Moji a)
{
	stream << a.str;
	return stream;
}
                    // 加算
template <class tp> tp add(tp a, tp b)
{
	tp c = a + b;
	return c;
}
                    // main
int main()
{
	Moji a("test "), b("data");
	std::cout << add(a, b) << std::endl;

	double d1 = 10.0, d2 = 0.7;
	std::cout << add(d1, d2) << std::endl;

	int i1 = 2, i2 = 3;
	std::cout << add(i1, i2) << std::endl;

	return 0;
}
		
[問2] n 個の任意の型のデータをディスクから配列に読み込み,ソートして配列に保存するクラステンプレートを作成せよ.
/****************************/
/* 任意のデータ型のソート   */
/*      coded by Y.Suganuma */
/****************************/
#include <iostream>
#include <fstream>
#include <stdlib.h>
using namespace std;
                    // クラスSort
template <class tp, int size> class Sort {
		int size;   // 最大データ数
		int m;      // 実際のデータ数
		tp *p;
	public:
		Sort(char *);
		~Sort() {delete [] p;}
		void print();
};
                    // コンストラクタ
template <class tp, int size> Sort <tp, size> :: Sort(char *f_name)
{
                              // メンバー変数の設定
	m = 0;
	p = new tp [size];
                              // データの読み込み
	ifstream in(f_name);

	while (m < size && !in.eof()) {
		in >> p[m];
		m++;
	}
                              // ソート
	int sw = 0;
	tp wk;
	while (sw == 0) {
		sw = 1;
		for (int i1 = 0; i1 < m-1; i1++) {
			if (p[i1] > p[i1+1]) {
				wk      = p[i1];
				p[i1]   = p[i1+1];
				p[i1+1] = wk;
				if (i1 != 0)
					sw = 0;
			}
		}
	}
}

template <class tp, int size> void Sort <tp, size> :: print()
{
	for (int i1 = 0; i1 < m; i1++)
		cout << p[i1] << endl;
}

int main()
{
	Sort < char, 20 > a("test1");
	Sort < int, 20 > b("test2");
	Sort < double, 20 > c("test3");

	cout << "文字\n";
	a.print();
	cout << "整数\n";
	b.print();
	cout << "実数\n";
	c.print();

	return 0;
}
		
[問3] n 個( 15 個以上)の異なる整数データを読み込み( vector に保存),昇順にソートした後,小さい方から 5 つ,及び,大きい方から 5 つ以外のデータを全て削除し,残りのデータを出力すると共にそれらの平均値を出力するプログラムを書け.
#include <iostream>
#include <vector>
#include <algorithm>

using namespace std;

int main()
{
			// データの入力
	int n = 15;
	vector <int> v;
	for (int i1 = 0; i1 < n; i1++) {
		int x;
		cin >> x;
		v.push_back(x);
	}
			// ソート
	sort(v.begin(), v.end());
			// 余分なデータの削除
	vector<int>::iterator it;
	it  = v.begin();
	it += 5;
	while (v.size() > 10)
		it = v.erase(it);
			// 結果の出力
	for (it = v.begin(); it != v.end(); it++)
		cout << "  " << *it;
	cout << endl;
	int s = 0;
	for (int i1 = 0; i1 < 10; i1++)
		s += v[i1];
	cout << " 平均:" << s/10 << endl;

	return 0;
}
		
[問4] n 個( 10 個以上)の異なる整数データを set に読み込み,小さい方から 5 つのデータの平均値を出力するプログラムを書け.ただし,set に保存するデータ数は 5 以下とし,データの数が 5 を超えた場合は,入力されたデータを無視するか,または,一番最後のデータ(最も大きなデータ)を削除した後入力されたデータを set に追加するか,いずれかの方法を用いるものとする.
#include <iostream>
#include <set>

using namespace std;

int main()
{
			// データの入力
	int n = 15;
	set <int> s;
	for (int i1 = 0; i1 < 5; i1++) {
		int x;
		cin >> x;
		s.insert(x);
	}

	set<int>::iterator it;
	for (int i1 = 5; i1 < n; i1++) {
		int x;
		cin >> x;
		it = s.end();
		it--;
		if (x < *it) {
			s.erase(it);
			s.insert(x);
		}
	}
			// 結果の出力
	int m = 0;
	for (it = s.begin(); it != s.end(); it++)
		m += *it;
	cout << m/5 << endl;

	return 0;
}
		
[問5] n( 10 以上)人のテストの点数(全て異なる整数,キーとする)と名前( string )を map に保存し,上位 5 人の名前と点数を出力するプログラムを書け.
#include <iostream>
#include <map>

using namespace std;

int main()
{
			// データの入力
	int n = 10;
	map <int, string, greater<int>> m;
	for (int i1 = 0; i1 < n; i1++) {
		int x;
		string s;
		cin >> x >> s;
		m.insert(pair<int, string>(x, s));
	}
			// 結果の出力
	map <int, string, greater<int>>::iterator it = m.begin();
	int k = 0;
	while (k < 5) {
		cout << (*it).second << "  " << (*it).first << endl;
		it++;
		k++;
	}

	return 0;
}
		
[問6]上と同じ問題を,点数と名前をメンバー変数として持つクラスを使用して書け( set を利用).
#include <iostream>
#include <set>

using namespace std;
			// クラスの定義
class Test {
	public:
		int point;
		string name;
		Test(int p, string n) {
			point = p;
			name  = n;
		}
};
			// 演算子のオーバーロード
bool operator< (Test t1, Test t2)
{
	return (t1.point > t2.point) ? true : false;
}
			// 二項関数オブジェクト
			// 演算子のオーバーロードを使用する場合は必要ない
class GT
{
	public:
		bool operator() (Test t1, Test t2) const
		{
			return (t1.point > t2.point) ? true : false;
		}
};

int main()
{
			// データの入力
	int n = 10;
	set <Test> st;   // 演算子のオーバーロード
//	set <Test, GT> st;   // 二項関数オブジェクト
	for (int i1 = 0; i1 < n; i1++) {
		int x;
		string s;
		cin >> x >> s;
		Test ts(x, s);
		st.insert(ts);
	}
			// 結果の出力
	set <Test>::iterator it = st.begin();   // 演算子のオーバーロード
//	set <Test, GT>::iterator it = st.begin();   // 二項関数オブジェクト
	int k = 0;
	while (k < 5) {
		cout << (*it).name << "  " << (*it).point << endl;
		it++;
		k++;
	}

	return 0;
}
		

菅沼ホーム 演習解答例目次 本文目次 付録 索引