13 プログラムの部品化(2)(戻り値)

13.1 学習目標

13.2 入力・処理・出力

累乗計算プログラムを例に、プログラムとメソッドの入力・処理・出力について学びます。

13.2.1 プログラムの入出力

13.2.1.1 累乗計算プログラムの入出力

次のプログラムは、ユーザから底と指数の入力を受け取り、累乗を計算するプログラムです。

リスト 13.2.1.1.1 Power.java
  1: import java.util.*;
  2: 
  3: /**
  4: * プログラム名:累乗計算プログラム
  5: * 作成者: MegumiAraki
  6: * 作成日: Tue Dec 04 12:28:06 JST 2007
  7: */
  8: public class Power{
  9: 	
 10: 	//起動処理
 11: 	public static void main(String[] args) {
 12: 		Power main = new Power();
 13: 		main.run();
 14: 	}
 15: 	
 16: 	//メイン処理
 17: 	public void run() {
 18: 		System.out.println("累乗計算プログラムを開始します");//アプリケーションの開始を知らせる
 19: 		
 20: 		Scanner scanner =new Scanner(System.in);//入力を受け付けるスキャナーを作る
 21: 		
 22: 		//底の入力を受け付ける
 23: 		System.out.println("底を入力してください>>");
 24: 		int base=scanner.nextInt();
 25: 
 26: 		//指数の入力を受け付ける
 27: 		System.out.println("指数を入力してください>>");
 28: 		int exponent=scanner.nextInt();
 29: 
 30: 		//累乗数を計算し、計算結果をcalculatedPowerという変数に書き込む
 31: 		int calculatedPower=calculatePower(base,exponent);
 32: 
 33: 		//累乗数を出力する
 34: 		System.out.println(base+"の"+exponent+"乗は"+calculatedPower+"です。");
 35: 		
 36: 		System.out.println("累乗計算プログラムを終了します");//アプリケーションの終了を知らせる
 37: 	}
 38: 	
 39: 	//累乗を計算する
 40: 	int calculatePower(int base, int exponent){
 41: 		int power=1;//累乗数の初期値を、数の0乗(1)に設定する
 42: 
 43: 		//累乗を計算する
 44: 		int i=0;
 45: 		while(i<exponent){
 46: 			power=power*base;
 47: 			i++;
 48: 		}
 49: 
 50: 		return power;
 51: 	}
 52: 	
 53: }

下のボタンを押すと、このプログラムが実行できます。 ここをクリックすると、プログラムをダウンロードできます。

このプログラムの入力・処理・出力を図に表すと以下のようになります。

矢印はデータの流れを、四角は処理を示します。

図 13.2.1.1.1 累乗計算メソッドの入出力

13.2.1.2 一般的なプログラムの入出力

プログラムは一般的に、入力・処理・出力の構造を持っています。

たとえば、7章「はじめてのCUIプログラム」の、BMI値算出プログラムの入力・処理・出力を図に表すと以下のようになります。

図 13.2.1.2.1 累乗計算メソッドの入出力
やってみよう!

7章の練習問題それぞれについて、入力・処理・出力を表す図を描いてみましょう。

13.2.2 メソッドの入出力

13.2.2.1 累乗を計算するメソッドの入出力

累乗を計算するメソッドは、int(整数)型の値を返す、戻り値ありメソッドです。 引数として底・指数を受け取り、累乗数を返しています。

						
 29: 		//累乗数を計算し、計算結果をcalculatedPowerという変数に書き込む
 30: 		int calculatedPower=calculatePower(base,exponent);

					
						
 38: 	//累乗を計算する
 39: 	int calculatePower(int base, int exponent){
 40: 		int power=1;//累乗数の初期値を、数の0乗(1)に設定する
 41: 
 42: 		//累乗を計算する
 43: 		int i=0;
 44: 		while(i<exponent){
 45: 			power=power*base;
 46: 			i++;
 47: 		}
 48: 
 49: 		return power;
 50: 	}

					

メソッドも、プログラムと同様に入力・処理・出力の構造を持っています。

