カテゴリー
Java

Java(Step4-3)

プログラムの流れの繰り返し

for文

定型的な繰り返しの制御を、while文よりも簡潔に実現する for文について説明していきます。

for文

読み込んだ個数だけ * を表示するプログラムをwhile文ではなく、for文(for statement)と呼ばれる文によって書き換えたものを以下に示します。

//PutAsteriskFor.java
//読み込んだ個数だけ*を表示
import java.util.Scanner;

public class PutAsteriskFor {
    public static void main(String[] args){
        Scanner stdIn = new Scanner(System.in);

        System.out.print("何個*を表示しますか?:");
        int n = stdIn.nextInt();

        for(int i = 0; i < n; i++){
            System.out.print('*');
        }
        System.out.println();
        stdIn.close();
    }    
}
PutAsteriskFor.java実行結果

プログラムはwhile文よりも短くなります。for文に慣れるとwhile文よりも直観的に分かりやすいものとなります。

for文とwhile文は相互に置き換えることができます。以下の図は、同等に書いた各文になります。

for文とwhile文

for文のプログラムの流れは以下のようになります。

  1. まず、前処理ともいうべきAが評価、実行されます。
  2. 継続条件であるBの制御式がtrueである限り、文が実行されます。
  3. 文の実行後は、後始末的な処理あるいは次の繰り返しのための準備としてCが評価、実行されます。

for文の各部に関する細かい規則などを以下に示します。

A for初期化部

Aには変数を置くことができます。ここで、宣言する変数はそのfor文の中でのみ使用できます。異なるfor文で同一名の変数を使用するには、各for文毎に宣言が必要です。

B 式(制御式)

B部も省略できます。省略した場合、繰り返しの継続判定は常にtrueとみなされます。この後で学習するbreak文やreturn文をループ本体中で実行しない限り、永遠に繰り返す無限ループになります。

C for 更新部

複数の式をコンマで区切っておくこともできます。何も行うことが無ければ、Cも省略可能です。

フローチャート

ここでは、フローチャートとその記号について解説します。

  • 流れ図の記号

問題の定義、分析、解法の図的表現である流れ図=フローチャート(flowchart)と、その記号は以下の規格で定義されています。

JIS X0121「情報処理用流れ図・プログラム網図・システム資源図記号」

  • プログラム流れ図(program flowchart)

プログラム流れ図は、以下に示す記号で構成されます。

実際に行う演算を示す記号、制御の流れを示す線記号、プログラム流れ図を理解し、かつ作成するために便宜を与える特殊記号。

  • データ(data)

媒体を指定しないデータを表します。

  • 処理(process)

任意の種類の処理機能を表します。例えば、情報の値、形、位置を変えるように定義された演算、もしくは演算群の実行、または、それに続くいくつかの流れの方向の1つを決定する演算もしくは演算群の実行を表します。

  • 定義済み処理(predefined process)

サブルーチンやモジュールなど、別の場所で定義された1つ以上の演算又は命令群からなる処理を表します。

  • 判断(decision)

1つの入り口と複数の択一的な出口を持ち、記号中に定義された条件の評価に従って、唯一の出口を選ぶ判断機能、またはスイッチ形の機能を表します。想定される評価結果は、経路を表す線の近くに書きます。

  • ループ端(loop limit)

2つの部分から構成され、ループの始まりと終わりを表します。記号の2つの部分には、同じ名前を用います。ループの始端記号または、ループの終端記号の中に初期化・増分・終了条件を表記します。

  • 線(line)

制御の流れを表します。流れの向きを明示する必要がある時は、矢先を付けなければなりません。

  • 端子(terminator)

外部環境への出口、または外部環境からの入り口を表します。例えばプログラムの流れの開始もしくは終了を表します。

この他に、並列処理や破線などの記号があります。

奇数の列挙

まずは、整数値を読み込んで、その整数値以下の正の奇数1,3,5,… を表示するプログラムを作りましょう。

//Odd.java
//読み込んだ整数値以下の奇数を表示
import java.util.Scanner;

public class OddNo {
    public static void main(String[] args){
        Scanner stdIn = new Scanner(System.in);

        System.out.print("整数値:");
        int n = stdIn.nextInt();

        for(int i = 1; i <= n; i += 2){
            System.out.println(i);
        }
        stdIn.close();
    }    
}
Odd.java実行結果

for文の中で i += 2 で使っているのは、右オペランドの値を左オペランドに加える複合代入演算子になります。変数 i に 2 を繰り返しの度に増やしていきます。

約数の列挙

次に読み込んだ整数値のすべての約数を表示するプログラムを作りましょう。

//Measure.java
//読み込んだ整数値の約数を全て表示
import java.util.Scanner;

public class Measure {
    public static void main(String[] args){
        Scanner stdIn = new Scanner(System.in);

        System.out.print("整数値:");
        int n = stdIn.nextInt();

        for(int i = 1; i <= n; i++){
            if(n % i == 0)
                System.out.println(i);
        }
        stdIn.close();
    }    
}
Measure.java実行結果

まず、変数nに整数値を読み込みます。続くfor文では、変数 i の値を1からnまでインクリメントします。n を i で割った余剰が0ならば、i は n の約数であると判断できます。

複数変数の同時制御

これまでのプログラムのfor文は、1つの変数の値を元にして繰り返しを制御するものでした。for文では、複数の変数を同時に制御することも可能です。例が以下のようになります。

//For2var.java
//読み込んだ整数値と各値との差を表示
import java.util.Scanner;

public class For2var {
    public static void main(String[] args){
        Scanner stdIn = new Scanner(System.in);

        System.out.print("整数値:");
        int n = stdIn.nextInt();

        for(int i = 1, j = n-1; i <= n; i++, j--){
            System.out.println("数字" + i +  "との差は" + j);
        }
        stdIn.close();
    }    
}
For2var.java実行結果

プログラムの流れを確認しましょう。まず、最初に整数値 n に読み込みます。 2つの変数 i と j を宣言して、それぞれ 1 と n – 1 で初期化します。i の値をインクリメントする傍ら、j の値をデクリメントします。i の値は1ずつ増加し、j の値は1ずつ減少します。i <= nが成立しなくなると、繰り返しは終了します。

カテゴリー
Java

Java(Step4-2)

プログラムの流れの繰り返し

While文

ある条件が成立するあいだ処理を繰り返すのは、do文だけでなくwhile文によっても実現できます。

while文

正の整数値を読み込んで、その値を0までカウントダウンする過程を表示するプログラムを作っていきましょう。

//CountDown1.java
//正の整数値を0までカウントダウン
import java.util.Scanner;

public class CountDown1 {
    public static void main(String[] args){
        Scanner stdIn = new Scanner(System.in);

        System.out.println("カウントダウンスタート");
        int x;
        do{
            System.out.print("正の整数値:");
            x = stdIn.nextInt();
        }while(x <= 0);

        while(x >= 0){
            System.out.println(x);   //xの値を表示
            x--;    //xの値をデクリメント
        }
        stdIn.close();
    }    
}
CountDown1.java実行結果

このプログラムでは、xに読み込んだ値が0以下である限り、繰り返されdo文が終了したときには正の値になっています。

その後に、変数xに読み込んだ値を0までカウントダウンする過程を表示する部分に用いているのが、while文(while statement)です。while文は、式を評価した値がtrueである限り文を繰り返し実行します。そのため、流れは以下のようになります。

while文のフローチャート

増分演算子と減分演算子

カウントダウンのために利用しているのが、変数の値を1つ減らす — です。

後置増分演算子と後置減分演算子

単項演算子である減分演算子 — は、オペランドの値をデクリメントする演算子です。したがって、while文は、xが0以上の間、以下に示すループ本体を繰り返すことになります。

  1. xの値を表示
  2. xの値をデクリメント

結果、xの値は0になるまで、カウントダウンしながら表示されます。

–演算子とは逆に、オペランドの値をインクリメントするのが、++演算子です。概略は以下に示しておきます。

x++xの値をインクリメントする(1つ増加する)。生成するのは増加前の値。
x–xの値をデクリメントする(1つ減少する)。生成するのは減少前の値。
後置増分演算子と後置減分演算子

この2つの演算子の特徴を利用すると先ほどのプログラムを簡略化することができます。

//CountDown2.java
//正の整数値を0までカウントダウン
import java.util.Scanner;

public class CountDown2 {
    public static void main(String[] args){
        Scanner stdIn = new Scanner(System.in);

        System.out.println("カウントダウンスタート");
        int x;
        do{
            System.out.print("正の整数値:");
            x = stdIn.nextInt();
        }while(x <= 0);

        while(x >= 0){
            System.out.println(x);   //xの値を表示してデクリメント
        }
        stdIn.close();
    }    
}
CountDown2.java実行結果

