選択(selection)

代入演算子(assignment operator)

int a = 13;
と書くと,aという変数名がついた箱の中に13という整数値が記録されます.図で表すと
\begin{figure}\centering\includegraphics[width=1.8cm]{CPPPIC/pic3-1.eps}
\end{figure}
のような感じです.

このとき用いた"="は代入演算子とよばれ,代入記号の右側の値を左側の変数に代入することを意味します.数学の等号ではないことに注意が必要です.等号の左側に来ることができる値を左側値(lvalue)といいます.例えば,
int n;
n = 44;
は可能ですが,
44 = n;
はエラーです.

複合代入演算子(Composite Assignment Operator)

演算子 意味
+= a += b a+bをaに代入
-= a -= b a-bをaに代入
*= a *= b a*bをaに代入
/= a /= b a/bをaに代入
%= a %= b a%bをaに代入

練習問題 3..1   複合代入演算子に慣れる
a = 33, b = 44のとき,a*bの結果をaに代入し表示するプログラムを複合演算子を用いて作成しなさい.

型変換(Type Conversions)

    int n = 22;
    float x = 3.141592;
    x += n;
    System.out.println(x - 2);
において,x += n;により,整数n=22は自動的にn=22.0に変換されます.また,x - 2において,2は2.0に変換されます. このように,小さな幅の型から大きな幅の型への変換は自動的に行なわれますが,大きな型から小さな型へ変換は自動的ではありません.

一般に,Tがある型で,vが別の型の値であるとき,

(T)v

により,vは型Tに変換されます.このことをキャスト(cast)といいます.キャストは,変数もしくは定数の前につけることで型の変換を行います.
(型)変数 (型)定数
例えば,nが浮動小数点型のとき,(int)nと書くと,nは小数点以下を全て無視して整数型になります.

例題 3..1   キャスト
\framebox{
\begin{minipage}{13.65cm}
次のプログラムは{\rm double}値を{\rm int}値に{\bf キャスト}します.
\end{minipage}}

class TypeConversion
{
  public static void main(String[] args)
  {
    double t = 1345.2567;
    int n = int(t);
    System.out.println("t = " + t + ", n = " + n );
  }
}

実行結果

\begin{figure}\centering\includegraphics[width=7.8cm]{JAVAFIG/TypeConversion.eps}
\end{figure}

小さい型から大きい型への変換はプロモーション(promotion)といい,そのための演算子は何も必要としありません.

入力ストリーム(Input Streams)

キーボードからの入力(標準入力)を取り込むには,System.inという入力ストリームを用いる方法があります.System.inはInputStreamオブジェクトを指しています.その唯一のデータ入力メソッドであるread()は,バイトコード入力という基本的な機能だけを持っています.つまり,

    int idt = System.in.read();

によって,1文字読み込み,その文字コードをidtに代入します.また,複数文字読み込むには,

    byte[] bdt = new byte[80];
    int nn = System.in.read(bdt,0,80);
    String name = new String(bdt,0,nn-2);

を用います.最初の2行で,キーボードでEnterキーが押されるまで,文字列をbyte型配列bdtの先頭から格納し,実際に読み込んだ文字数をnnに代入します.残りの1行は,byte型配列bdtに格納された文字列を読み込んだ文字より2文字少なく文字列strに代入します.2文字少なくする理由は,read()メソッドで読み込んだ後,改行文字(Windows環境で,0D 0Aのペア文字)が格納されるためです.また,System.inの標準入力を用いるには,java.io.*ライブラリをインポートしなくてはなりません.ライブラリのインポートは,

import java.io.*;
で行います.

例外処理 プログラムを作成する場合,例外処理が必要な場合があります.例外処理とは「普通ではない処理」のことで,

の二つの意味を含みます.ここで,「特別な状態」とは,キーボード入力時のEnterキー入力の発生などのことで,エラーではありませんが,何かの対処を必要とするものです

そこで,この例題では,入力時のキーボード入力を検査するため,try catchの構文で「特別な状態」を捕まえる処理が必要となります.

例題 3..2   キーボードからの入力
\framebox{
\begin{minipage}{13.65cm}
コマンドラインから自分の名前を打ち込んだら次の行に''こんにちは誰々さん''と表示するプログラムを考えなさい.
\end{minipage}}