このメソッドの入力・処理・出力を図に表すと、以下のようになります。

図 13.2.2.1.1 累乗計算メソッドの入出力

13.2.2.2 一般的なメソッドの入出力

戻り値とは

前の章「プログラムの部品化(1)」では、メソッドと、引数について学びました。 引数は、メソッドブロック外から渡される値= 入力 でした。

引数は、呼び出し元のメソッドから呼び出したメソッドに、データを受け渡したいという要求をかなえる仕組みでした。 逆に、呼び出されたメソッドが処理した結果を呼び出し元に受け渡したい、という場合もあります。 これをかなえる仕組みが、戻り値です。

戻り値は、呼び出し元に戻す値= 出力 です。

図 .1 メソッドの入出力
このように、メソッドも、入力・処理・出力の構造を作ることができます。 引数は、複数指定することができますが、戻り値は必ずひとつです。

戻り値ありメソッドの定義と呼び出し

戻り値ありメソッドの定義の仕方は、以下の通りです。

戻り値ありメソッドでは、return文を書いたところでメソッドの出力は決まり、メソッドの処理を抜けます。 したがって、return文の後に命令を書いても、実行されることはありません。(「この文に制御が移ることはありません」というエラーが出ます)

							
[戻り値の型] [メソッド名]([引数の型] [仮引数名]){
	return [戻り値];
}
						

戻り値ありメソッドの呼び出し方は、以下の通りです。(引数ありメソッドと同じです)

							
[メソッド名]([実引数]);

						
やってみよう!

税抜価格を引数とし、税込価格を戻り値とするメソッド【int calculateTaxIn(int price)】を作り、 税抜価格を入力すると、「税抜価格○○円の品物の税込価格は○○円です」と出力するプログラムを作りましょう。

整数に小数をかけると、浮動小数点数型になります。戻り値はint型なので、int型に キャスト してください。 int型にキャストすると、小数点以下は切り捨てられます。 (例:int taxInPrice=(int)(price*1.05))

(一般の事業者の場合、消費税の計算は切捨て、四捨五入、 切り上げのいずれかを事業者自身が選択してよいことになっています。 切捨て、もしくは四捨五入をするところが多いようです。この問題では、 消費税の小数点以下は切り捨てるものとして扱ってください。)

13.3 入出力を持つメソッドを用いたプログラムの構造化

西暦和暦変換プログラムを例に、 プログラムの部品化と戻り値について学びます。 西暦和暦変換プログラムは、西暦を入力として受け取り、和暦を出力するプログラムです。 西暦和暦変換プログラムの入力・処理・出力を表す図は以下の通りです。

図 13.3.1 西暦和暦変換プログラムの入出力

西暦和暦変換プログラムの中には、さらに入力・処理・出力の構造が入っています。 以下の図は、西暦和暦変換プログラムの入力・処理・出力の階層構造を表す図です。

図 13.3.2 西暦和暦変換プログラムの入出力

西暦和暦変換プログラムの全体構造は、以下のようになっています。

「西暦を和暦に変換する」という処理は、「アプリケーションの開始を知らせる」 「西暦を和暦に変換する」「アプリケーションの終了を知らせる」という1レベル下の処理から成り立っています。

「西暦を和暦に変換する」という処理は、さらに1レベル下の、 「西暦を入力する」「西暦を和暦に変換する」「変換結果を出力する」という処理から成り立っています。

図 13.3.3 西暦和暦変換プログラムの構造

13.3.1 西暦和暦変換プログラム(メソッドなし)

次のプログラムは西暦を和暦に変換するプログラムです。 このプログラムでは、メソッドを使っていません。