後置増分演算子(postfix increment operator)と後置減分演算子(postfix decrement operator)の後置という名前は、オペランドの後ろに演算子を適用することからきています。

前置増分演算子と前置減分演算子

演算子 ++ と — には、オペランドの前に演算子を適用する形の前置増分演算子(prefix increment operator)と前置減分演算子(prefix decrement operator)もあります。

++xxの値をインクリメントする(1つ増加する)。生成するのは増加後の値。
–xxの値をデクリメントする(1つ減少する)。生成するのは減少後の値。
前置増分演算子と前置減分演算子

※後置(前置)の増分演算子/減分演算子を適用した式を評価して得られるのは、インクリメント/デクリメントを行う前(後)の値です。

式の評価順序

2項演算子の左オペランドは、右オペランドよりも先に評価されることになります。検証しているのが以下のプログラムです。

//EvaluationOrder.java
//式の評価順序の確認

public class EvaluationOrder {
    public static void main(String[] args){
        int a = 3;
        int x = (a++) * (3 + a);
        System.out.println("a = " + a);
        System.out.println("x = " + x);
    }    
}
EvaluationOrder.java実行結果

注目するのは、左オペランド(a++)の評価が行われ、そこから(2 + a)の評価が行われ、最後に*による乗算が行われます。そのため、この式の演算は以下の手順で行われます。

  1. 式 a++ が評価される。評価によって得られる値は、インクリメント前の3です。評価が完了されると、インクリメントされて4となる。
  2. 式 3 + a が評価される。評価によって生成される値は7 です。a の値は変化しない。
  3. 乗算 3 * 7 によって21が生成され、その値がxに入れられる。

式の値の切り捨て

以前のwhile文を振り返ってみましょう。

while(x >= 0){
            System.out.println(x);   //xの値を表示
            x--;    //xの値をデクリメント
}

このプログラムでは、後置減分演算子で変数xをデクリメントしています。もし、変数xの値が5であれば、この式を評価した値はデクリメント前の5になります。ここで注意すべきなのは、式x–を評価した値を使っていないことです。演算を行った結果は無視することができます

式を評価した値を切り捨てる文脈では、前置形式、後置形式のどちらの演算子を使っても同じ結果が得られます。

文字リテラル

while文と++演算子を組み合わせたプログラムを作ってみましょう。キーボードから読み込んだ値の分だけ、アスタリスク記号を描画しましょう。

//PutAsterisk1.java
//読み込んだ個数だけ*を表示
import java.util.Scanner;

public class PutAsterisk1 {
    public static void main(String[] args){
        Scanner stdIn = new Scanner(System.in);

        System.out.print("何個*を表示しますか?:");
        int n = stdIn.nextInt();

        int i = 0;
        while(i < n){
            System.out.print('*');
            i++;
        }
        System.out.println();
        stdIn.close();
    }
}
PutAsterisk1.java実行結果

このプログラムで画面に出力しているのは、’*’です。このように単一の文字を単一引用符 ‘ で囲んだ式が文字リテラル(character literal)です。文字列リテラルとは別になります。

  • 文字リテラル ‘*’ …単一の文字 * を表す。型はchar
  • 文字列リテラル “*” …文字 * だけから構成される文字の並びを表す。型はString

while文は0で初期化された変数 i の値をインクリメントしながら、’*’ を表示します。n個目の表示が終わった後にインクリメント i の値はnと等しくなるため、while文による繰り返しが終了します。

このプログラムは、以下のようにも実現することが出来ます。

//PutAsterisk2.java
//読み込んだ個数だけ*を表示
import java.util.Scanner;

public class PutAsterisk2 {
    public static void main(String[] args){
        Scanner stdIn = new Scanner(System.in);

        System.out.print("何個*を表示しますか?:");
        int n = stdIn.nextInt();

        int i = 1;
        while(i <= n){
            System.out.print('*');
            i++;
        }
        System.out.println();
        stdIn.close();
    }
}
PutAsterisk2.java実行結果

while文とdo文

上のプログラムを実行した際に、負の値や0を入力してみましょう。そうすると*は一個も表示されないです。例えば、-5と入力するとwhile文の制御式 i < n の評価結果がfalseとなるため、ループ本体は一回も実行されないです。これがdo文とは大きく異なる特徴です。

  • do文…後判定繰り返し:ループ本体を実行した後に判定を行う。
  • while文…前判定繰り返し:ループ本体を実行する前に判定を行う。
後後判定繰り返しのdo文と前判定繰り返しのwhile文

本来は、do文もwhile文もfor文もループ本体が単一の文であれば、わざわざブロックにする必要はありません。しかし、do文に限っては、ループ本体が単一であっても{ }を導入した方がプログラムが読みやすくなります。

複合代入演算子

以下に示すのは、読み込んだ整数値を反転して表示するプログラムになります。

//ReverseNo.java
//正の整数値を読み込んで逆順に表示
import java.util.Scanner;

public class ReverseNo {
    public static void main(String[] args){
        Scanner stdIn = new Scanner(System.in);

        System.out.println("正の整数値を逆順に表示します。");
        int x;
        do{
            System.out.print("正の整数値:");
            x = stdIn.nextInt();
        }while(x <= 0);

        System.out.print("逆から読むと");
        while(x > 0){
            System.out.print(x % 10);   //xの最下位桁を表示
            x /= 10;   //xを10で割る
        }
        System.out.println("です。");
        stdIn.close();
    }    
}
ReverseNo.java実行結果

数値の逆転

while文のループ本体で行うのは、以下の2つのことです。

  1. xの最下位桁の表示…xの最下位桁の値であるx%10を表示、例えばxが1254なら、表示するのは10で割った余りの4になります。
  2. xを10で割る…表示後に行うのはxを10で割ることです。

演算子/=は、左オペランドの値を右オペランドの値で割ります。これらの処理を繰り返してxの値が0になると、while文が終了します。

演算子*, / , % , + , – , << , >> , >>> , & , ^ , | に対しては、その直後に = を付けた演算子が用意されています。これらの演算子は、演算と代入の2つの働きをもつため、複合代入演算子(compound assignment operator)と呼ばれます。複合代入演算子には以下のメリットがあります。

  • 行うべき演算を簡潔に表せる
  • 左辺の変数名を書くのが一回で済む
  • 左辺の評価が1回限りである

整数の和を求める

複合代入演算子を用いた別のプログラム例を見てみましょう。これは、1~nまでの和を求めるプログラムです。

//SumUp.java
//1からnまでの和を求める
import java.util.Scanner;