解答 キーボードから入力した名前を保存するには,配列,文字列とJavaには色々用意されています.キーボードから入力した名前はSystem.in.read(bdt,0,80);でbyte型配列bdtに格納されます.String name = new String(bdt,0,nn)でbyte型配列bdtに格納された文字をnn個文字列型変数nameに代入します. では,プログラムを作成しましょう.

import java.io.*;
class InputStream
{
  public static void main(String[] args)
  {
    byte[] bdt = new byte[80];
    try
    {
      System.out.println("名前はなんですか?");
      int nn = System.in.read(bdt,0,80);
      String name = new String(bdt,0,nn-2);
      System.out.println("こんにちは" + name + "さん");
    }
    catch(IOException ex)
    {
      System.out.println(ex);
    }
  }
}

実行結果

\begin{figure}\centering\includegraphics[width=7.8cm]{JAVAFIG/InputStream.eps}
\end{figure}

この例題では,名前をコマンドラインから入力しました.それに対して,次の例題では表示させるものをコマンドライン引数として使います. Javaのmainメソッドのargs[0]は第1引数となります.

例題 3..3   コマンドライン引数
\framebox{
\begin{minipage}{13.65cm}
自分の名前を引数として打ち込んだら次の行に''こんにちは誰々さん''と表示するプログラムを考えなさい.
\end{minipage}}

解答 main(String[] args)において第1引数は,argv[0]に代入されます.では,プログラムを作成しましょう.

class InputCommand
{
  public static void main(String[] args)
  {
    System.out.println("こんにちは" + args[0] + "さん" );
  }
}

実行するには,プログラム名の後にスペースを空けて自分の名前を打ち込んでからリターンキーを押す.

実行結果

\begin{figure}\centering\includegraphics[width=7.8cm]{JAVAFIG/InputCommand.eps}
\end{figure}

練習問題 3..2   コマンドライン引数
args[0]とargs[1]は第1引数と第2引数となります.そこで,2つの引数EnglishとMathを用いて,"好きな科目はEnglish and Mathです"と表示するプログラムを作成しなさい.

if文(if Statement) もし〜ならば〜する

\begin{figure}\centering\includegraphics[width=10.0cm]{CPPPIC/flowchart.eps}
\end{figure}

if文の記述法は次のようです.

    if (条件式) 文1;

ここで,条件式が真ならば,文1を実行する.

例題 3..4   整除可能性のテスト
\framebox{
\begin{minipage}{13.65cm}
{\rm 2つの整数をコマンドライン引数として用意し,1つがもう1つの整数で割れるか判断するプログラムを作成しなさい.}
\end{minipage}}

解答 n%dは整数nを整数dで割ったときのあまりを表すので,n%dが零ならば割り切れ,そうでないならば割り切れないとなります.また,if文の条件式はC/C++と異なり,真または偽となるようにしなけらばなりません.そこで,if(n%d == 0) System.out.println("割り切れる"); if(n%d != 0) System.out.println("割り切れない");と書くことができます.

コマンドライン引数はString型ですので,これを整数に直して用いる必要があります.Javaにはラッパークラス(wrapper class)とよばれる便利なものがあります.Integer系ラッパークラスは,1章で10進数の数を16進数に直すときに一度用いました.ここでは,数字からなる文字列を整数に直すInteger.parseInt()を用います.

class DivisibleTest
{
  public static void main(String[] args)
  {
    int first = Integer.parseInt(args[0]);
    int second = Integer.parseInt(args[1]);
    if(first%second == 0)
    {
      System.out.println(first + "は" + second + "で割り切れる");
    }
    if(first%second != 0)
    {
      System.out.println(first + "は" + second + "で割り切れない");
    }
  }
}

実行結果

\begin{figure}\centering\includegraphics[width=7.8cm]{JAVAFIG/DivisibleTest.eps}
\end{figure}

練習問題 3..3   %の用い方
%と/を用いて整数34の並びを逆にするプログラムを作成しなさい.

if文の後の中括弧{と}は,セミコロン;で終了する文が一つの時は必要ありませんが,私の美的センスで書いています.

if … else文(if else Statement) もし〜でなければ〜する

3..1   式の場合