リスト 13.3.1.1 ConvertYearApplication1.java
  1: import java.util.*;
  2: 
  3: /**
  4:  * 西暦和暦変換プログラム(メソッドなし)
  5:  * 
  6:  * @author オブプロ例題
  7:  * @version 1.0
  8:  */
  9: public class ConvertYearApplication1 {
 10: 
 11: 	public static void main(String[] args) {
 12: 		ConvertYearApplication1 main = new ConvertYearApplication1();
 13: 		main.run();
 14: 	}
 15: 
 16: 	Scanner scanner = new Scanner(System.in);
 17: 
 18: 	// 西暦を和暦に変換する
 19: 	public void run() {
 20: 		// アプリケーションの開始を知らせる
 21: 		System.out.println("西暦和暦変換プログラムを開始します");
 22: 
 23: 		{// 西暦を和暦に変換する
 24: 			int year;
 25: 			String japaneseYear;
 26: 
 27: 			// 西暦を入力する
 28: 			System.out.println("西暦を入力してください");
 29: 			year = scanner.nextInt();
 30: 
 31: 			// 西暦を和暦に変換する
 32: 			if (year >= 1989) {
 33: 				japaneseYear = "平成" + (year - 1988);
 34: 			} else if (year >= 1926) {
 35: 				japaneseYear = "昭和" + (year - 1925);
 36: 			} else {
 37: 				japaneseYear = "不明";
 38: 			}
 39: 
 40: 			// 変換結果を出力する
 41: 			System.out.println(year + "年は" + japaneseYear + "年です.");
 42: 		}
 43: 
 44: 		// アプリケーションの終了を知らせる
 45: 		System.out.println("西暦和暦変換プログラムを終了します");
 46: 	}
 47: }

下のボタンを押すと、このプログラムが実行できます。 ここをクリックすると、プログラムをダウンロードできます。

13.3.2 西暦和暦変換プログラム(1レベルをメソッド化)

次のプログラムでは、1レベルをメソッド化しています。

リスト 13.3.2.1 ConvertYearApplication2.java
  1: import java.util.*;
  2: 
  3: /**
  4:  * 西暦和暦変換プログラム(1レベルをメソッド化)
  5:  * 
  6:  * @author オブプロ例題
  7:  * @version 2.0
  8:  */
  9: public class ConvertYearApplication2 {
 10: 
 11: 	public static void main(String[] args) {
 12: 		ConvertYearApplication2 main = new ConvertYearApplication2();
 13: 		main.run();
 14: 	}
 15: 
 16: 	Scanner scanner = new Scanner(System.in);
 17: 
 18: 	// 西暦を和暦に変換する
 19: 	public void run() {
 20: 		showTitle();
 21: 		convertYear();
 22: 		showEndTitle();
 23: 	}
 24: 
 25: 	// 西暦を和暦に変換する
 26: 	void convertYear() {
 27: 
 28: 		int year;
 29: 		String japaneseYear;
 30: 
 31: 		// 西暦を入力する
 32: 		System.out.println("西暦を入力してください");
 33: 		year = scanner.nextInt();
 34: 
 35: 		// 西暦を和暦に変換する
 36: 		if (year >= 1989) {
 37: 			japaneseYear = "平成" + (year - 1988);
 38: 		} else if (year >= 1926) {
 39: 			japaneseYear = "昭和" + (year - 1925);
 40: 		} else {
 41: 			japaneseYear = "不明";
 42: 		}
 43: 
 44: 		// 変換結果を出力する
 45: 		System.out.println(year + "年は" + japaneseYear + "年です.");
 46: 	}
 47: 
 48: 	// アプリケーションの開始を知らせる
 49: 	void showTitle() {
 50: 		System.out.println("西暦和暦変換プログラムを開始します");
 51: 	}
 52: 
 53: 	// アプリケーションの終了を知らせる
 54: 	void showEndTitle() {
 55: 		System.out.println("西暦和暦変換プログラムを終了します");
 56: 	}
 57: 
 58: }

下のボタンを押すと、このプログラムが実行できます。 ここをクリックすると、プログラムをダウンロードできます。

13.3.3 西暦和暦変換プログラム(2レベルをメソッド化)

次のプログラムでは、2レベルをメソッド化しています。

