7 はじめてのCUIプログラム

7.1 学習目標

7.2 はじめてのCUIプログラム

7.2.1 CUIとは

【Character User Interface】

ユーザに対する情報の表示を文字によって行ない、すべての操作をキーボードを用いて行なうユーザインターフェースのこと。

ユーザから入力を受け取ることもできる。(IT用語辞典より)

7.2.2 タートルプログラムとの違い

今までは、プログラミング初心者のために用意された 「タートルライブラリ」 (2) というライブラリを使ってプログラミングをしてきました。

ライブラリとは、特定の機能を持ったプログラムを1つのファイルにまとめたものです。 ライブラリは単体で実行することはできず、他のプログラムの1部として動作します。

fd(100)やinput()やprint()などの命令は、「タートルライブラリ」というプログラムがなければ使えません。 (論プロエディタには、「タートルライブラリ」があらかじめ入っています)

これから学習するCUIプログラムでは、Java標準ライブラリという、Javaにはじめから入っている、 プロでも使っているライブラリを使ってプログラミングをします。

  1. 論プロエディタで使用しているタートルライブラリは、萩野先生が98年に作ったものをもとに、大岩研究室で機能追加を行ったものです。

7.2.3 情報の表示とユーザ入力の受け取り

次のプログラムはユーザから文字列の入力を受け取り、おうむ返しするプログラムです。

リスト 7.2.3.1 InputAndPrint.java
  1: import java.util.*;
  2: 
  3: /**
  4: * プログラム名: おうむ返しのプログラム
  5: * 作成者: Yoshiaki Matsuzawa
  6: * 作成日: 2007/09/22
  7: */
  8: public class InputAndPrint{
  9: 	
 10: 	//起動処理
 11: 	public static void main(String[] args) {
 12: 		InputAndPrint main = new InputAndPrint();
 13: 		main.run();
 14: 	}
 15: 	
 16: 	//おうむ返しをする
 17: 	public void run() {
 18: 		//前処理
 19: 		Scanner scanner = new Scanner(System.in);//入力を受け取るためのスキャナ
 20: 		
 21: 		//入力を受けとる
 22: 		System.out.print("好きな文字を入力>>");
 23: 		String text = scanner.nextLine();
 24: 		
 25: 		//出力を行う
 26: 		String reply = "あなたの入力したのは" + text + "ですね";
 27: 		System.out.println(reply);
 28: 	}
 29: 	
 30: }

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

7.2.4 Java標準ライブラリ

7.2.4.1 インポート

importとは、名前空間を取り込む命令です。 import文を書くと、別パッケージの中にあるクラス名をフルネームで指定しなくてすむようなります。 Java標準ライブラリの機能である「java.util.Scanner」をパッケージ名(java.util)なしで使うために、 このプログラムでは1行目でライブラリをインポートしています。

System.outは、Java標準ライブラリ(rt.jar)の中の「java.lang」というパッケージに入っていますが、 これはJavaの仕様により自動でインポートされるので、import文を書かなくても使えます。

(論プロエディタでは、タートルライブラリ(blib.jar)をコンパイル時にクラスパスに追加することで、 インポート文を書かなくても使えるようにしてありました。)

import java.util.*;

7.2.4.2 入力を受け付ける命令

Java標準ライブラリの「Scanner」を使って、ユーザからの入力を受け付けることができます。 タートルプログラムでは、input()命令を使っていました。

19:	Scanner scanner = new Scanner(System.in);//入力を受け取るためのスキャナを作る
23:	String text = scanner.nextLine();//スキャナを使って文字を読み込む
					

スキャナーは、文字以外にも、整数や浮動小数点数などを読み込むことができます。 これらについては、あとで説明します。

int number = scanner.nextInt();//スキャナを使って整数を読み込む
double number = scanner.nextDouble();//スキャナを使って浮動小数点数を読み込む
					

7.2.4.3 コンソールに出力する命令

Java標準ライブラリの「System.out」を使って、コンソールに文字を出力することができます。 タートルプログラムでは、print()命令を使っていました。

22:	System.out.print("好きな文字を入力>>");//改行なしで""内の文字を出力する
27:	System.out.println(reply);//改行ありで()内の文字(文字列型の変数の中身)を出力する
					

7.2.5 変数の型-文字列型

変数には、今までタートルプログラムでも使ってきたint(整数)型のほかに、 String(文字列)型や、double(浮動小数点数)型があります。

