よく利用するアプリケーションは、Dockに登録しておきますと、次回からはワンクリックで起動できるようになります。 登録したいアプリケーションのアイコンを、Dockの適当な位置(縦線の左側)にドラッグ・アンド・ドロップしてください。 ただし、「ターミナル」を起動する"Shift_JIS.term"アイコンについては、Dockの縦線の右側に登録します。
「ターミナル」でコマンドを入力するとき、途中でtabキーを押しますと、自動的に残りの部分が入力されます。 ただし、残りの部分に複数の候補がある場合は、自動入力されるのはその共通部分のみです。 また、上矢印キーを押しますと、直前に入力したコマンドが現れ、下矢印キーを押しますと、直後に入力したコマンドが現れます。
この授業の内容は、Javaのプログラムを作成することです。 そもそも、プログラムとは何でしょうか。 ここでは、次のように用語を定めます。
アルゴリズムの説明で、問題解決と言われても、ピンと来ないかもしれません。 例として、次の問題を考えます。
与えられた文字列が回文か否かを判定せよ。 ここで回文とは、「たけやぶやけた」のように、左から読んでも右から読んでも同じになる文字列のことである。
この問題は、次のような方法で解決できます。
今、「いるかはまるい」という文字列が与えられたとします。 s1 は「いるかはまるい」に、 s2 は「いるまはかるい」になります。 左から一文字ずつ比較しますと、3文字目で違いが見つかりますので、"No"と答えます。 一方、「たけやぶやけた」の場合は、 s1 は「たけやぶやけた」に、 s2 も「たけやぶやけた」になります。 左から一文字ずつ比較しても違いは見つかりませんので、"Yes"と答えるというわけです。
この方法は、回文を判定するという問題を解決するものです。 したがって、回文判定のアルゴリズムなのです。
アルゴリズムは必ずしも一つとは限りません。 以下も回文判定のアルゴリズムです。
アルゴリズムが分かっていましても、そのままではコンピュータは問題解決をしてくれません。 コンピュータが日本語を理解するわけでもありませんし、どうやって「左右を逆転した文字列を生成」するのかも、はっきりしていません。 コンピュータに問題解決をしてもらうためには、コンピュータに処理できるような形で、アルゴリズムを具体的に表現する必要があります。 この表現のための言語がプログラミング言語であり、表現自身がプログラムです。
Javaはプログラミング言語のひとつです。 この授業の目的は、アルゴリズムをJavaのプログラムで表現し、コンピュータに問題解決をさせることであると言えます。 Java言語を覚えることと、アルゴリズムを見つけることは、無関係ではありません。 Javaの知識があればこそ、Javaで表現しやすいアルゴリズムが構成できるからです。 授業では、Java言語、アルゴリズム、およびプログラミングを並行して身につけることにします。
なお、プログラミング言語はJavaの他にもたくさんあります。 現在よく使われいるのは、C, C++, Javaです。 それなりに使われているのは、Fortran, Cobol, Lisp, Basic, Pascal, Prologといったところです。 プログラミング言語が変われば、解決しやすい問題の種類や、プログラムに対する考え方が変わります。 今はJavaで精一杯かもしれませんが、色々なプログラミング言語を経験し、問題や考え方に応じてプログラミング言語を選べるようなるのが理想的です。
プログラムの一部や全部の説明文がプログラムの中に書けますと、プログラマにとってプログラムが理解しやすくなります。
このような説明文を
コメント
(
comment
)
とよびます。
Javaコンパイラ(javac)は、プログラムに記号
//
が現れますと、そこから行末までを無視します。
そこにコメントを書けば、プログラムに影響を与えずにプログラムの説明ができます。
次のプログラムはコメントの使用例です。
class GoodAfternoon { // b04a001, Kyoko Azuma, Apr. 28, 2006 public static void main (String[] args) { System.out.println("Good afternoon!"); // Say good afternoon. } }
また、記号
/*
と
*/
に囲まれた部分も無視されます。
このふたつは同じ行にある必要はありませんので、たくさんの行を一度にコメント指定できます。
ただし、このコメントは入れ子にできません。
例えば、
System.out.println("Good morning!"); /* System.out.println("----------"); System.out.println("----------"); */ System.out.println("Good afternoon!");
という部分をコメント指定しようとして、
/* System.out.println("Good morning!"); /* System.out.println("----------"); System.out.println("----------"); */ System.out.println("Good afternoon!"); */
と書きましても、最初の
*/
までがコメントだと見なされてしまいます。
プログラムの行頭のスペース(字下げ)は インデント ( indent ) とよばれます。 Javaコンパイラ(javac)は行頭のスペースを無視します。 インデントをうまく使いますと、プログラムの構造を見やすくできます。
上記のプログラムでインデントを用いませんと
class GoodAfternoon { // b04a001, Kyoko Azuma, Apr. 28, 2006 public static void main (String[] args) { System.out.println("Good afternoon!"); // Say good afternoon. } }
となります。
最後の2つの閉じブレース(
}
)がそれぞれどの開きブレース(
{
)に対応しているかが分かりにくいです。
インデントを用いずに長いプログラムを書きますと、ブレースの対応が分からなくなり、プログラムの構造を見えなくしてしまいます。
前々回の授業では、Javaアプリケーションの例として、「ターミナル」にGood afternoon!と出力するプログラムを動かしてみました。 また、前回は、アプレットの例として、絵を描くプログラムを作成しました。 今回は、再びアプリケーションに戻りまして、数(特に整数)を取り扱うことにします。
次のプログラムを動かしますと、「ターミナル」で以下のような出力が得られます。
/* 1*/ class ExpressionTest { /* 2*/ public static void main (String[] args) { /* 3*/ System.out.println(100); /* 4*/ System.out.println(250 + 100); /* 5*/ System.out.println(250 - 100); /* 6*/ System.out.println(250 * 100); /* 7*/ System.out.println(250 / 100); /* 8*/ System.out.println(250 % 100); /* 9*/ System.out.println(1000 + 250 * 3); /* 10*/ } /* 11*/ }
b04a001@AsiaA1:~/comp2b% javac ExpressionTest.java b04a001@AsiaA1:~/comp2b% java ExpressionTest 100 350 150 25000 2 50 1750 b04a001@AsiaA1:~/comp2b%
プログラムの最初の2行はそのまま書くものと考えてください。
ただし、
class
の右はファイル名です。
プログラム中の
250 + 100
,
250 - 100
などは
式
(
expression
)
とよばれるものです。
プログラムを動かしますと、式が計算されているのが分かります。
ここで、記号
*
が掛け算を表していることに注意してください。
また、記号
/
は割り算を表していますが、この場合は2余り50という計算をして、2を計算結果としています。
余りを求めるには、
/
の代わりに
%
を書きます。
+
,
-
,
*
,
/
,
%
などを
演算子
(
operator
)
とよびます。
記号 | 演算 | 例 |
---|---|---|
+ |
足し算 | 19 + 3 ⇒ 22 |
- |
引き算 | 19 - 3 ⇒ 16 |
* |
掛け算 | 19 * 3 ⇒ 57 |
/ |
割り算 | 19 / 3 ⇒ 6 |
% |
割った余り | 19 % 3 ⇒ 1 |
上記の最後の出力を見ますと、式
1000 + 250 * 3
の計算は、はじめに掛け算をして、次に足し算をしていることが分かります。
これは、演算子
+
より
*
のほうが優先順位が高いと決められていて、式は優先順位の高い演算子から順に計算されるからです。
もし、足し算を先に計算したければ、括弧を使って
(1000 + 250) * 3
と書いてください。
この式の計算結果は3750となります。
演算子の優先順位を簡単に説明しますと、まず括弧の中が最優先で計算されます。
次に演算子
*
,
/
, および
%
が優先します。
最も優先順位が低いのは、演算子
+
と
-
です。
ここで注意すべきことは、
+
と
-
は同じ優先順位であり、これらが続いているときは左から右に計算されることです。
例えば、式
5 - 3 + 1
は
(5 - 3) + 1
と見なされ、3という計算結果になります。
演算子
*
,
/
,
%
についても同様です。
注意: 割り算で、0 で割ることはできません。 そのような計算を行いますと、エラーが発生してプログラムは途中で停止します。 javacコマンドが成功しても、プログラムが動くとは限らないのです。
/* 1*/ class DivisionTest { /* 2*/ public static void main (String[] args) { /* 3*/ System.out.println(100 / 2); /* 4*/ System.out.println(100 / 0); /* 5*/ System.out.println(100 / 5); /* 6*/ } /* 7*/ }
b04a001@AsiaA1:~/comp2b% javac DivisionTest.java b04a001@AsiaA1:~/comp2b% java DivisionTest 50 Exception in thread "main" java.lang.ArithmeticException: / by zero at DivisionTest.main(DivisionTest.java:4) b04a001@AsiaA1:~/comp2b%
プログラムでは、 変数 ( variable ) というものが重要な役割を果たします。 変数とは、数などのデータが格納できる「入れ物」であると考えてください。 次の図は変数のイメージです。
変数には名前がついています。 これを 変数名 ( variable name ) とよびます。 この場合は x です。 また、変数にはデータがひとつ格納できます。 これを変数の 値 ( value ) とよびます。 この場合、変数 x の値は100です。
変数を使えるようにするには、変数の 宣言 ( declaration )という手続きが必要です。 変数の宣言を行うのが 宣言文 ( declaration statement )です。
変数にデータを格納することを、 代入 ( assignment )と言います。 代入を行うのが 代入文 ( assignment statement )です。
変数に格納されたデータを取り出すには、式の中で数の代わりに変数名を書きます。
以下は変数を使ったプログラムの例です。
/* 1*/ class VariableTest { /* 2*/ public static void main (String[] args) { /* 3*/ int x; /* 4*/ x = 100; /* 5*/ System.out.println(x); /* 6*/ } /* 7*/ }
b04a001@AsiaA1:~/comp2b% javac VariableTest.java b04a001@AsiaA1:~/comp2b% java VariableTest 100 b04a001@AsiaA1:~/comp2b%
3行目では、変数の宣言を行って、変数を使えるようにしています。
変数名を
x
とし、ここに格納するデータの種類(型といいます)は整数(
int
型)だと言っています。
4行目は代入文です。 変数 x にデータ100を格納します。 代入文は、一般に
variable = expression;
という形をとります。 式 expression の計算結果を変数 variable に格納するということです。 単なる数も式の一種だということに注意してください。
5行目は結果の出力です。
変数
x
にはデータ100が格納されていますので、あたかも
System.out.println(100);
と書いたように振舞います。
なお、変数名はプログラマが決めます。 アルファベットの大文字か小文字で始まり、アルファベットの大文字、小文字、数字、アンダースコア(_)を並べた文字列が使えます。 ただし、次の文字列はJavaで特別な意味を持つキーワードですので、変数名としては使えません。
A | abstract ,assert . |
---|---|
B | boolean ,break ,byte . |
C | case ,catch ,char ,class ,const ,continue . |
D | default ,do ,double . |
E | else ,extends . |
F | final ,finally ,float ,for . |
G | goto . |
I | if ,implements ,import ,instanceof ,int ,interface . |
L | long . |
N | native ,new . |
P | package ,private ,protected ,public . |
R | return . |
S | short ,static ,strictfp ,super ,switch ,synchronized . |
T | this ,throw ,throws ,transient ,try . |
V | void ,volatile . |
W | while |
また、
null
,
true
,
false
も変数名としては使えません。
次のプログラムはいくつかの変数を使う例です。
/* 1*/ class SomeVariables { /* 2*/ public static void main (String[] args) { /* 3*/ int temp1, temp2, temp3; /* 4*/ temp1 = 300; /* 5*/ temp2 = 200; /* 6*/ temp3 = 4 * temp1 + 3 * temp2; /* 7*/ System.out.println(temp3); /* 8*/ System.out.println(4 * 300 + 3 * 200); /* 9*/ } /* 10*/ }
b04a001@AsiaA1:~/comp2b% javac SomeVariables.java b04a001@AsiaA1:~/comp2b% java SomeVariables 1800 1800 b04a001@AsiaA1:~/comp2b%
3行目で、3つの変数 temp1 , temp2 , temp3 を宣言します。 これは、変数の宣言
int temp1; int temp2; int temp3;
をまとめたものです。 6行目で、変数 temp3 に式 4× temp1 +3× temp2 の値を代入します。 変数 temp1 の値は300で、 temp2 の値は200ですので、4×300+3×200を計算して、この値1800が変数 temp3 に格納されます。
前小節では次のようなプログラムを動かしました。
/* 1*/ class VariableTest { /* 2*/ public static void main (String[] args) { /* 3*/ int x; /* 4*/ x = 100; /* 5*/ System.out.println(x); /* 6*/ } /* 7*/ }
変数の宣言とデータの格納は一緒に行うことができます。 この操作を変数の 初期化 ( initialization ) とよび、そのデータをその変数の 初期値 ( initial value ) とよびます。 次のプログラムの3行目で、変数 x を100に初期化しています。
/* 1*/ class VariableTest2 { /* 2*/ public static void main (String[] args) { /* 3*/ int x = 100; /* 4*/ System.out.println(x); /* 5*/ } /* 6*/ }
次のように書きますと、複数の変数が初期化できます。
int x = 100, y = 200;
次のように、変数の初期化と単なる宣言を混ぜることもできます。
int x = 100, y = 200, z;
今までの例では、変数に格納されたデータは特に変更されませんでした。 一般的には、変数に格納されたデータは何度も変更されます。
/* 1*/ class VariableTest3 { /* 2*/ public static void main (String[] args) { /* 3*/ int x = 100; /* 4*/ x = x + 1; /* 5*/ System.out.println(x); /* 6*/ } /* 7*/ }
b04a001@AsiaA1:~/comp2b% javac VariableTest3.java b04a001@AsiaA1:~/comp2b% java VariableTest3 101 b04a001@AsiaA1:~/comp2b%
このプログラムは、いったん変数 x にデータ100を格納した後、それを1増加させるものです。 4行目は、変数 x の値に1をたしたものを変数 x に格納する代入文です。 x と x + 1 が等しいと言っているわけではありません。 このイメージは次の図のようになります。
変数の値を1増加させることは頻繁に行われますので、省略形が用意されています。
x++;
で
x = x + 1;
と同じことが行われます。
変数の値を1減少させることにつきましても、
x = x - 1;
を
x--;
と省略することができます。
/* 1*/ class VariableTest4 { /* 2*/ public static void main (String[] args) { /* 3*/ int x = 100, y = 200; /* 4*/ x++; /* 5*/ y--; /* 6*/ System.out.println(x); /* 7*/ System.out.println(y); /* 8*/ } /* 9*/ }
b04a001@AsiaA1:~/comp2b% javac VariableTest4.java b04a001@AsiaA1:~/comp2b% java VariableTest4 101 199 b04a001@AsiaA1:~/comp2b%
変数の使用例として、次の問題を考えます。
A子は店に行き、150円のペットボトルを1本と120円の缶ジュースを3本買いました。 A子はいくら支払わなければならないでしょうか。
この問題を解決するには、式 150+3×120 を計算するのが簡単です。 プログラムは次の通りです。
/* 1*/ class SomeDrinks { /* 2*/ public static void main (String[] args) { /* 3*/ System.out.println(150 + 3 * 120); /* 4*/ } /* 5*/ }
b04a001@AsiaA1:~/comp2b% javac SomeDrinks.java b04a001@AsiaA1:~/comp2b% java SomeDrinks 510 b04a001@AsiaA1:~/comp2b%
変数を使って、合計金額を順番に増加させるというアルゴリズムもあります。 つまり、始めに合計金額を表す変数 total に0を格納し、次に変数 total の値を150増加させ、最後に変数 total の値を 3×120 増加させます。 プログラムは次の通りです。
/* 1*/ class SomeDrinks2 { /* 2*/ public static void main (String[] args) { /* 3*/ int total = 0; /* 4*/ total = total + 150; /* 5*/ total = total + 3 * 120; /* 6*/ System.out.println(total); /* 7*/ } /* 8*/ }
合計金額だけではなく、ペットボトルと缶ジュースの値段も変数に格納しておくことも考えられます。 変数名は、それぞれ pet , can とします。 プログラムは次の通りです。
/* 1*/ class SomeDrinks3 { /* 2*/ public static void main (String[] args) { /* 3*/ int total = 0, pet = 150, can = 120; /* 4*/ total = total + pet; /* 5*/ total = total + 3 * can; /* 6*/ System.out.println(total); /* 7*/ } /* 8*/ }
次の問題を考えます。
B子は店に行き、100円のチョコレートを2枚と120円のアイスクリームを2個と150円のクッキーを1袋買いました。 B子はいくら支払わなければならないでしょうか。
この問題を解決するアルゴリズムを考え、プログラムを作成してください。 プログラムでは、変数を適切に利用してください。
b04a001@AsiaA1:~/comp2b% javac SomeSweets.java b04a001@AsiaA1:~/comp2b% java SomeSweets 590 b04a001@AsiaA1:~/comp2b%
余力のある人は、同じような買い物を自分で考え、支払金額を求めるプログラムを作成してください。 プログラムは、何を買ったかが分かるようにしてください。
今日の演習3の答案(Javaプログラム)を、メールでkonishi@twcu.ac.jp宛に提出してください。 メールを送るときは、大学のパソコンを使うか、大学のメール・サーバに接続するかして、差出人が大学のメール・アドレスになるようにしてください。 メールの本文には、学生番号、氏名、科目名、授業日(4月28日)を明記してください。