リスト 13.3.3.1 ConvertYearApplication3.java
  1: import java.util.*;
  2: 
  3: /**
  4:  * 西暦和暦変換プログラム(2レベルをメソッド化)
  5:  * 
  6:  * @author オブプロ例題
  7:  * @version 3.0
  8:  */
  9: public class ConvertYearApplication3 {
 10: 
 11: 	public static void main(String[] args) {
 12: 		ConvertYearApplication3 main = new ConvertYearApplication3();
 13: 		main.run();
 14: 	}
 15: 
 16: 	Scanner scanner = new Scanner(System.in);
 17: 
 18: 	// 西暦を和暦に変換する
 19: 	public void run() {
 20: 		showTitle();
 21: 		convertYear();
 22: 		showEndTitle();
 23: 	}
 24: 
 25: 	// 西暦を和暦に変換する
 26: 	void convertYear() {
 27: 		int year;
 28: 		String japaneseYear;
 29: 
 30: 		year = inputYear();
 31: 		japaneseYear = convertToJapaneseYear(year);
 32: 		showResult(year, japaneseYear);
 33: 	}
 34: 
 35: 	// 西暦を入力する
 36: 	int inputYear() {
 37: 		int year;
 38: 		System.out.println("西暦を入力してください");
 39: 		year = scanner.nextInt();
 40: 		return year;
 41: 	}
 42: 
 43: 	// 西暦を和暦に変換する
 44: 	String convertToJapaneseYear(int year) {
 45: 		String japaneseYear;
 46: 		if (year >= 1989) {
 47: 			japaneseYear = "平成" + (year - 1988);
 48: 		} else if (year >= 1926) {
 49: 			japaneseYear = "昭和" + (year - 1925);
 50: 		} else {
 51: 			japaneseYear = "不明";
 52: 		}
 53: 		return japaneseYear;
 54: 	}
 55: 
 56: 	// 変換結果を出力する
 57: 	void showResult(int year, String japaneseYear) {
 58: 		System.out.println(year + "年は" + japaneseYear + "年です.");
 59: 	}
 60: 
 61: 	// アプリケーションの開始を知らせる
 62: 	void showTitle() {
 63: 		System.out.println("西暦和暦変換プログラムを開始します");
 64: 	}
 65: 
 66: 	// アプリケーションの終了を知らせる
 67: 	void showEndTitle() {
 68: 		System.out.println("西暦和暦変換プログラムを終了します");
 69: 	}
 70: 
 71: }

下のボタンを押すと、このプログラムが実行できます。 ここをクリックすると、プログラムをダウンロードできます。

13.4 練習問題

「はじめてのCUIプログラム」で作ったCUIプログラムを、メソッドを使って書き直しましょう。

仕様は以下を参考にしてください。

(メソッドの作り方に関する指示が追加されています)

13.4.1 問題1:体型評価プログラムを作ろう

13.4.1.1 概要

このプログラムは,身長と体重の入力を実数で受け付ける. その入力をもとにBMI指数と,その値から評価されたコメントを出力する.

13.4.1.2 機能

  1. プログラムの起動時および終了時に、その旨をユーザに伝えるメッセージを出力する(起動時出力:「開始しました」(適宜変えてよい)  終了時出力:「終了しました」(適宜変えてよい))
  2. 身長と体重の入力を受け取り,BMI指数と,その値から評価されたコメントを出力する入力:体重(kg)と身長(cm)の実数値。出力:BMI指数(小数点1桁で四捨五入することが望ましい,およびコメント)

13.4.1.3 エラー処理

文字など処理不可能な値が入力されたときの処理は,行わなくてよい.

13.4.1.4 プログラム設計条件

  1. 入出力は起動したコンソールから行う.(CUIプログラムである)
  2. 身長と体重の入力はscanner.nextDouble()を利用すること.
  3. 必ず次の入出力(身長と体重を入力とし、小数型のBMI値を出力とする)を持つメソッドを作ること.【double calculateBMI(double height, double weight)】
  4. 上記以外の部分のメソッド化はプログラマに一任する.

13.4.2 問題2:恋愛占いプログラムを作ろう

13.4.2.1 概要

このプログラムは,男女の名前を入力すると, その恋愛成就確率(?)を百分率で判定し,コメント付で出力する.