public class SumUp {
    public static void main(String[] args){
        Scanner stdIn = new Scanner(System.in);

        System.out.println("1からnまでの和を求めます。");
        int n;
        do{
            System.out.print("nの値:");
            n = stdIn.nextInt();
        }while(n <= 0);

        int sum = 0;   //合計
        int i = 1;

        while(i <= n){
            sum += i;   //sumにiを加える
            i++;      //iをインクリメント
        }
        System.out.println("1から"+ n + "までの和は" + sum + "です。");
        stdIn.close();
    }    
SumUp.java実行結果

和を求める部分のフローチャートは以下のようになります。

1からnまでの和を求めるフローチャート

和を求める前準備として、和を格納する変数sumの値を0にして、繰り返しを制御するための変数 i の値を1にします。変数 i の値がn以下である間、繰り返し実行します。i の値が1つずつ増えるため、繰り返すのはn回となります。

カテゴリー
Java

Java(Step4-1)

プログラムの流れの繰り返し

do文

プログラムで行う処理は一回だけ実行するのではなく、何度も繰り返して実行できます。そのための1つとしてdo文があります。

do文

前の記事では、入力された月の季節を表示するプログラムを作成しました。入力・表示は一回のみに限られています。何度でも入力できるように拡張していきましょう。それが、以下のコードです。

//Season2.java
//入力された月の季節を表示
import java.util.Scanner;

public class Season2 {
    public static void main(String[] args){
        Scanner stdIn = new Scanner(System.in);
        int retry;

        do{
            System.out.print("季節を求めます。\n何月ですか:");
            int month = stdIn.nextInt();

            if(month >= 3 && month <= 5)
                System.out.println("その季節は春です。");
            else if(month >= 6 && month <= 8) 
                System.out.println("その季節は夏です。");
            else if(month >= 9 && month <= 11) 
                System.out.println("その季節は秋です。");
            else if(month >= 12 || month == 1 || month == 2 ) 
                System.out.println("その季節は冬です。");
        
            System.out.print("もう一度? 1…Yes/0…No :");
            retry = stdIn.nextInt();
        }while(retry==1);
        stdIn.close();
    }
}
Season2.java実行結果

mainメソッドの大部分がdoとwhileで囲まれています。この囲んでいる文をdo文(do statement)と呼びます。

doは、「実行せよ」という意味で、whileは「~のあいだ」という意味です。do文は、式を評価した値がtrueである限り、文を繰り返し実行します。このプログラムの流れは、図のようになります。

Season2.javaのdo文のフローチャート

繰り返しのことをループ(loop)と呼ぶので、do文が繰り返す文のことをループ本体(loop body)と呼ぶことにします。

一定範囲の値の読み込み

ジャンケンの手である「グー」「チョキ」「パー」を表示するプログラムを以前作りましたが、0、1、2以外の値を入力すると何も表示されません。do文を用いれば、この3つの値のみの入力しか受け付けないようにできます。そのように書き換えたのが以下のプログラムになります。

//FingerFlashing3.java
//読み込んだ値に応じてジャンケンを表示(0,1,2のみ)
import java.util.Scanner;

public class FingerFlashing3 {
    public static void main(String[] args){
        Scanner stdIn = new Scanner(System.in);
        int hand;
        do{
            System.out.print("何を出しますか?(0…グー、1…チョキ、2…パー):");
            hand = stdIn.nextInt();
        }while(hand < 0 || hand > 2);
        
        switch(hand){
        case 0:System.out.println("グー");break;
        case 1:System.out.println("チョキ");break;
        case 2:System.out.println("パー");break;
        }
        stdIn.close();
    }    
}
FingerFlashing3.java実行結果

このプログラムのdo文の制御式は、次のようになっています。

hand < 0 || hand > 2   //handが0~2の範囲外か

変数handの値が、不正な値(0より小さいかまたは2より大きい値)であれば、この式を評価した値はtrueとなります。そのため、handが0、1、2以外の値であれば、ループ本体であるブロックが繰り返し実行されます。

このdo文の流れを示したのが以下の図になります。

FingerFlashing3.javaのdo文のフローチャート
数あてゲーム

これまで習ってきた乱数、if文、do文を利用して数あてゲームを作ってみましょう。0~99の数字の中から数を当てるプログラムを以下に示します。

//NumGussing.java
//数当てゲーム(0-99)
import java.util.Random;
import java.util.Scanner;

public class NumGussing {
    public static void main(String[] args){
        Random rand = new Random();
        Scanner stdIn = new Scanner(System.in);

        int num = rand.nextInt(100);

        System.out.println("数当てゲームスタート");
        System.out.println("0~99の値を当ててください。");
    
        int x;
        do{
            System.out.println("数を入力してください。:");
            x = stdIn.nextInt();

            if(x > num)
                System.out.println("もっと小さい数です。");
            else if(x < num)
                System.out.println("もっと大きい数です。");
        }while(x != num);
    System.out.println("正解です。");
        stdIn.close();
    }
}
NumGussing.java実行結果

プログラムのフローチャートを以下に示します。

NumGussing.javaのフローチャート
  1. 「数を入力してください」と数値の入力を促して、変数xに値を読み込みます。
  2. 読み込んだxの値がnoより大きければ、「もっと小さい数です」と表示し、xの値がnoより小さければ「もっと大きいです」と表示します。

それから、do文を繰り返すかどうかの判定を行います。判定のための制御式は、

x != no       //読み込んだxと当てるべき数noが等しくないか

です。したがって、読み込んだxの値が当てるべき数noと等しくない間do文が繰り返されることになります。数が当たったら、do文は終了し、「正解です」と表示してプログラムを終了します。

カテゴリー
Java

Java(Step3-3)

プログラムの流れの分岐

キーワード・識別子・演算子

ここでは、演算子を含めたプログラムの構成要素について説明していきます。

キーワード

if や else といった語句には、特別な意味が込められています。このような語句をキーワード(keyword)と呼ばれ、プログラム作成時に変数などの名前としては使えません。Javaのキーワードは、以下のようになっています。

abstractassertbooleanbreakbytecase
catchcharclassconstcontinuedefault
dodoubleelseenumextendsfinal
finallyfloatforgotoifimplements
importinstanceofintinterfacelongnative
newpackageprivateprotectedpublicreturn
shortstaticstrictfpsuperswitchsyncronized
thisthrowthrowstransienttryvoid
volatilewhile
キーワード一覧

正式なキーワードではないですが、true、false、nullも準じてあります。

区切り子

キーワードは、1種の単語のようなものです。その単語を区切るために使われる記号が区切り子(separator)です。以下の9つが使用されます。

[ ] ( ) { } , : .
区切り子の一覧

識別子

識別子(identifier)とは、変数、ラベル、メソッド、クラスなどに与えられる名前のことです。名前は自由に設定できますが、以下の規則に従う必要があります。

  • 識別子の1文字目は、次のいずれかでなければならない…いわゆる文字
  • 識別子の2文字目以降は、次のいずれかでなければならない…いわゆる文字、数字

数字が使えるのは2文字目からであることを覚えておきましょう。また、キーワードに加えて、true と false と null も識別子として使うことができません。

Javaでは、Unicodeという文字コード体系を使うため、”いわゆる文字”にはアルファベットだけでなく漢字文字なども含みます。

リテラル

整数リテラル、浮動小数点リテラル、文字列リテラルなども、プログラムを構成する要素の1つです。

演算子

数多くの演算子(operator)を学習しましたが、以下にJavaで利用できる全演算子をまとめています。

優先順位演算子形式名称結合規則
1[ ]x[y]インデックス演算子
1( )x(arg )メソッド呼び出し演算子
1.x.yメンバアクセス演算子
1++x++後置増分演算子
1x–後置減分演算子
2++++x前置増分演算子
2–x前置減分演算子
2++x単項 + 演算子
2-x単項 – 演算子
2!!x論理補数演算子
2~~xビット単位の補数演算子
3newnewnew 演算子
3( )( )キャスト演算子
4*x * y乗除演算子
4/x / y乗除演算子
4%x % y乗除演算子
5+x + y加減演算子
5x – y加減演算子
6<<x << yシフト演算子
6>>x >> yシフト演算子
6>>>x >>> yシフト演算子
7<x < y関係演算子
7>x > y関係演算子
7<=x <= y関係演算子
7>=x >= y関係演算子
7instanceofx instanceof yinstanceof演算子
8==x == y等価演算子
8!=x != y等価演算子
9&x & yビット論理積演算子
10^x ^ yビット排他的論理和演算子
11|x | yビット論理和演算子
12&&x && y論理積演算子
13||x || y論理和演算子
14? :x ? y : z条件演算子
15=x = y単純代入演算子
15*=x *= y複合代入演算子
15/=x /= y複合代入演算子
15%=x %= y複合代入演算子
15+=x += y複合代入演算子
15-=x -= y複合代入演算子
15<<=x <<= y複合代入演算子
15>>=x >>= y複合代入演算子
15>>>=x >>>=y複合代入演算子
15&=x &= y複合代入演算子
15^=x ^= y複合代入演算子
15|=x |= y複合代入演算子
全演算子の一覧
優先度

演算子の一覧表は、先頭側の方が優先度(precedence)が高くなるように表記しています。たとえば、乗除算を行う * と / が、加減算を行う + や – より優先度が高いのは、日常での計算法則と同じです。よって、

a + b * c

は、(a + b) * c ではなく、 a + (b * c)と解釈されます。

+演算子よりも優先度が低い演算子を文字列の連結時に使用する時は、( )が必要になることに注意しよう。

結合規則

同じ優先度の演算子が連続する時に左右どちらかの演算を先に行うかを示すのが、結合規則(associativity)です。例えば、2項演算子を○とした場合、式 a ○ b ○ c を

(a ○ b) ○ c 左結合

とみなすのが左結合の演算子であり、

a ○ (b ○ c)   右結合

とみなすのが右結合の演算子です。

代入式の評価

原則として式は、その値を評価することができるので、代入式であってもその評価を行うことができます。次のことは必ず覚えましょう。