class IfElseStatement
{
  public static void main(String[] args)
  {
    int a = 0, b = 1;
    if(a*b == 0)     {
      System.out.println("a*bは0です");
    }
    else
    {
      System.out.println("a*bは0ではありません");
    }
  }
}

実行結果

\begin{figure}\centering\includegraphics[width=7.8cm]{JAVAFIG/IfElseStatement.eps}
\end{figure}

分岐条件の組み合わせ − 論理演算子(Logical Operators)

分岐の条件は範囲の指定などのときに,複数組み合わせられる.その組み合わせには,主に論理積&&と,論理和||の演算が用いられる.

3..2   論理積(&&)の場合:xがaからbの間にある場合

class LogicalOperatorIn
{
  public static void main(String[] args)
  {
    int a = 1, b = 3, x = 2;
    if(a <= x && x <= b)
    {
      System.out.println("xはaとbの間にあります");
    }
    else
    {
      System.out.println("xはaとbの間にはない");
    }
  }
}

実行結果

\begin{figure}\centering\includegraphics[width=7.8cm]{JAVAFIG/LogicalOperatorIn.eps}
\end{figure}

3..3   論理和(||)の場合:xがa以下またはb以上にある場合

class LogicalOperator
{
  public static void main(String[] args)
  {
    int a = 1, b = 3, x = 2;
    if(a <= x || x >= b)
    {
      System.out.println("xはaとbの間にはない");
    }
    else
    {
      System.out.println("xはaとbの間にあります");
    }
  }
}

実行結果

\begin{figure}\centering\includegraphics[width=7.8cm]{JAVAFIG/LogicalOperator.eps}
\end{figure}

単純な分岐(Selection)−等価演算子,関係演算子(Comparison Operator)

単純な分岐とは,条件式に1つの式だけを使った選択構造です.

おもに式としては,等価演算子(=),関係演算子(< >)が使用されます.変数や式が単独で設定されることもあります.その場合は,その評価値が0ならば偽,0以外ならば真という判定になります.

x $<$ y // xはyより小さい
x $>$ y // xはyより大きい
x $<=$ y // xはy以下である
x $>=$ y // xはy以上である
x $==$ y // xはyと等しい
x != y // xはyと等しくない

論理演算子(Logical Operators)

コンピュータの計算は論理演算を用いて行なわれる.基本的な論理演算には,論理積(AND)論理和(OR)論理否定(NOT)排他的論理和(EOR,XOR)があります.なお,論理否定は単に否定ともいいます.

論理演算の結果をまとめたものを真理値表(truth table)といい,次のような表です.

A B 論理積 論理和 排他的論理和 論理否定
    AB A+B A B
0 0 0 0 0 1
0 1 0 1 1 1
1 0 0 1 1 0
1 1 1 1 0 0

また,排他的論理和は,論理積,論理和,否定を用いて次のように展開できます.

$\displaystyle A \oplus B = A \cdot {\bar B} + {\bar A} \cdot B$

条件式には&&(AND), $\vert\vert$(OR), !(not)の3つの論理演算子を用いることができます.真理値表より,次の結果を得る.
DeMoivreの定理
1. !(A $\vert\vert$ B) = !A && !B
2. !(A && B) = !A $\vert\vert$ !B
3. A $\vert\vert$ (B && C) = (A $\vert\vert$ B) && (A $\vert\vert$ C)
4. A && (B $\vert\vert$ C) = (A && B) $\vert\vert$ (A && C)

if文(if Statement):もし〜ならば〜する

例題 3..5   2数の比較
\framebox{
\begin{minipage}{13.65cm}
{\rm 2つの異なる数字を読み取って比較し,大きい方を求めるプログラムを({\rm if}文だけを使って)作成しなさい.}
\end{minipage}}

解答

変数aとbにコマンドライン引数を入れます.つぎに,aとbの値を比較をします.もしaがbより大きいならばmaxはaです. もしbがaより大きいならばmaxはbであるとなります.では,プログラムを作成しましょう.

class ComparisonOfTwoNumbers
{
  public static void main(String[] args)
  {
    int a = Integer.parseInt(args[0]);
    int b = Integer.parseInt(args[1]);
    int max;
    if(a > b)
    {
      max = a;
    }
    else
    {
      max = b;
    }
    System.out.println("max = " + max);
  }
}