13.4.2.2 機能

  1. プログラムの起動時および終了時に、その旨をユーザに伝えるメッセージを出力する(起動時出力:「開始しました」(適宜変えてよい)  終了時出力:「終了しました」(適宜変えてよい))
  2. 男女の名前の入力を受け取り,恋愛成就確率をコメント付で出力する.(入力:男女の名前(姓名をつなげたもの)の入力,出力:恋愛成就確率(0-100%実数でも整数でも可),コメント)

13.4.2.3 エラー処理

処理不可能な値が入力されたときの処理は,行わなくてよい.

13.4.2.4 プログラム設計条件

  1. 入出力は起動したコンソールから行う.(CUIプログラムである)
  2. 入力はscaner.nextLine()を利用すること.
  3. 必ず次の入出力(女性の名前を整数に変換したものと、男性の名前を整数に変換したものを入力とし、小数型の恋愛成就率を出力とする)を持つメソッドを作ること.【double calculateAishou(int girlsNameNumber,int boysNameNumber)】
  4. 上記以外の部分のメソッド化はプログラマに一任する.
文字列からハッシュコード(整数)を求める命令

入力された文字列からハッシュコード (4) を求めるには、hashCode()命令を使います。

以下のプログラムを参考にしてください。

						
//文字の入力を受けとる System.out.print("文字を入力>>"); String
text = scanner.nextLine();

//入力された文字をハッシュコード(整数)に変換し、その値をnumberという変数に保存する
int number=text.hashCode();

//ハッシュコードの出力を行う
System.out.println("あなたの入力した文字のハッシュコードは" +
number + "ですね");

					
実装のヒント

ハッシュコードは正負の非常に大きな値を取ります。これを100までの整数にして、 百分率表示に使うためには、「負の数だったら(-1)をかけて、正の数にする」 「数が100より大きい間、数を10で割り続ける」といった方法が使えます。

  1. ハッシュコードとは、ハッシュ関数という、特定のデータを固定長のデータに変換する関数によって求められた値のことです。同じデータからは同じハッシュコードが生成されます。ハッシュコードは、情報セキュリティを高めるための技術として、パスワードの保管やデータの改ざんの検出などに使われています。今回、このプログラムでは相性判断のために、文字列を数値に変換するための手段としてハッシュコードを使いましたが、これはハッシュコードの本来の使い方ではありません。

13.4.3 問題3:単位取得状況評価プログラムを作ろう

13.4.3.1 概要

このプログラムは,SFC生の単位取得の状況の入力を受け取り, それを評価し,卒業するためのコメントを出力する.

13.4.3.2 機能

  1. プログラムの起動時および終了時に、その旨をユーザに伝えるメッセージを出力する(起動時出力:「開始しました」(適宜変えてよい)  終了時出力:「終了しました」(適宜変えてよい))
  2. 経過した学期数と現在取得した単位数の入力を受け取り,その値から評価されたコメントを出力する.(入力:経過した学期数(0-20)の整数値,取得済みの単位数、出力:今後1学期あたりにとらねばならない単位数(CPS:Credit Per Semester),およびコメント)

13.4.3.3 エラー処理

文字など処理不可能な値が入力されたときの処理は,行わなくてよい.

13.4.3.4 プログラム設計条件

  1. 入出力は起動したコンソールから行う.(CUIプログラムである)
  2. 入力はscanner.nextInt()を利用すること.
  3. 必ず次の入出力(経過した学期数と取得した単位数を入力とし、小数型の「今後1学期あたりに取らなければならない単位数」を出力とする)を持つメソッドを作ること.【double calculateCPS(int passedSemesterCount,int earnedCredits)】
  4. 上記以外の部分のメソッド化はプログラマに一任する.

13.5 発展問題

13.5.1 問題1:脳トレ 論プロ風

13.5.1.1 概要

ユーザが計算問題を解くことで脳を鍛えるソフトウエアである. このプログラムは,足し算の計算問題を自動生成して,何問か出題し,そのつど答えあわせをする.