  • 代入式を評価すると、代入後の左オペランドの型と値が得られる。

例えば、変数xがint型であれば、代入式 x = 5 を評価して得られるのは、代入後の左オペランドでxの型と値である「int型の5」になります。

以上でプログラムの分岐、構成要素については終わりです。次からは、プログラムの流れの繰り返しを説明していきます。

カテゴリー
Java

Java(Step3-2)

プログラムの流れの分岐

Switch文

if文は、ある条件の判定結果に応じて、プログラムの流れを2つに分岐していました。switch文を用いると、一度に複数の分岐ができます。

switch文

以下に示すのは、キーボードから入力された値に応じてジャンケンの手を表示するプログラミングです。

//FingerFlashing1.java
//読み込んだ値に応じてジャンケンを表示(if文)
import java.util.Scanner;

public class FingerFlashing1 {
    public static void main(String[] args){
        Scanner stdIn = new Scanner(System.in);

        System.out.print("何を出しますか?(0…グー、1…チョキ、2…パー):");
        int hand = stdIn.nextInt();

        if(hand == 0)
            System.out.println("グー");
        else if(hand == 1)
            System.out.println("チョキ");
        else if(hand == 2)
            System.out.println("パー");
        stdIn.close();
    }    
}
FingerFlashing1.java実行結果

このプログラムのif文は、handの値によって分岐しています。プログラミング作成時にはhandが何回もタイプするので、煩わしいです。

そこで、分岐を簡潔に表現するのがswitch文(switch statement)になります。switch文は、ある式を評価した値によってプログラムの流れを複数に分岐させる文であり、切り替えスイッチのようなものになります。

次に示すのは、switch文で上のプログラムを書き換えたものになります。

//FingerFlashing2.java
//読み込んだ値に応じてジャンケンを表示(switch文)
import java.util.Scanner;

public class FingerFlashing2 {
    public static void main(String[] args){
        Scanner stdIn = new Scanner(System.in);

        System.out.print("何を出しますか?(0…グー、1…チョキ、2…パー):");
        int hand = stdIn.nextInt();

        switch(hand){
        case 0:System.out.println("グー");break;
        case 1:System.out.println("チョキ");break;
        case 2:System.out.println("パー");break;
        }
        stdIn.close();
    }    
}
FingerFlashing2.java実行結果
ラベル

プログラムの流れがswitch文に差し掛かると、まず()内に書かれた制御式の評価が行われます。そして、その結果に応じてswitch文内のどこにプログラムの流れを移すか決定します。もし、制御式のhandの値が1であれば、プログラムの流れは

case 1:   //handが1のときの飛び先を表すラベル

と書かれた目印へと一気に移ります。プログラムの飛び先を示す目印がラベル(label)です。

プログラムの流れがラベルに飛んだあとは、その後ろに置かれた文が順次実行されます。この場合、handが1であれば、まず以下の文が実行されます。

System.out.println("チョキ");

これで、画面に”チョキ”と表示されます。

break文

プログラムの流れが、break文(break statement)と呼ばれる、

break;

に行き着くと、switch文の実行は終了することになります。breakとは「破る」意味の語句で、break文が実行されると、プログラムの流れはswitch文を突き破って抜け出ます。

より、switch文における、ラベルとbreak文の働きの理解を深めるために以下のコードをチェックしましょう。

//SwitchBreak.java
//switch文とbreak文の復習
import java.util.Scanner;

public class SwitchBreak {
    public static void main(String[] args){
        Scanner stdIn = new Scanner(System.in);
        System.out.print("整数を入力してください:");
        int n = stdIn.nextInt();

        switch(n){
            case 0:System.out.print("A");
                   System.out.print("B");
                   break;
            case 2:System.out.print("C");
            case 5:System.out.print("D");
                   break;
            case 6:
            case 7:System.out.print("E");
                   break;
            default:System.out.print("F");
                    break;
        }
        System.out.println();
        stdIn.close();
    }
}
SwitchBreak.java実行結果
defaultラベル

今回のプログラムには、

default:    //どのラベルとも一致しないときの飛び先を表すラベル

というラベルがあります。分岐のための制御式を評価した値が、どのcaseとも一致しないときは、プログラムの流れはこのラベルに飛ぶことになります。

選択文

if文とswitch文は、プログラムの流れを分岐させるという点で共通しています。これらをまとめて選択文(selection statement)と呼びます。

単一の式の値によるプログラムの流れの分岐は、if文ではなくswitch文によって実現したほうがよい場合が多いので、分岐処理をする際は読み手に分かりやすい処理を検討するようにしましょう。

カテゴリー
Java

Java(Step3-1-2)

プログラムの流れと分岐

if文

論理積演算子と論理和演算子

整数値を読み込んで、それが0なのか、1桁かそれ以上かを判断して表示するプログラムを作りましょう。

//DigitsNo1.java
//読み込んだ整数値の桁数判別(0、一桁、二桁以上)
import java.util.Scanner;

public class DigitsNo1 {
    public static void main(String[] args){
        Scanner stdIn = new Scanner(System.in);

        System.out.print("整数値:");
        int n = stdIn.nextInt();
        if(n == 0)
            System.out.println("その値は0です。");
        else if(n >= -9 && n <= 9)
            System.out.println("一桁です。");
        else
            System.out.println("二桁以上です。");
        stdIn.close();
    }
}
DigitsNo1.java実行結果
論理積演算子 &&

このプログラムで利用している && 演算子は、論理積の演算を行う論理積演算子(logical and operator)です。日本語でいえば、「AかつB」だと考えれば分かりやすいです。

論理和演算子Ⅱ

もう1つの論理和を求めるのが論理和演算子(logical or operator)と呼ばれる || 演算子になります。これは、日本語でいう「AまたはB」に近い形です。この演算子を利用したプログラム以下になります。

//DigitsNo2.java
//読み込んだ整数値の桁数判別(2桁以上かどうか)
import java.util.Scanner;

public class DigitsNo2 {
    public static void main(String[] args){
        Scanner stdIn = new Scanner(System.in);

        System.out.print("整数値:");
        int n = stdIn.nextInt();
        if(n <= -10 || n >= 10)
            System.out.println("2桁以上です。");
        else if(n >= -9 && n <= 9)
            System.out.println("2桁未満です。");
        stdIn.close();
    }
}
DigitsNo2.java実行結果
x && yxとyの両方ともtrueであればtrueを、そうでなければ、falseを生成します。
x || yxとyの一方でもtrueであればtrueを、そうでなければ、falseを生成します。
論理積演算子と論理和演算子

季節の判定

上の演算子2つを利用して季節(月)を判定するプログラムを作りましょう。

//Season.java
//読み込んだ月の季節を表示
import java.util.Scanner;

public class Season {
    public static void main(String[] args){
        Scanner stdIn = new Scanner(System.in);

        System.out.print("季節を求めます。\n何月ですか:");
        int month = stdIn.nextInt();
        if(month >= 3 && month <= 5)
            System.out.println("その季節は春です。");
        else if(month >= 6 && month <= 8) 
            System.out.println("その季節は夏です。");
        else if(month >= 9 && month <= 11) 
            System.out.println("その季節は秋です。");
        else if(month >= 12 || month == 1 || month == 2 ) 
            System.out.println("その季節は冬です。");
        stdIn.close();
    }
Season.java実行結果
春・夏・秋の判定

&&を用いて、以下の要領で判定します。

  • monthが3以上かつmonthが5以下…春
  • monthが6以上かつmonthが8以下…夏
  • monthが9以上かつmonthが11以下…秋
冬の判定

冬の判定を用いるには、||を利用する必要があります。以下の要領で判定しています。

  • monthが12か1か2…冬
短絡評価

季節が春の際には以下のように記述しました。

month >= 3 && month <= 5

この判定の際に左オペランドのmonth >= 3がfalseとなった場合、右のオペランドは実行しなくてもfalseとなることが分かります。このように論理演算の式全体の評価結果が、左オペランドの評価結果のみで明確になる場合に、右オペランドが評価されないことを、短絡評価(short circuit evaluation)と呼びます。

条件演算子

2つの値を読み込んで小さい方の値を表示するプログラムを以下に示します。

//Min2.java
//読み込んだ2つの整数値の小さい方の値を表示(if文)
import java.util.Scanner;

public class Min2 {
    public static void main(String[] args){
        Scanner stdIn = new Scanner(System.in);

        System.out.print("整数a:");
        int a = stdIn.nextInt();
        System.out.print("整数b:");
        int b = stdIn.nextInt();

        int min; //小さい方の値
        if(a < b)
            min = a;
        else  
            min = b;
        System.out.println("小さい値は" + min + "です。");
        stdIn.close();
    }    
}
Min2.java実行結果

変数a、bに読み込んだ値を比較して、aの方がbより小さければ変数minにaを代入し、そうでなければ変数minにbを代入します。その結果、if文の終了時に変数minには小さい値が入ることになります。

条件演算子

上のプログラムは、if文を用いずに条件演算子(conditional operator)で実現できます。

//Min2Cond.java
//読み込んだ2つの整数値の小さい方の値を表示(条件演算子)
import java.util.Scanner;

public class Min2Cond {
    public static void main(String[] args){
        Scanner stdIn = new Scanner(System.in);

        System.out.print("整数a:");
        int a = stdIn.nextInt();
        System.out.print("整数b:");
        int b = stdIn.nextInt();

        int min = a < b ? a : b; //小さい方の値 
        System.out.println("小さい値は" + min + "です。");
        stdIn.close();
    }    
}
Min2Cond.java実行結果

条件式は、if文を凝縮したようなもので、Javaのプログラミングで好んで使われます。

x ? y : zxがtrueであればyを評価した値を、そうでなければzを評価した値を生成します。
条件演算子

三値の最大値

以下に示すのは、3つの変数a,b,cに整数値を読み込んで、その最大値を求めて表示するプログラムになります。

//Max3.java
//3つの整数値の最大値を求める
import java.util.Scanner;

public class Max3 {
    public static void main(String[] args){
        Scanner stdIn = new Scanner(System.in);

        System.out.print("整数a:");
        int a = stdIn.nextInt();
        System.out.print("整数b:");
        int b = stdIn.nextInt();
        System.out.print("整数c:");
        int c = stdIn.nextInt();

        int max = a; //小さい方の値
        if(b > max)max = b;
        if(c > max)max = c; 
        System.out.println("最大値は" + max + "です。");
        stdIn.close();
    }   
}
Max3.java実行結果

三値の最大値を求める手段は、以下のようになっています。