実行結果

\begin{figure}\centering\includegraphics[width=9.3cm]{JAVAFIG/ComparisonOfTwoNumbers.eps}
\end{figure}

else-if文(else-if Construct):もし〜ならば〜し,そうでなければ〜し,それでもなければ〜する

この構文はif-elseのelseに新たに条件が加わった形です.この構文は選択条件が3つ以上あっても対処できます.

練習問題 3..4   else-if 文の例 3数の比較
3つの数字30, 10, 40を読み取って比較し,一番大きい数字を求めるプログラムを作成しなさい.

例題 3..6   うるう年の判定
\framebox{
\begin{minipage}{13.65cm}
西暦年数{\rm year}をコマンドライン引数として入力し,うるう年かを判定するプログラムを作成しなさい.
\end{minipage}}

解答 うるう年とは400で割り切れる年数.または,4で割り切れ,かつ100で割り切れない年数のことです.例えば1900年はうるう年ではありません.なぜならば,4と100の両方で割り切れてしまうからです.

これをプログラムにするには,if (year % 400 == 0)ならばうるう年.else if (year % 4 == 0 && year % 100 != 0)ならばうるう年.else うる年ではないとすればよいでしょう.ではプログラムを作成しましょう.

class LeapYear
{
  public static void main(String[] args)
  {
    int year = Integer.parseInt(args[0]);
    if(year%400 == 0)
    {
      System.out.println(year + "はうるう年です");
    }
    else if(year % 4 == 0 && year % 100 != 0)
    {
      System.out.println(year + "はうるう年です");
    }
    else
    {
      System.out.println(year + "はうるう年ではありません");
    }
  }
}

実行結果

\begin{figure}\centering
\includegraphics[width=7.8cm]{JAVAFIG/LeapYear.eps}
\end{figure}

if(year%400 == 0)以降は次のように書くこともできます.

if(year%400 == 0 $\vert\vert$ year%4 == 0 && year%100 != 0)

練習問題 3..5   うるう年の判定
if(year%400 == 0 $\vert\vert$ year%4 == 0 && year%100 != 0)を用いて, うるう年判定プログラムを作成しなさい.

Switch文(switch Construct)

Java言語にはelse-if文の代わりにswitch文とよばれるものがあります.switch文で書けるものはすべてelse-if文で書けます.しかし,逆は真ではありません.swith文の構文は次のようになります.

switch (式)
{
    case 定数式1:
          文1
          break
    case 定数式2:
          文2
          break
    default:文
          break
}

switch文の動作

「ステップ1」  
  式の値を求める
「ステップ2」  
  式の値が
  (1) caseの定数式と等しい場合,
  そのcaseに続く文にプログラムの制御が移り実行され,break文に出会うか,switch文の終端に出会うと終了します.
  (2) どのcaseとも等しくないが,defaultが存在するとき,
  defaultに続く文にプログラムの制御が移り,実行されます.
  (3)どのcaseとも等しくなく,defaultが存在しないとき,
  プログラムの制御は,switch文の次の文に移る.

各caseには1つ以上の数値を持つ定数あるいは定数式による名札を付ける.Defaultという名札の付いたcaseは,他のcaseのどれもが満足されなかったときに実行されます. Javaのswitch文は,C/C++の悪い習慣(すり抜け)をそのまま引きずっており,break文を省略することができます.しかし,すり抜けの機能はバグの温床になるので,使わないようにして下さい.

例題 3..7   順位の判定
\framebox{
\begin{minipage}{13.65cm}
コマンドラインから順位を入力し,入賞者の判別を行うプログラムを作成しなさい.
\end{minipage}}

解答

class SwitchStatement {
  public static void main(String[] args)
  {
    int rank = Integer.parseInt(args[0]);
    switch (rank)
    {
      case 1:
        System.out.println("優勝者には海外旅行です");
        break;
      case 2:
        System.out.println("2位のあなたには,国内旅行です");
        break;
      case 3:
        System.out.println("3位のあなたには,図書券です");
        break;
      default:
        System.out.println("残念賞のタオルをどうぞ");
        break;
    }
  }
}

実行結果

\begin{figure}\centering
\includegraphics[width=7.8cm]{JAVAFIG/SwitchStatement.eps}
\end{figure}