おうむ返しプログラムでは、ユーザから入力された文字を保存しておくために、 String(文字列)型の変数を用意しています。

また、「あなたの入力したのは」と、「text(入力された文字列)」と、 「ですね」を+記号で連結し、 まとめて「reply」という文字列型の変数に入れて、出力しています。

7.3 入力、処理、出力

7.3.1 西暦和暦変換プログラム

次のプログラムは、西暦を入力すると、変換処理を行い、和暦を出力するプログラムです。

リスト 7.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: }

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

7.3.2 変数の型-整数型

このプログラムでは、西暦(整数型)を読み込んで、 西暦和暦変換処理を行い、和暦(文字列型)にして出力しています。 整数を読み込む命令は以下のとおりです。

16:	Scanner scanner = new Scanner(System.in);//入力を受け取るためのスキャナを作る
29:	year = scanner.nextInt();//スキャナを使って整数を読み込む
				

整数は文字列と連結し、文字列として保存することができます。 このプログラムでは、西暦を和暦に変換するときに、 年号(文字列型)と、年(整数型)を連結し、文字列型として出力しています。

35:	japaneseYear = "昭和" + (year - 1925);
やってみよう!

合計金額を人数で割った数を表示する「割り勘計算機」を作りましょう。

まず「合計金額を入力してください>>」と表示し、合計金額の入力を受け取り、

次に「飲み会参加人数を入力してください>>」と表示し、人数の入力を受け取り、

最後に「ひとりあたりの金額は●●円です」と表示しましょう。

結果は、整数(小数点以下切捨て)で出すようにしてください。

(すべての変数を整数型にして実装すると、Javaの仕様により、計算結果の小数点以下は切り捨てられます。「キャスト」の項で説明してあります)

7.4 変数の型とキャスト

7.4.1 平均得点計算プログラム

次のプログラムは3教科の平均を計算し、小数点1位を四捨五入して平均点を出力するプログラムです。

リスト 7.4.1.1 ScoreAverage.java
  1: import java.util.*;
  2: 
  3: /**
  4: * プログラム名:成績平均計算プログラム
  5: * 作成者: Megumi Araki
  6: * 作成日: Sat Oct 20 15:11:37 JST 2007
  7: */
  8: public class ScoreAverage{
  9: 	
 10: 	//起動処理
 11: 	public static void main(String[] args) {
 12: 		ScoreAverage main = new ScoreAverage();
 13: 		main.run();
 14: 	}
 15: 	
 16: 	//メイン処理
 17: 	public void run() {
 18: 		
 19: 		//各教科の点数を設定する
 20: 		int japanese = 49; //国語
 21: 		int mathematics = 72; //数学
 22: 		int english = 25; //英語
 23: 		
 24: 		//3教科の合計点を求める
 25: 		double total = japanese + mathematics  + english;
 26: 		//3教科の平均を求める
 27: 		double average = total / 3.0; //平均を計算する
 28: 		
 29: 		//平均を四捨五入する
 30: 		average = average * 10;
 31: 		if ((average % 10) >= 5) { //1の位が5以上なら
 32: 			average = average + 10; //繰り上げる
 33: 		}
 34: 		int result = (int) (average / 10);//double型のaverageをint型に型変換して、resultに代入する
 35: 		
 36: 		//四捨五入した平均を表示する
 37: 		System.out.println(result);
 38: 		
 39: 	}
 40: 	
 41: }

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

7.4.2 変数の型-浮動小数点数型

このプログラムでは、浮動小数点数(double)を扱っています。

浮動小数点数には誤差があります。 これは、コンピュータは2進法で計算をしており、 普段わたしたちが使っている10進法とは違うためです。

やってみよう!

0.1を10回足すプログラムを作り、結果を表示しましょう。

やってみよう!

0.125を8回足すプログラムを作り、結果を表示しましょう。

考えてみよう

なぜ上記2つの結果が違うのか、考えてみましょう。

7.4.3 キャスト(型変換)

通常、整数型に浮動小数点数型を代入するなど、値を型の違う変数を代入することはできません。 (浮動小数点数型の変数に整数を代入するなど、Javaで認められているものは、特別な処理をしなくても自動で型変換が行われ、代入ができる)

このような場合、プログラマが明示的に「キャスト(型変換)」を行う必要があります。キャストの命令は、以下のように書きます。