  1. maxをaの値で初期化する
  2. bの値がmaxよりも大きければ、maxにbの値を代入する。
  3. cの値がmaxよりも大きければ、maxにcの値を代入する。

このように処理の流れを定義した規則をアルゴリズム(algorithm)と呼びます。

ブロック

以下に2つの整数値を読み込んで、小さい方の値と大きい方の値の両方を求めることにしたプログラムを示します。

//MinMax.java
//2つの整数値の大小比較表示
import java.util.Scanner;

public class MinMax {
    public static void main(String[] args){
        Scanner stdIn = new Scanner(System.in);

        System.out.print("整数a:");
        int a = stdIn.nextInt();
        System.out.print("整数b:");
        int b = stdIn.nextInt();

        int min, max; 
        if(a < b){
            min = a;
            max = b;
        }else{
            min = b;
            max = a;
        }
        
        System.out.println("小さい値は" + min + "です。");
        System.out.println("大きい値は" + max + "です。");
        stdIn.close();
    }   
}
MinMax.java実行結果

このプログラムのif文は、aがbより小さければ、

{
min = a; max = b;
}

を実行し、そうでなければ次を実行します。

{
min = b; max = a;
}

いずれも、{ }で囲まれたており、このように囲んだものをブロック(block)と呼びます。

二値のソート

以下に示すのは、2つの変数a,bに整数値を読み込んで、昇順(小さい順)にソートする(sort:並べ替える)プログラムです。

//Sort2.java
//2つの変数を昇順にソート
import java.util.Scanner;

public class Sort2 {
    public static void main(String[] args){
        Scanner stdIn = new Scanner(System.in);

        System.out.print("整数a:");
        int a = stdIn.nextInt();
        System.out.print("整数b:");
        int b = stdIn.nextInt();

        if(a > b){
            int t = a;
            a = b;
            b = t;
        }
        System.out.println("小さい値から順に" + a + "、" + b + "です。");
        stdIn.close();
    }   
}
Sort2.java実行結果

ソートの手順は以下のようになっています。

  • aの値がbより大きい時…aとbの値を交換する
  • そうでないとき…何もしない(そのまま)
二値の交換

ブロック内で行っている手順は以下のようになります。

  1. aの値をtに保存しておく。
  2. bの値をaに代入する。
  3. tに保存しておいた最初のaの値をbに代入する。

この3つのステップで交換が完了します。

カテゴリー
Java

Java(Step3-1-1)

プログラムの流れと分岐

if文

ある条件が成立するかどうかによって、行うべき処理を決定するのがif文になります。

if – then 文

キーボードから数値を読み込んで、その値が0より大きければ、「その値は正です。」と表示するプログラムを作りましょう。

//Positive.java
//読み込んだ整数値の符号判定
import java.util.Scanner;

public class Positive {
    public static void main(String[] args){
        Scanner stdIn = new Scanner(System.in);

        System.out.print("整数値:");
        int n = stdIn.nextInt();
        if(n > 0)
        System.out.println("その値は正です。");
//n > 0がtrueのときに実行される
        stdIn.close();
    }
}
Positive.java実行結果

変数nに読み込んだ値を判定する部分が、if 文(if statement)と呼ばれ、その構文は、以下のようになっています。

if (式) 文

これは、if文の一種である if – then 文です。先頭のifは、「もしも~」という意味で、の値を調べて、その条件に一致する時(真)となったときにのみが実行されます。これからの説明では、条件判定のための制御式と呼ぶことにします。

if文の制御式n > 0で利用している > は、左オペランドが右オペランドより大きければ true(真)、そうでなければ false(偽)を生成する演算子になります。この2つは理論値リテラル(boolean literal)と呼ばれる論理(boolean)型のリテラルになります。

関係演算子

演算子 > のように、オペランドの大小関係を判定する演算子を、関係演算子(relational operator)と呼びます。関係演算子には、以下の4種類があります。

x < yxがyより小さければ true、そうでなければ false を生成
x > yxがyより大きければ true、そうでなければ false を生成
x <= yxがyより小さいか等しければ true、そうでなければ false を生成
x >= yxがyより大きいか等しければ true、そうでなければ false を生成
関係演算子

if – then – else文

前のプログラムでは、正でない値を読み込むと何も表示しません。正でない場合には、「その値は0か負です。」と表示するように変更しましょう。

//PositiveNot.java
//読み込んだ整数値の符号判定
import java.util.Scanner;

public class PositiveNot {
    public static void main(String[] args){
        Scanner stdIn = new Scanner(System.in);

        System.out.print("整数値:");
        int n = stdIn.nextInt();
        if(n > 0)
            System.out.println("その値は正です。");
        else
            System.out.println("その値は0か負です。");
        stdIn.close();
    }
}
PositiveNot.java実行結果

このプログラミングのif文は、以下の構文をもちます。

if (式) 文 else 文

もちろんelseは「~でなければ」という意味を持ちます。制御式の値がtrueならば先頭側のを実行し、falseであれば、末尾側のを実行します。そのため、nが正であるかで異なる処理が実行されます。

等価演算子

キーボードから読み込んだ2つの整数値が等しいかどうか判定して表示するプログラムを作りましょう。

//Equal.java
//読み込んだ2つの整数値が等しいか判別
import java.util.Scanner;

public class Equal {
    public static void main(String[] args){
        Scanner stdIn = new Scanner(System.in);

        System.out.print("整数a:");
        int a = stdIn.nextInt();
        System.out.print("整数b:");
        int b = stdIn.nextInt();

        if(a == b)
            System.out.println("2つの値は等しいです。");
        else
            System.out.println("2つの値は等しくありません。");
        stdIn.close();
    }
}
Equal.java実行結果

変数aと変数bに値を読み込んで、それらの値の等価性を判断します。if文の制御式で利用している、==は、左右のオペランドが等しいかどうかを判断します。これを等価演算子(equality operator)と呼びます。また、等しくないかどうか判断する!=もあります。

x == yxとyが等しければtrueを、そうでなければfalseを生成
x != yxとyが等し毛羽trueを、そうでなければfalseを生成
等価演算子

論理補数演算子

以下に示しているのは、キーボードから読み込んだ値が0であるかどうかを判定して表示するプログラムになります。

//Zero.java
//読み込んだ整数値が0か判別
import java.util.Scanner;

public class Zero {
    public static void main(String[] args){
        Scanner stdIn = new Scanner(System.in);

        System.out.print("整数値:");
        int n = stdIn.nextInt();

        if(!(n != 0))
            System.out.println("その値は0です。");
        else
            System.out.println("その値は0ではありません。");
        stdIn.close();
    }    
}
Zero.java実行結果

単項演算子!は、論理補数演算子(logical complement operator)です。オペランドの値がfalseであれば、trueを生成し、trueであれば、falseを生成します。

!xxがfalseであれば、trueを、trueであれば、falseを生成
論理補数演算子

入れ子となったif文

以下は、キーボードから読み込んだ整数値の符号を判定して表示するプログラムです。

//Sign.java
//読み込んだ整数値の符号(正/負/0)を判別
import java.util.Scanner;

public class Sign {
    public static void main(String[] args){
        Scanner stdIn = new Scanner(System.in);

        System.out.print("整数値:");
        int n = stdIn.nextInt();
        if(n > 0)
            System.out.println("その値は正です。");
        else if(n < 0)
            System.out.println("その値は負です。");
        else
            System.out.println("その値は0です。");
        stdIn.close();
    }
}
Sign.java実行結果

このプログラムには、else if… とありますが、そのような構文が特別に用意されているわけではないです。elseが制御する文は、当然if文でもかまいません。

入れ子のif文を利用した別のプログラムの例を以下に示します。読み込んだ整数値の符号が正であれば、偶数/奇数のいずれかであるかを表示します。

//EvenOdd.java
//読み込んだ値が偶数か奇数か判別
import java.util.Scanner;

public class EvenOdd {
    public static void main(String[] args){
        Scanner stdIn = new Scanner(System.in);

        System.out.print("整数値:");
        int n = stdIn.nextInt();
        if(n > 0)
            if(n % 2 == 0)
                System.out.println("その値は偶数です。");
            else
            System.out.println("その値は奇数です。");
        else
            System.out.println("正の値ではありません。");
        stdIn.close();
    }
}
Sign.java実行結果

式と評価

これまでに、(expression)という用語を何度か使いましたが、式は以下のものの総称になります。

