よく利用するアプリケーションは、Dockに登録しておくと、次回からはワンクリックで起動できるようになります。 登録したいアプリケーションは、起動したときにDockに現れるアイコンを右クリックし、「オプション」→「Dockに追加」とクリックしてください。
Jeditで、プログラムを修正するとき、何行目かが分かると便利です。 そのときは、メニューバーで「表示」→「行番号を表示」→「狭い幅で」とクリックして、行番号を表示してください。
「ターミナル」でコマンドを入力するとき、以下のキーを押すと、入力が楽になります。
前々回の授業では、プログラムとは何かについて説明しました。 人間がプログラムを作ってパソコンに与えると、パソコンはそのプログラムに従って動くという内容です。 プログラムには、もう一つの特徴付けがあります。 それは、「プログラムとはアルゴリズムの具体的な表現である。」です。 ここで、 アルゴリズム ( algorithm )とは、問題を解決するための手順のことです。
アルゴリズムの説明で、問題解決と言われても、ピンと来ないかもしれません。 例として、次の問題を考えます。
与えられた文字列が回文か否かを判定せよ。 ここで回文とは、「たけやぶやけた」のように、左から読んでも右から読んでも同じになる文字列のことである。
この問題は、次のような手順で解決できます。
今、「いるかはまるい」という文字列が与えられたとします。 s1 は「いるかはまるい」に、 s2 は「いるまはかるい」になります。 左から一文字ずつ比較すると、3文字目で違いが見つかるので、"No"と答えます。 一方、「たけやぶやけた」の場合は、 s1 は「たけやぶやけた」に、 s2 も「たけやぶやけた」になります。 左から一文字ずつ比較しても違いは見つからないので、"Yes"と答えるというわけです。
この手順は、回文判定のアルゴリズムと言えます。 実際、この手順によって、回文を判定するという問題が解決します。
アルゴリズムは必ずしも一つとは限りません。 以下も回文判定のアルゴリズムです。
アルゴリズムが分かっても、そのままではパソコンは問題解決をしてくれません。 パソコンが日本語を理解するわけでもないですし、どうやって「左右を逆転した文字列を生成」するのかも、はっきりしていません。 パソコンに問題解決をしてもらうには、パソコンに処理できるような形で、アルゴリズムを具体的に表現する必要があります。 この表現のための言語がプログラミング言語であり、表現自身がプログラムです。
Javaはプログラミング言語の一つです。 この授業の目的は、アルゴリズムをJavaのプログラムで表現し、パソコンに問題解決をさせることであると言えます。 Javaを覚えることと、アルゴリズムを見つけることは、無関係ではありません。 Javaの知識があればこそ、Javaで表現しやすいアルゴリズムが構成できるからです。 授業では、Java、アルゴリズム、およびプログラミングを並行して身につけることにします。
なお、プログラミング言語はJavaの他にもたくさんあります。 現在よく使われているのは、C, C++, Javaです。 今までよく使われてきたのは、Fortran, Cobol, Lisp, Basic, Pascal, Prologといったところです。 プログラミング言語が変われば、解決しやすい問題の種類や、プログラムに対する考え方が変わります。 今はJavaで精一杯かもしれませんが、色々なプログラミング言語を経験し、問題や考え方に応じてプログラミング言語を選べるようになるのが理想的です。
プログラミング言語と似たものに、 スクリプト言語 ( script language )または スクリプティング言語 ( scripting language )というものがあります。 これは、特定の用途のために、簡単にプログラミングができるようにした言語です。 例えば、スクリプト言語JavaScriptを使えば、Webブラウザの中で動くプログラムが作成できます。 スクリプト言語はJavaScriptだけでなく、Perl, PHP, Pythonなど種類も多く、それぞれの得意分野で使われています。
プログラムの一部や全部の説明文がプログラムの中に書けると、プログラマにとってプログラムが理解しやすくなります。
このような説明文を
コメント
(
comment
)とよびます。
javacコマンド(Javaコンパイラ)は、プログラムに記号
//
が現れると、そこから行末までを無視します。
そこにコメントを書けば、プログラムに影響を与えずにプログラムの説明ができます。
次のプログラムはコメントの使用例です。
// k16x1001 東 京子 2017年10月6日 class ProgramTest { public static void main (String[] args) { System.out.println("OK"); // 動作確認 } }
また、記号
/*
と
*/
に囲まれた部分も無視されます。
この2つの記号は同じ行に書く必要はないので、たくさんの行を一度にコメント指定できます。
例えば、
class CommentTest { public static void main (String[] args) { System.out.println("OK"); System.out.println("Good"); System.out.println("Nice"); System.out.println("Excellent"); } }
というプログラムは、どこも無視されませんが、
class CommentTest { public static void main (String[] args) { System.out.println("OK"); /* System.out.println("Good"); System.out.println("Nice"); */ System.out.println("Excellent"); } }
とすると、GoodとNiceの行が無視されます。 ただし、このコメントは入れ子にできません。 OKからExcellentまで無視してもらおうとして、
class CommentTest { public static void main (String[] args) { /* System.out.println("OK"); /* System.out.println("Good"); System.out.println("Nice"); */ System.out.println("Excellent"); */ } }
と書いても、最初の
*/
までがコメントだと見なされ、Excellentの行は無視されないのです。
注意: この授業の例題のプログラムには、一行一行に行番号のコメントを入れていますが、これは説明のためであり、自作のプログラムでは書く必要はありません。
プログラムの行頭のスペース(字下げ)は インデント ( indent )とよばれます。 javacコマンド(Javaコンパイラ)は行頭のスペースを無視します。 インデントをうまく使うと、プログラムの構造を見やすくできます。
動作確認のプログラムでインデントを用いないと
class ProgramTest { public static void main (String[] args) { System.out.println("OK"); } }
となります。
最後の2つの閉じブレース(
}
)がそれぞれどの開きブレース(
{
)に対応しているかが分かりにくいです。
インデントを用いずに長いプログラムを書くと、ブレースの対応が分からなくなり、プログラムの構造を見えなくしてしまいます。
この授業では、次の規則でインデントをします。
{
)の直後に改行する。
}
)のインデントは、対応する開きブレースの行に合わせる。
この規則に従ってインデントをすると、ブレースに囲まれた部分が下図のようなブロック(長方形)になるので、プログラムの構造が見やすくなります。
前々回の授業では、Javaアプリケーションの例として、「ターミナル」にOKと出力するプログラムを動かしてみました。 また、前回は、アプレットの例として、絵を描くプログラムを作成しました。 今回は、再びアプリケーションに戻って、数(特に整数)を取り扱うことにします。
次のプログラムを動かすと、「ターミナル」で以下のような出力が得られます。
/* 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*/ }
24102a1:java1 k16x1001$ javac ExpressionTest.java 24102a1:java1 k16x1001$ java ExpressionTest 100 350 150 25000 2 50 1750 24102a1:java1 k16x1001$
プログラムの最初の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*/ }
24102a1:java1 k16x1001$ javac DivisionTest.java 24102a1:java1 k16x1001$ java DivisionTest 50 Exception in thread "main" java.lang.ArithmeticException: / by zero at DivisionTest.main(DivisionTest.java:4) 24102a1:java1 k16x1001$
プログラムでは、 変数 ( 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*/ }
24102a1:java1 k16x1001$ javac VariableTest.java 24102a1:java1 k16x1001$ java VariableTest 100 24102a1:java1 k16x1001$
3行目では、変数の宣言を行って、変数を使えるようにしています。 変数名を x とし、ここに格納するデータの種類(型といいます)は整数(int型)だと言っています。
宣言文は、整数の場合は
int 変数名;
という形が基本です。
4行目は代入文です。 変数 x にデータ100を格納します。
代入文は、一般的に
変数名 = 式;
という形をとります。 「 変数名 」に「 式 」の計算結果を格納するということです。 単なる数や変数も式の一種です。 従って、
変数名 = 数;
ならば、「 変数名 」に「 数 」を格納しますし、
変数名1 = 変数名2;
ならば、「 変数名1 」に「 変数名2 」の値を格納します。
5行目は結果の出力です。 変数 x にはデータ100が格納されているので、
System.out.println(x);
の部分が
System.out.println(100);
と書いたように振舞います。
なお、変数名はプログラマが決めます。 英単語などを使って、分かりやすい変数名にしてください。 数学の変数のように、1文字にする必要はありません。 変数名の条件は、アルファベットの大文字か小文字で始まり、アルファベットの大文字、小文字、数字、アンダースコア(_)を並べた文字列です。 ただし、次の文字列はJavaで特別な意味を持つ キーワード なので、変数名としては使えません。
A |
abstract
assert
|
---|---|
B |
boolean
break
byte
|
C |
case
catch
char
class
const
continue
|
D |
default
do
double
|
E |
else
enum
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
も変数名としては使えません。
Javaらしい変数名の付け方は、英単語を続けて書き、2番目以降の単語の先頭を大文字にするというものです。 例えば、ペットボトルの値段を表す変数名としては、次のようなものが考えられます。
次のプログラムはいくつかの変数を使う例です。
/* 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*/ }
24102a1:java1 k16x1001$ javac SomeVariables.java 24102a1:java1 k16x1001$ java SomeVariables 1800 1800 24102a1:java1 k16x1001$
3行目で、3つの変数 temp1 , temp2 , temp3 を宣言します(temporary=一時的な)。 これは、変数の宣言
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 /* 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 { // 変数のテスト3 /* 2*/ public static void main (String[] args) { /* 3*/ int x = 100; /* 4*/ x = 101; // 101を格納 /* 5*/ System.out.println(x); /* 6*/ } /* 7*/ }
24102a1:java1 k16x1001$ javac VariableTest3.java 24102a1:java1 k16x1001$ java VariableTest3 101 24102a1:java1 k16x1001$
このプログラムは、変数 x にデータ100を格納した後、さらにデータ101を格納するものです。 5行目で変数 x の値を取り出すと、101になります。 最初のデータ100は上書きされてしまいます。 このイメージは次の図のようになります。
変数の使用例として、次の問題を考えます。
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*/ }
24102a1:java1 k16x1001$ javac SomeDrinks.java 24102a1:java1 k16x1001$ java SomeDrinks 510 24102a1:java1 k16x1001$
変数に計算結果を格納するアルゴリズムもあります。 まず、合計金額を表す変数 total を宣言しておきます。 次に、式を計算し、その結果を変数 total に格納します。 最後に、変数 total の値を取り出して出力します。
合計金額だけではなく、ペットボトルと缶ジュースの値段も変数に格納しておくと、より分かりやすくなります。 変数名は、それぞれ pet , can とします。 プログラムは次の通りです。
/* 1*/ class SomeDrinks2 { // いくつかの飲み物2 /* 2*/ public static void main (String[] args) { /* 3*/ int total, pet = 150, can = 120; /* 4*/ total = pet + 3 * can; /* 5*/ System.out.println(total); /* 6*/ } /* 7*/ }
次の問題を考えます。
B子はドラッグストアに行き、100円のティッシュを5箱と200円の石けんを2個と300円のタオルを1枚買いました。 B子はいくら支払わなければならないでしょうか。
この問題を解決するアルゴリズムを考え、プログラムを作成してください。 プログラムでは、変数を適切に利用してください。
24102a1:java1 k16x1001$ javac Drugstore.java 24102a1:java1 k16x1001$ java Drugstore 1200 24102a1:java1 k16x1001$
余力のある人は、同じような買い物を自分で考え、支払金額を求めるプログラムを作成してください。 プログラムは、何を買ったかが分かるようにしてください。
今日の演習3の答案(Javaプログラム)をメールで提出してください。 差出人は学内のメール・アドレス(学生番号@cis.twcu.ac.jp)とし、宛先はkonishi@cis.twcu.ac.jpとします。 メールの本文には、学生番号、氏名、科目名、授業日(10月6日)を明記してください。