(変換したい型)変換元の変数;

今回のプログラムでは、以下のようにしてdouble型の変数をint型にキャストして、int型の変数に代入しています。

34:	int result = (int) (average / 10);

Javaでは、double型をint型にキャストすると、小数点以下は切り捨てられます。 この仕様を利用して、四捨五入のプログラムは以下のように書くこともできます。

//平均を四捨五入する
average = average+0.5;
int result = (int) (average);
				

7.5 CUIプログラムの作り方

7.5.1 クラス(ファイル)の作り方

論プロエディタのクラス(ファイル)作成画面のテンプレートの中から「CUI」を選んでください。 このテンプレートにはあらかじめimport文と、起動処理が書かれています。

7.5.2 新しい命令-変数の型と変数宣言

変数には整数(int)型、文字列型(String)、浮動小数点型(double)などがあります。

文字列や浮動小数点数を変数に保存したい場合は、以下のように書きます。

それぞれの型の変数宣言と代入文の例
int x=0;
整数型の変数xを作り、0を代入しています。
double y=0.01;
浮動小数点数方の変数yを作り、0.01を代入しています。
String text="hello";
文字列型の変数textを作り、「hello」という文字列を代入しています。

7.5.3 新しい命令-Java標準ライブラリを使った命令

7.5.3.1 標準出力に文字を出力する命令

System.out.println("hello")
"と"でかこまれた文字(例ではhello)を、標準出力(コンソール)に出力します。

7.5.3.2 ユーザから入力を受け取る命令

Scanner scanner = new Scanner(System.in);
文字を受け取るための「スキャナー」を生成します(下の3つの命令を使うためには、必ず、下の3つの命令の前にこの命令を書いておく必要がある)
int x = scanner.nextInt()
整数の入力を受け取り、その値をxという変数に保存します。
double y = scanner.nextDouble()
浮動小数点数の入力を受け取り、その値をyという変数に保存します。
String text = scanner.nextLine()
文字列の入力を受け取り、その値をtextという変数に保存します。

7.6 練習問題

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

7.6.1.1 概要

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

7.6.1.2 機能

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

7.6.1.3 エラー処理

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

7.6.1.4 プログラム設計条件

  1. 入出力は起動したコンソールから行う.(CUIプログラムである)
  2. 身長と体重の入力にはscanner.nextDouble()を使用すること。

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

7.6.2.1 概要

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

7.6.2.2 機能

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

7.6.2.3 エラー処理

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

7.6.2.4 プログラム設計条件

  1. 入出力は起動したコンソールから行う.(CUIプログラムである)
  2. 男女の名前の入力にはscanner.nextLine()を使用すること。
文字列からハッシュコード(整数)を求める命令

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

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

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

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

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

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

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

7.6.3.1 概要

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

7.6.3.2 機能

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

7.6.3.3 エラー処理

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

7.6.3.4 プログラム設計条件

  1. 入出力は起動したコンソールから行う.(CUIプログラムである)
  2. 単位数の入力にはscanner.nextInt()を使用すること。

7.7 発展問題

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

7.7.1.1 概要

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

7.7.1.2 機能

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

7.7.1.3 エラー処理

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

7.7.1.4 プログラム設計条件

  1. 入出力は起動したコンソールから行う.(CUIプログラムである)
  2. 入力はscanner.nextInt()を利用すること.

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

7.7.2.1 概要

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

7.7.2.2 機能

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

7.7.2.3 エラー処理

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

7.7.2.4 プログラム設計条件

  1. 入出力は起動したコンソールから行う.(CUIプログラムである)
  2. 入力はscanner.nextInt()を利用すること.

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

7.7.3.1 概要

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

7.7.3.2 機能

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

7.7.3.3 エラー処理

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

7.7.3.4 プログラム設計条件

  1. 入出力は起動したコンソールから行う.(CUIプログラムである)
  2. 入力はscanner.nextInt()を利用すること.
乱数を求める命令

Java標準ライブラリを用いた、乱数を求める命令は以下のとおりです。

(タートルライブラリのrandom([数])命令とは、返ってくる値が違います。この命令では、0以上、1より小さい小数がかえってきます)

//乱数を発生させ、numberという変数に保存する
double number=Math.random();

//乱数の出力を行う
System.out.println( "今回の乱数は" + number + "ですね");