  • 変数
  • リテラル
  • 変数やリテラルを演算子で結合したもの

以下の式を例に考えましょう。

abc + 32

変数abc、整数リテラル32、それらを+演算子で結んだ abc + 32 のいずれも式になります。○○演算子によって結合された式のことを、○○式と呼びます。

評価

式には、基本的にがあります。その値は、プログラム実行時に調べられます。式の値を調べることを評価(evaluation)といいます。

評価のイメージを具体的にしたのが次の図です。

式と評価

ここで、変数abcは、int型で値が50であるとします。abc、100、abc + 100はいずれも式です。変数abcの値が100なので、それぞれの式を評価した値は50、100、150になります。

カテゴリー
Java

Java(Step2-2)

変数を使おう②

キーボードからの入力

変数を使うことの最大のメリットは、自由に値を入れたり出したりできることです。

外部コンソール設定

前回までは、デバックコンソールに実行結果は出力していましたが、これでは、キーボードからの入力を受け付けることができません。そのため、「launch.json」ファイルでコンソールの設定を変える必要があります。以下のように記述を変更または追記し、再設定しましょう。

"console": "externalTerminal"

すると、デバックを実行すると外部のコンソールに出力されます。

キーボードからの入力

キーボードからの2つの整数値を読み込んで、それらに加算、減算、乗算、除算を行った結果を表示しましょう。コードは以下に記します。

//ArthInt.java
//2つの整数値を読み込んで加減乗除した値を表示
import java.util.Scanner;

public class ArithInt {
    public static void main(String[] args){
        Scanner stdIn = new Scanner(System.in);
        System.out.println("xとyを加減乗除します");

        System.out.print("xの値:"); //xの値を入力
        int x = stdIn.nextInt(); //xに整数値を読み込む
        System.out.print("yの値:"); //yの値を入力
        int y = stdIn.nextInt(); //yに整数値を読み込む

        System.out.println("x + y = " + (x + y));
        System.out.println("x - y = " + (x - y));
        System.out.println("x * y = " + (x * y));
        System.out.println("x % y = " + (x % y));
        stdIn.close();
    }
}
ArthInt.java実行結果

キーボードからの読み込みにはいくつかの手順があるので、順を追って説明していきます。現時点では、こういう記述をするんだということを覚えておくだけで大丈夫です。

  1. プログラムの先頭に「import java.util.Scanner;」をプログラムの先頭(クラス宣言前に)置きましょう。
  2. mainメソッドの先頭に「Scanner stdIn = new Scanner(System.in);」を記述します。System.inは、キーボードと結びつく標準入力ストリーム(standard input stream)になります。
  3. キーボードからの読み込みを行う部分として「stdIn.nextInt();」を記述しましょう。このプログラムではint型整数値を読み込むように設定しています。

演算子とオペランド

今回のプログラムでも使っている演算を行う + や – などの記号を演算子(operator) と呼びます。演算の対象となる式をオペランド(operand)と呼びます。

たとえば、xとyを求める式x + yにおいて、演算子は + であり、オペランドは、x、yの2つになります。このように2つのオペランドを持つ演算子を2項演算子(binary operator)と呼ばれます。それ以外にも、オペランドが1つの単項演算子(unary operator)、3つの3項演算子(ternary operator)があります。

x + y
x – y
加減演算子(additive operator)
x * y
x / y
x % y
乗除演算子(multiplicative operator)
+x
-y
単項符号演算子(unary plus operator and unary minus operator)

単項保符号演算子を使ったプログラムの例は以下のようになります。

//Minus.java
//整数値を読み込んで符号を反転した値を表示
import java.util.Scanner;

public class Minus {
    public static void main(String[] args){
        Scanner stdIn = new Scanner(System.in);

        System.out.print("整数値:");
        int a = stdIn.nextInt(); //aに整数値を読み込む
        int b = -a; //aの符号を反転した値でbを初期化
        System.out.println(a + "の符号を反転した値は" + b + "です。");
        stdIn.close();
    }
}
Minus.java実行結果

基本型

ここまでのプログラムでは、int型の変数を使ってきました。Javaでは、多くの型があり、自分で型を作ることもできます。Javaで標準でサポートしている型を基本型(primitive type)と呼びます。以下に例を記しておきます。

整数型

整数を表し、代表的なのは以下の4つです。型によって表現できる数値の範囲が異なります。

  • byte…1バイト整数 -128 ~ 127
  • short…短い整数 -32,768 ~ 32,767
  • int…整数 -2,147,483,648 ~ 2,147,483,647
  • long…長い整数 -9,223,372,036,854,775,808 ~ 9,223,372,036,854,775,807
浮動小数点型

実数を表し、2つの型があります。

  • float…単精度浮動小数点数 ±3.40282347E+38 ~ ±1.40239846E-45
  • double…倍精度浮動小数点数 ±1.79769313486231507E+378 ~ ±4.9406564841246544E-324

実数の内部は浮動小数点数(floating point number)という形式で表現されます。また、3.14とか13.5といっ定数値は、浮動小数点リテラル(floating point literal)と呼びます。

この他に文字型(char)と論理型(boolean)がありますが、後のページで説明します。

実数値の読み込み

2つの実数値を加減乗除するプログラムを作りましょう。今回は実数を扱うdouble型を使って見ましょう。

//ArthDouble.java
//2つの実数値を読み込んで加減乗除した値を表示
import java.util.Scanner;

public class ArithDouble {
    public static void main(String[] args){
        Scanner stdIn = new Scanner(System.in);
        System.out.println("xとyを加減乗除します");

        System.out.print("xの値:"); //xの値を入力
        double x = stdIn.nextDouble(); //xに実数値を読み込む
        System.out.print("yの値:"); //yの値を入力
        double y = stdIn.nextDouble(); //yに実数値を読み込む

        System.out.println("x + y = " + (x + y));
        System.out.println("x - y = " + (x - y));
        System.out.println("x * y = " + (x * y));
        System.out.println("x % y = " + (x % y));
        stdIn.close();
    }
}
ArthDouble.java実行結果

注意点としては、double型の実数値を読み込むには、nextInt()ではなく、nextDouble()を使わなければいけないです。

fainal変数

次に、円の半径をキーボードから読み込んで、その円の円周の長さと面積を求めて表示するプログラムを作りましょう。

//Circle1.java
//円周の長さと円の面積を求める
import java.util.Scanner;

public class Circle1 {
    
    public static void main(String[] args){
        Scanner stdIn = new Scanner(System.in);

        System.out.print("半径:");
        double r = stdIn.nextDouble();

        System.out.println("円周の長さは" + 2 * 3.14 * r + "です。");
        System.out.println("面積は" + 3.14 * r * r + "です。");
        stdIn.close();
    }    
}
Circle1.java実行結果

円周率は3.14ではなく、無限に続く数値です。プログラム中に複数3.14を使っている箇所が場合によっては選択的な置換が要求されることもあります。そこで、効力を発揮するのが、値を書き換えることのできないfinal変数になります。次のプログラムはそれを使って書き換えたものになります。

//Circle2.java
//円周の長さと円の面積を求める
import java.util.Scanner;

public class Circle2 {
    public static void main(String[] args){
        final double PI = 3.1416;
        Scanner stdIn = new Scanner(System.in);

        System.out.print("半径:");
        double r = stdIn.nextDouble();

        System.out.println("円周の長さは" + 2 * PI * r + "です。");
        System.out.println("面積は" + PI * r * r + "です。");
        stdIn.close();
    }
}
Circle2.java実行結果

final変数を使うメリットは、以下の通りです。

  • 値の管理を一か所に集約できる

円周率の値3.1416は、final変数PIの初期化子となっています。もし、他の値に変える場合は、この一か所だけで済みます。

  • プログラムが読みやすくなる

プログラムの中では、数値ではなく変数名PIで円周率を参照できるので、プログラムが読みやすくなります。

また、final変数の名前は大文字とすることが推奨されています。普通の変数と見分けやすくするためです。加えて、初期化するのが原則です。

乱数の生成

キーボードから値を読みこむのではなく、コンピュータに値を作ってもらうことができます。以下のプログラムは、0~9までの数値から1つランダムに生成して表示しています。

//LuckyNo.java
//0~9のラッキーナンバーを乱数で作成
import java.util.Random;

public class LuckyNo {
    public static void main(String[] args){
        Random rand = new Random();

        int lucky = rand.nextInt(10); //0~9の乱数
        System.out.println("今日のラッキーNo." + lucky);

    }
}
LuckyNo.java実行結果

コンピュータがランダムに生成する値のことを乱数と言います。いくつかの手順があるので、順を追って説明していきます。