13.5.1.2 機能

  1. プログラムの起動時,および終了時にその旨をユーザに知らせるメッセージを出力する.  起動時出力:「開始しました.」(適宜変えてよい)  終了時出力:「終了しました.」(適宜変えてよい)
  2. 足し算の計算問題を生成する.出力:問題 (3 + 4 = ?)  各数字の桁数は一桁の整数である(答えは任意の桁数の整数とする)
  3. 出題し,答えあわせをする.入力:回答出力:答えあわせの結果(正解or不正解(正答を添える))
  4. 2),3)を連続で10回行い,最後に正答率を出力する.

13.5.1.3 エラー処理

処理不可能な値が入力されたときの処理は,行わなくてよい.

13.5.1.4 プログラム設計条件

  1. 入出力は起動したコンソールから行う.(CUIプログラムである)
  2. 入力はscanner.nextInt()を利用すること.
  3. メソッドを作る場所は自由であるが,引数,戻り値の双方を持つメソッドを一つ以上含むこと.
  4. 上記以外の部分のメソッド化はプログラマに一任する.

13.5.2 問題2:マイホーム大作戦

13.5.2.1 概要

マイホームローンの返済計算を行うプログラムである.ユーザは家を買うときに利用することを想定する. システムは,家の値段と利率,月々の返済金額を入力として受け取り, 返済が終わるまでにかかる期間を計算し,コメントとともに出力する.

13.5.2.2 機能

  1. プログラムの起動時および終了時に、その旨をユーザに伝えるメッセージを出力する(起動時出力:「開始しました」(適宜変えてよい)  終了時出力:「終了しました」(適宜変えてよい))
  2. 家の値段とローン年数,利率,月々の返済金額を入力として受け取り,月々の返済金額を計算して出力する.入力:家の値段(整数:万円単位だと使いやすい),利率(百分率の実数),月々の返済金額(整数) 出力:かかる期間(○年),総返済金額,コメント

13.5.2.3 エラー処理

処理不可能な値が入力されたときの処理は,行わなくてよい.

13.5.2.4 プログラム設計条件

  1. 入出力は起動したコンソールから行う.(CUIプログラムである)
  2. 入力はscanner.nextInt()を利用すること.
  3. メソッドを作る場所は自由であるが,引数,戻り値の双方を持つメソッドを一つ以上含むこと.
  4. 上記以外の部分のメソッド化はプログラマに一任する.

13.5.3 問題3:ザ・バイナリサーチ

13.5.3.1 概要

「数あてゲーム」である.システムはまず,1-1000までの整数をランダムに選ぶ(表示しない). ユーザはこの数をなるべく少ない回答で当てるのが目的である.ユーザは推測した数を入力し, システムは当っていたら,あたったことをユーザに知らせて終了, 外れていたら,大きすぎるのか,小さすぎるのかをユーザに知らせて再入力を求める.

13.5.3.2 機能

  1. プログラムの起動時,および終了時にその旨をユーザに知らせるメッセージを出力する.起動時出力:「開始しました.」(適宜変えてよい) 終了時出力:「終了しました.」(適宜変えてよい)
  2. 整数をランダムに選ぶ.出力:問題の正解 (1-1000までのランダムな整数)
  3. 整数をランダムに選ぶ.出力:問題の正解 (1-1000までのランダムな整数)
  4. 回答の入力を受けつけ,答えあわせをする.プロンプト:「私が選んだ数を当ててみてね.」入力:回答(整数)正解時出力:「正解です.おめでとう!」と出力して終了.(4の処理を行う)不正解時出力:「ちがいます.」の後,大きすぎるか,小さすぎるかを出力する.

13.5.3.3 エラー処理

処理不可能な値が入力されたときの処理は,行わなくてよい.

13.5.3.4 プログラム設計条件

  1. 入出力は起動したコンソールから行う.(CUIプログラムである)
  2. 入力はscanner.nextInt()を利用すること.
  3. メソッドを作る場所は自由であるが,引数,戻り値の双方を持つメソッドを一つ以上含むこと.
  4. 上記以外の部分のメソッド化はプログラマに一任する.