- トップページ
- 特集PC技術
- Java言語入門 ~C言語を学んだ君へ~
- [第18回]演習問題Ⅲ
Java言語入門 ~C言語を学んだ君へ~
[第18回]演習問題Ⅲ
この回がJava言語の最後になります。
学習したすべての内容を元に演習問題を解いてもらいます。
もしわからない場合には、前のページに戻り必要な情報を調べてください。調べるのも勉強の1つです。
演習問題 第1問
まず、可変長のint型配列を実現するMyVectorクラスを作成しなさい。
クラスとコンストラクタとメソッドは次の条件を満たしなさい。
クラス
クラス:public class MyVector
ファイル名:MyVector.java
継承:Objectクラス
コンストラクタ
コンストラクタ:public MyVector()
処理内容:メンバ変数の初期化。
容量(配列の長さ)を「10」に指定するなど。
引数:なし
メソッド
メソッド:public int size()
処理内容:要素数を返す。
引数:なし
戻り値:要素数
メソッド:public void add(int n, int index)
処理内容:指定位置に要素を挿入する。
容量がいっぱいなら、容量を10増して挿入する。
引数:n - 要素、index - 位置
戻り値:なし
例外:ArrayIndexOutOfBoundsException-(index < 0 || index > 要素数)の場合
メソッド:public void remove(int index)
処理内容:指定位置の要素を削除する。
指定位置以降の要素は左に移動する
引数:index - 位置
戻り値:なし
例外:ArrayIndexOutOfBoundsException-(index < 0 || index >= 要素数)の場合
メソッド:public int get(int index)
処理内容:指定位置の要素を返す。
引数:index - 位置
戻り値:要素
例外:ArrayIndexOutOfBoundsException-(index < 0 || index >= 要素数)の場合
メンバ変数
メンバ変数については「必要なもの」を定義してください。
アクセス修飾子はすべて「private」とします。
Ex18_01クラス
次にEx18_01クラスを作成して、以下の処理を行いなさい。
1. MyVectorクラスのオブジェクト「vector」を生成
2. vectorに「0~19」の20個の要素を追加する(addメソッドを使用)
3. vectorの0番目の要素を削除する(removeメソッドを使用)
4. vectorの0番目の要素をコンソールに出力する(getメソッドを使用)
5. vectorの要素数をコンソールに出力する(sizeメソッドを使用)
実行結果
実行結果は次のようになります。
第1問解答
MyVectorクラス
Ex18_01クラス
第1問解説
可変長の配列を作成する問題です。
通常、配列の大きさは変更できないため、このようなMyVectorクラスを使用すると、配列の長さを気にせずプログラムが書けます。
なお、可変長の配列を実装したクラスは基本APIにあります。
それは、「java.util.Vector」です。
興味があれば、調べてみてください。
少し前置きが長くなりましたが、以下にMyVectorクラスの解説をします。
MyVectorクラスの解説
2~3行目
メンバ変数の宣言
1つは配列arrayです。
そして、もう1つは要素の最後尾を保持する変数tailです。
つまり、「要素数」を保持します。
5~8行目
コンストラクタ
配列arrayの長さを10に、変数tailを0に初期化します。
11~21行目
addメソッド
まずは例外処理を行います。
続いて、配列が要素でいっぱいであるかを調べます。
もし要素がいっぱいなら、元の配列より10大きい配列を新たに作成し、元の配列の要素をすべてコピーします。
そして、arrayに新しい配列を参照させます。
これにより、可変長の配列が実現できます。
その後は、指定位置indexに変数nを追加します。
ただし、ただ代入するのではなく、「挿入」により要素を格納します。
データを追加したら、変数tailを1増やします。
24~28行目
removeメソッド
まずは例外処理を行います。
続いて、指定位置より後ろの要素を1つ分詰めて、要素を削除します。
削除したら、変数tailを1減らします。
31~34行目
getメソッド
まずは例外処理を行います。
続いて、指定位置の要素を返します。
37~39行目
sizeメソッド
要素数は変数tailが保持しているため、この変数の値を返します。
演習問題 第2問
まず、int型の要素の後入れ先出し(LIFO)を実現するMyStackクラスを作成しなさい。
LIFOとは、後から入れた要素から、先に取り出すことです。
そして、このようなデータ構造を「スタック」といいます。
クラスとメソッドは次の条件を満たしなさい。
クラス
クラス:public class MyStack extends MyVector
ファイル名:MyStack.java
継承:演習問題1で作成したMyVectorクラスを継承する
メソッド
メソッド:public void push(int n)
処理内容:スタックの先頭に要素を入れる
引数:n - 要素
戻り値:なし
メソッド:public int pop()
処理内容:スタックの先頭の要素を削除し、その要素を取り出す
引数:なし
戻り値:要素
コンストラクタ、メンバ変数
なお、コンストラクタとメンバ変数は、必要ならば記述しなさい。
特に指定はありません。
Ex18_02クラス
次にEx18_02クラスを作成して、以下の処理を行いなさい。
1. MyStackクラスのオブジェクト「stack」を生成
2. stackに「0~19」の20個の要素を追加する(pushメソッドを使用)
3. stackから要素を5個取り出し、コンソールに出力する(popメソッドを使用)
4. stackの要素数をコンソールに出力する(sizeメソッドを使用)
実行結果
実行結果は次のようになります。
第2問解答
MyStackクラス
Ex18_02クラス
第2問解説
スタック構造を作成する問題です。
1から作成するのは大変ですが、演習問題1で作成したMyVectorクラスを継承することで、容易に実現することができます。
以下にMyStackクラスの解説をします。
1行目
「extends」キーワードを使ってMyVectorクラスを継承します。
3~5行目
pushメソッドです。
これは、MyVectorクラスのaddメソッドを使います。
引数の指定位置を最後尾にすれば、良いだけです。
最後尾はsizeメソッドでわかります。
8~12行目
popメソッドです。
要素の取り出しはgetメソッドを使います。
ここで注意することは引数を(size() - 1)にすることです。
1減らすと、最後尾の要素位置になります。
要素を取り出した後は要素を削除します。
それには、removeメソッドを使います。
そして、一連の処理が終わったら、取り出した要素を返します。
演習問題 第3問
2つの入力ファイル(in1.txtとin2.txt)より、データを読み込み、一文ずつ交互に出力を行って、1つの出力ファイル(out.txt)を作成するプログラムを作りなさい。
ただし、作成にて条件があります。
それは、ファイルの入出力にはスレッドを使うことです。
つまり、2つのスレッドがそれぞれ、2つの入出力ファイルより、データを受け取り、同期により書き込みを制御し、一行ずつ交互に処理するようにしてください。
in1.txtのファイル内容
A
C
E
in2.txtのファイル内容
B
D
F
実行結果(out.txtのファイル内容)
out.txtファイルより、交互に出力されていることがわかると思います。
なお、作成方法は上記の条件を満たせば自由に作ってよい。
第3問解答
FileIOクラス
Ex18_03クラス
第3問解説
主に、ファイル入出力とマルチスレッドの理解度を確認する問題です。
内容はそれほど難しくありません。
また、この問題では、プログラムの作成方法に「マルチスレッドによる入出力を行うこと」以外の条件は指定していません。
つまり、条件を満たし、実行結果が正しく出力できれば、正解となります。
そのため、今回の答えはあくまで「一例」と考えてください。
では、次にプログラムの解説をします。
FileIOクラスの解説
まずは、FileIOクラスです。
このクラスは指定した入力ストリームから出力ストリームへ、1行ずつ書き込みを行います。
以下に詳しく解説します。
1行目
入出力クラスを使うため、インポートを行います。
3行目
Threadクラスを継承します。
これにより、スレッドによる処理が行えます。
4行目
このクラスで一つのみ存在するオブジェクトを作成します。
後で解説しますが、このオブジェクトを使って、「排他制御」を行います。
8~11行目
コンストラクタです。
入出力ストリームを受け取り、メンバ変数を初期化します。
13行目
runメソッドの開始です。
このメソッドより、スレッドが開始されるため、ここに入出力の処理を記述していきます。
14行目
入出力を行うには、例外処理が必要になります。
そのため、try~catchで例外を受け取ります。
15~21行目
入力と出力を繰り返し行います。
ただし、ここで「synchronized」を使います。
これは、排他制御をおこなうためのキーワードで、読み書きを同時に行うことを禁止しています。
そして、この排他制御を実現するためにオブジェクトobjを使います。
これは、このクラスに1つしか存在しないため、このクラスをいくつ作成しても、排他制御が行われます。
Ex18_03クラスの解説
続いて、Ex18_03クラスです。
このクラスはFileIOを使って、2つのファイルから1行ずつ読み込み1つのファイルに書き込みを行います。
以下に詳しく解説します。
1行目
ファイル入出力クラスを使うため、インポートします。
6~8行目
入出力ストリームを作成します。
入力ファイルは2つ作成し、出力ファイルは1つのみです。
10~11行目
クラスFileIOを作成します。
12~13行目
読み書きを開始します。
startメソッドより、スレッドが開始します。
15~16行目
二つのスレッドが終了するまで待ちます。
18~20行目
入出力ストリームを閉じます。
コメント
匿名
第3問の解答例ではうまくいきません。
synchronizedによる排他制御はスレッドの実行順序を規定しないため、
交互に書き込まれる保証はありません。
2018年4月15日 14:37
コメントの投稿
トラックバックURL
http://www.isl.ne.jp/cgi-bin/mt/mt-tb.cgi/1084