  1. プログラムの先頭に「import java.util.Random;」をプログラムの先頭(クラス宣言前に)置きましょう。
  2. mainメソッドの先頭に「Random rand = new Random();」を記述します。
  3. 「rand.nextInt(n);」を記述し、値の範囲を決めましょう。()内に入力した数値は、0以上n未満の数値になります。したがった、今回はnを10として値の範囲を0以上9以下で実現しています。

文字列の読み込み

ここまでは、数値を扱ってきましたが、文字列を扱うプログラムを作ってみましょう。名前を入力させて、それに対する挨拶を表示するようにしましょう。

//HelloNext.java
//名前を読み込んで挨拶する1
import java.util.Scanner;

public class HelloNext {
    public static void main(String[] args){
        Scanner stdIn = new Scanner(System.in);

        System.out.print("お名前は:");
        String s = stdIn.next(); //文字列を読み込む
        System.out.println("Hello" + s + "さん");
        stdIn.close();
    }    
}
HelloNext.java実行結果

組み込んだ文字列を格納する変数sの型は、String型になります。これは文字列を表すための型です。ただし、このプログラムでは、空白文字やタブ文字が文字列の区切りとみなされます。そのため、1行分の文字列入力を可能にするには、以下のようにnextLine()を使わなければいけません。

//HelloNextLine.java
//名前を読み込んで挨拶する2
import java.util.Scanner;

public class HelloNextLine {
    public static void main(String[] args){
        Scanner stdIn = new Scanner(System.in);

        System.out.print("お名前は:");
        String s = stdIn.nextLine(); //一行分の文字列読み込み
        System.out.println("Hello" + s + "さん");
        stdIn.close();
    }
}
HelloNextLine.java実行結果

文字列s1は、”ABC”で初期化され、その後”DEF”で代入されます。したがって、s1は”ABC”から”DEF”に変更されます。

以上で、キーボードからの読み込みが終わったので、次からはプログラムの流れの分岐を学んでいきましょう。

カテゴリー
Java

Java(Step2-1)

変数を使おう①

足し算や掛け算などの計算ができるプログラムを作成しながら、変数について学んでいきましょう。

変数

演算結果の出力

まずは、単純な結果を表示するプログラムを作ります。以下のコードを記述してみましょう。

//Sum1.java
//2つの整数値の和を表示

class Sum1{
    public static void main(String[] args){
        System.out.println(50 + 100);
    }
}
Sum1.java実行結果
数値の出力

System.outに続く、()の中に注目しましょう。50+100の演算結果が150となるプログラムです。前回のプログラムでは文字列を表示していましたが、整数値の表示を行っています。

整数のリテラル

100や50のような、整数を表す定数のことを整数リテラル(integer literal)と呼びます。100と書けば整数リテラル、”100″と書けば文字列リテラルになります。

文字列と数値の連結

先ほどの整数リテラルのプログラムに文字列を繋げたプログラムに改良してみましょう。以下にコードを記述しておきます。

//Sum2.java
//2つの整数値の和を表示

public class Sum2 {
    public static void main(String[] args){
        System.out.println("実行結果:"+(50 + 100));
    }
}
Sum2.java実行結果

処理の流れは以下のようになります。

  1. ()で囲まれた50+100の演算が行われます。()で囲まれた演算が優先的になるのは、日常での数学のルールと同じになります。
  2. 演算結果150が、文字列”150″として変換されます。
  3. 文字列 “実行結果:”と”150″が連結されます。そして、画面に表示されます。

もし、この(50+100)から括弧を取り除いたら、どうなるでしょうか。以下のプログラムを実行してみましょう。

//Sum3.java
//2つの整数値の和を表示(誤り)

public class Sum3 {
    public static void main(String[] args){
        System.out.println("50 + 100 =" + 50 + 100);
    }
}
Sum3.java実行結果

実行すると、50+100の和が50100になってしまいます。文字列の連結や数値の加算を行う+は、左から順に演算を行います。そのため、このプログラムでは、文字列”50+100=”に50という数値を文字列として”50+100=50″にしてから、100を”100″として連結しています。

加算の式で括弧を使わない場合は、以下のようにプログラムを書きます。

//Sum4.java
//2つの整数値の和を表示

public class Sum4 {
    public static void main(String[] args){
        System.out.println(50 + 100 + "は50と100の和です");
    }
}

加算の式で括弧を書かずとも記述できますが、完全に括弧を省略してしまうと、読みにくくなっていしまいます。プログラムに応じて適せん、使い分けていきましょう。

変数

これまでのプログラムでは、50と100の数値以外の和を求めることができません。そこで、値を自由に出し入れできる変数(variable)を使うと、色々なプログラムに対応できます。

変数の宣言

変数とは、値を格納する箱のような役割を持ちます。一度、値を入れておけば、その箱があるかぎり値が保持されます。また、値の書き換えや取り出しも自由に行えます。

プログラム中には、複数の変数を設定することができます。どれがどの変数なのか分けるために名前を与えます。これを変数の宣言と言います。この宣言によって、値を入れる箱を作り、何という箱なのか設定します。以下のようにコードで変数を宣言するものを宣言文(declaration statement)と言います。

 int x;  //xという名前のint型の変数の宣言

intは「整数」という意味のintegerからきています。この宣言でxという名の箱が作られます。変数xが扱えるのは、「整数」だけになります。intは(type)の1つで、文字や実数など別の値を入れたいときは、別の型を使わなければなりません。型の設定も宣言する際に重要になります。

変数をいれたプログラムは以下のように書くことができます。

//Variable.java
//変数に値を代入して表示
public class Variable {
   
    public static void main(String[] args){
        int x;  //xはint型の変数
        x = 100;  //xに100を代入
        System.out.println(x); //xの値を表示
    }
}
Variable.java実行結果
代入演算子

上のコードでは、変数xに100の値を代入していますが、=の部分は代入するための記号で、代入演算子(assignment operator)と呼ばれます。数学のようにxと100は等しいという意味ではないので、注意しましょう。

変数の値の表示

変数に格納されている値はいつでも取り出すことができます。

System.out.println(x); //xの値を表示

表示されるのは、xの値で変数名を表示するわけではないので、気をつけましょう。

次に、複数の変数を使ったプログラムに挑戦してみましょう。以下に示すのは2つの値の合計と平均を表示するプログラムです。

//SumAve1.java
//2つの変数xとyの合計と平均を表示

public class SumAve1 {
    
    public static void main(String[] args){
        int x;
        int y;

        x = 100;
        y = 50;

        System.out.println("xの値は" + x);
        System.out.println("yの値は" + y);
        System.out.println("合計は" + (x + y));
        System.out.println("平均は" + (x + y) / 2);
    }
}
SumAve1.java実行結果

上のコードでは、intxとyを別々に宣言していますが、以下のようにまとめることもできます。

int x,y;

しかし、1行ずつ宣言した方が、個々に扱えるので宣言の追加や削除も容易になります。

初期化を伴う宣言

変数に入れるべき値が分かっているなら、最初から変数に入れておくことも可能です。そのように修正したプログラムが次のようになります。最初に値を入れる事を初期化(initialize)と言います。また、その際に入れた値を初期化子(initializer)と呼びます。

//SumAve3.java
//2つの変数xとyの合計と平均を表示(変数初期化)

public class SumAve3 {
    public static void main(String[] args){
        int x = 100;
        int y = 50;

        System.out.println("xの値は" + x);
        System.out.println("yの値は" + y);
        System.out.println("合計は" + (x + y));
        System.out.println("平均は" + (x + y) / 2);
    }
}
初期化と代入

プログラムで行っている初期化と代入は、値を入れるという点では同じですが、タイミングが異なります。以下のように理解しましょう。

  • 初期化:変数を生成する時に値を入れる事
  • 代入:生成済みの変数に値を入れる事

次からはキーボードからの入力に取り組んでいきましょう。

カテゴリー
Java

Java(Step1-2)

画面に文字を表示しよう

Javaについて

Javaの誕生

1991年ごろにアメリカのSun Microsystems社が、家電製品用ソフトウェアの開発の為にプログラミング言語が作られ、改良が重ねられ、Javaになりました。注目された理由は、Webブラウザ上で動作する「アプレット」という小規模なプログラム開発ができたことでした。

Javaの特徴