三項演算子(Ternary Operator)

Javaには,if ... else文の代わりに用いることができる演算子があります.その演算子は三項演算子(ternary operator)と呼ばれ,その構文は次のようになります.

条件 ? ステートメント1 : ステートメント2;
ここで,条件が満たされると,ステートメント1が実行され,満たされない場合はステートメント2が実行されます. 例えば,構文
min = (x < y ? x : y);
は,xとyの小さい方をminに代入します.
三項演算子は条件とステートメントが単純なときに用いるくらいで,複雑なステートメントの時は用いないようにします.

例題 3..8   2数の比較
\framebox{
\begin{minipage}{13.65cm}
2つの数字をコマンドライン引数として入力し,三項演算子を用いて大きい方を求めるプログラムを作成しなさい.
\end{minipage}}

解答

3項演算子(a $>$ b ? a:b)により大きいほうを取り出せます.

class TernaryOperator {
  public static void main(String[] args)
  {
    int a = Integer.parseInt(args[0]);
    int b = Integer.parseInt(args[1]);
    System.out.println("大きいほうは" + (a > b ? a : b));
  }
}

実行結果

\begin{figure}\centering
\includegraphics[width=7.8cm]{JAVAFIG/TernaryOperator.eps}
\end{figure}

練習問題 3..6   3数の最大値
3つの数字を読み取って比較し,三項演算子を用いて一番大きな数字を求めるプログラムを作成しなさい.

スコープ(Scope)

識別子のスコープとは,その識別子を用いることができるプログラムの部分です.例えば,変数は宣言されるまで用いることはできません.よって,そのスコープはその変数が宣言されているところで始まる.

例題 3..9   変数のスコープ
\framebox{
\begin{minipage}{13.65cm}
\end{minipage}}

class LifeOfScope
{
  public static void main(String[] args)
  {
    x = 11; // エラー:これはxのスコープに入っていありません.
    int x;
    { x= 22; // OK:これはxのスコープに入っています.
    y= 33; // エラー:これはyのスコープに入っていありません.
    int y; // OK:これはyのスコープに入っています.
    x = 44; // OK:これはxのスコープに入っています.
    y = 55; // OK:これはyのスコープに入っています.
    }
    x = 66; // OK:これはxのスコープに入っています.
    y = 77; // エラー:これはyのスコープに入っていありません.   }

}

xのスコープはxが宣言されたところからmainメソッドの最後までです.yのスコープはyが宣言されたところからブロックの終了までです. $ \blacksquare$

確認問題 3..1  

1. 次の命題は正しいか調べなさい.

a. !(p || q) と !p || !qは同値です.
b. !!!pと!pは同値です.
c. p && q || rはp && (q || r)と同値です.

2. 次の命題を表す論理式を作成しなさい.

a. scoreは80以上で90よりも低い
b. answerは'N'か'Y'のどちらかである
c. nは3で割り切れるが,30では割り切れない
d. chは大文字である

4. 次のプログラムコードはどこがいけないか.

if (x == 0)
    if (y == 0) System.out.println("xとyは共に0です" );
else System.out.println("xは0ではありません" );

5. 次の式の値を求めなさい. (x < y ? -1: (x == y ? 0 : 1));

6. xの絶対値をabsxに代入する文を3項演算子を用いて表しなさい.

演習問題 3..1  

1. 代入を使って,変数aとbの内容を壊さずに,入れ替えるプログラムを完成しましょう.ただし,変数aとb以外に作業用として変数wを用いることとします.

class SwapNumbers
{
  public static void main(String[] args)
  {
    int a,b,w;
    a=10;
    b=20;
    System.out.println("a = " + a);
    System.out.println("b = " + b);
    //入れ替え
    (ア)
    (イ)
    (ウ)
    System.out.println("a = " + a);
    System.out.println("b = " + b);
  }
}

2. 次のプログラムを実行した結果を数値で答えなさい.

class DivAndRem
{
  public static void main(String[] args)
{
    int a,b;
    a=9;
    b=2;
    System.out.println("a/bの結果= " + (a/b); /*整数どうしの割り算を行います.結果は
整数で表されます.*/
    System.out.println("a%bの結果=" + (a%b));
}