  • 無料で提供される…Javaの開発ツールは無料で提供され、開発環境を準備しやすいです。
  • 一度作成すれば、どこでも実行できる…一般的には、プログラミング言語で作成したプログラムは、特定の機器や環境でのみ動作しますが、Javaで作成したプログラムは動作環境が整っていれば、どこでも動きます。
  • C言語やC++に似た構文…Javaの文法体系は、C言語やC++を参考に作られているので、それらの言語を経験していればとっつきやすいです。
  • 強い型付け…プログラムでは、整数、実数、文字などの多くのデータ型を扱います。各種の演算において、厳密に開発ツールでチェックされるので、信頼性の高いプログラムが作りやすいです。
  • オブジェクト指向プログラミングのサポート…クラスによるカプセル化、継承、多相性といったオブジェクト指向プログラミングを実現する技術がサポートされています。
  • 複数のライブラリ…Javaでは基本の機能がAPIとして多数、提供されているので、目的の処理を簡単に行うことが可能です。
  • ガーベジコレクションによる記憶管理…Javaでは、不要になったオブジェクトの開放処理が自動的に行われるので、オブジェクトの管理が簡単になります。
  • 例外処理… 予期せぬエラーなどの例外的な状況に遭遇した時の処理を、スムーズに行えるようになっているので、頑丈なプログラム開発ができます。
  • 並行処理…1つのプログラム内で、複数の処理を同時に実行できます。
  • パッケージによるクラスの分類…Javaのクラスをパッケージごとに分類でき、膨大な数のクラスを効率よく管理できます。

Javaの発展

Javaは、頻繁にバージョンアップを重ねており、開発容易性(EoD)を重視しています。特にバージョン1.2と5.0(1.5)では、文法体形が大きく変わり、沢山の機能が加わりました。

文字の出力

Step1-1で環境設定が済んでいるのなら、プログラムを作成して確認してみましょう。

プログラムの作成と実行

最初に作るのは、コンソール画面に文字を表示するプログラムになります。「Test.java」ファイルを作成し以下のようにソースを入力して見ましょう。

//画面への出力を行うプログラム

public class Test {
    public static void main(String[] args) {
        System.out.println("初めてのプログラム");
        System.out.println("Hello, World!");
    }
}

実行すると、次のようにコンソールに文字列が出力されます。

※プログラム中の余白や「”」などの記号は全角文字で打ち込まないように気を付けましょう。余白の部分は、スペース・タブ・エンターキーを用いて打ち込みます。

ソースプログラムとソースファイル

プログラムは文字の並びとして作成し、そのようなプログラムをソースプログラムと呼び、ソースプログラムを格納したファイルのことをソースファイルと呼びます。

ソースファイルは、classの後ろに書かれているクラスの名前(このプログラムではTest)に拡張子.javaを加えた名前とするのが原則です。したがって、ソースファイルの名前は、Test.javaとなります。

プログラムのコンパイルと実行

ソースプログラムを作成してもそのままでは実行できないので、2つの手順を実行する必要があります。

1.コンパイル

コンパイル(compile)とは、そのままでは実行できないソースプログラムを実行できる形式に変える作業になります。(バイトコードを生成する)

2.実行

コンパイルに成功したら、「.class」の拡張しを持つファイルが生成されるます。このファイルから、クラスを読み込んで実行します。

コメント(注釈)

先ほど、記述したプログラムに注目していきましょう。

// 画面への出力を行うプログラム

先頭にある連続する2個のスラッシュ記号「//」は、プログラムそのものではなく、プログラムに対してのコメント(comment)になります。コメントの内容はプログラム動作に影響を与えません。ここには、プログラムの読み手に伝えたいことを簡潔に記述しましょう。

コメントの記述方法は以下の3つがあります。

1.伝統的コメント(traditional comment)

コメントを「/*」と「*/」で囲みます。

/* 画面への出力を行うプログラム */

複数行にわたるコメントの記述に効果的な方法です。なぜ、伝統的かというと、C言語のコメント形式と同じで古くから使われているからです。

2.文書化コメント(documentation comment)

コメントを「/**」と「*/」で囲みます。

/** 画面への出力を行うプログラム */

伝統的コメントと同様に、複数行にわたってコメントが書けます。この形式のコメントから、プログラムの仕様書となるドキュメントを作成できます。

3.行末コメント(end of line comment)

「//」から、その行の末端までがコメントになります。

// 画面への出力を行うプログラム

複数行にわたってコメントできないので、短いコメントの記述に使います。

プログラムの構造

次にコメント以外のプログラム本体部分に注目していきましょう。

クラス宣言

上の図の青い部分はプログラム全体の骨組みになります。クラスという骨組みを宣言するということです。以下のように書くと覚えておけば、大丈夫です。

class クラス名{
    // mainメソッド他
}

クラス名の先頭文字は、大文字が基本となります。また、ソースファイルの名前は、大文字・小文字の区別を含めてクラス名と同一でないといけません。

mainメソッド

上の図の白い部分は、mainメソッドの宣言になります。「public static void…」の部分は後ほど説明しますが、この部分を決まり文句として覚えましょう。

public static void main(String[] args){
     // 行うべき処理
}

プログラムを起動して実行すると、mainメソッド中の(statement)が順に実行されます。

重要なことは以下の2つです。

  • Javaプログラムの本体はmainメソッドで、プログラム実行時には、文が上から順に実行される
  • 文は原則、セミコロンで終わる

文字列リテラル

コンソール画面に出力を行う文に注目しましょう。

 System.out.println("初めてのプログラム");
 System.out.println("Hello, World!");

最初に「初めてのプログラム」と「Hello, World!」に着目します。二重引用符「””」で囲んだ文字の並びを文字列リテラル(string literal)と呼びます。リテラルとは「文字通りの」という意味で、例えば文字列リテラル”あいうえお”は5個の文字の並びとして表されます。

コンソール画面への出力とストリーム

コンソール画面を含め、外部との入出力にはストリーム(stream)を利用します。ストリームとは文字が流れる川のようなものになります。

「System.out」は、コンソール画面と結びつくストリームであって、標準出力ストリーム(standard output stream)と呼ばれます。続く、「println」は、()内の内容を表示した後に改行を行います。図で表すと以下のようになります。

「println」のlnは、lineの略で行を表します。ただのprintでは、改行が行われません。このような依頼された処理を行うprintやprintlnは、プログラムの部品になります。これらをメソッド(method)と呼びます。

文字列の連結

複数の文字列リテラルを「+」で結んだら、連結されます。そのことをを利用して前のプログラムを書き直すと以下のようになります。

//画面への出力を行うプログラム

public class Test {
    public static void main(String[] args) {
        System.out.println("初めてのプログラム" + "Hello, World!");
    }
}

長くて一行に文字列の表示などには+を挟むことでわかりやすく記述できます。

改行

文字列リテラルには、改行文字を示す表記「\n」を埋め込むことができます。パソコンによっては、バックスラッシュ(\)が円記号(¥)として表示されることもありますがプログラムでは、別の文字として扱われます。以下のように記述します。

public class Test{
  public static void main(String[] args) {
    System.out.println("こんにちは\nJava!!");
  }
}
記号文字の読み方

他にもJavaのプログラムで利用する記号文字があるので、以下に記載しておきます。

記号読み方
+プラス符号 プラス たす
マイナス符号 マイナス ひく ハイフン
*アスタリスク かけ こめ
/スラッシュ
$ドル ダラー
%パーセント
.ピリオド ドット 小数点文字
,コンマ カンマ
:コロン ダブルドット
;セミコロン
一重引用符 シングルクォーテーション
二重引用符 ダブルクォーテーション
(左括弧 パーレン
)右括弧 パーレン
{左波括弧 ブレイス
}右波括弧 ブレイス
[左角括弧 ブラケット
]右角括弧 ブラケット
<小なり 左向き不等号
>大なり 右向き不等号
?疑問符 ハテナ クエスチョン
!感嘆符 ビックリ エクスクラメーション
&アンド アンパサンド
~チルダ ※JISコードでは、オーバーライン
オーバーライン 上線 アッパーライン
^アクサンシルコンフレックス ハット
#シャープ ナンバー
_アンダーライン 下線 アンダーバー
=等号 イコール
|縦線
バックスラッシュ ※JISコードでは¥
\円記号 円マーク

自由形式記述

まずは、以下のコードを見てください。実行結果は同じですが、読みにくいと思います。

 public class 
Test{
    public static
 void main(String[] 
  args) {
    System   .   out.
println("こんにちは\nJava!!");
  }
}

一部のプログラミング言語は、「プログラムの各行を、決められた桁位置から記述しないといけない」などの制約があります。しかし、Javaプログラムは制約を受けません。それは、自由形式(free formatted)が許されてるからです。ただ、若干の制限もあります。

  • 単語の途中にホワイトスペースを入れてはいけない
  • 文字列リテラルの途中で改行してはいけない

インデント

プログラムの構造を掴みやすくするためには、記述の際に読みやすくする必要があります。文を段落で管理するためにインデントを用います。文の左側に設ける余白をインデントと呼び、これを用いた記述をインデンテーション(段付けする、字下げする)と言います。