配列


月を数字で入力して, 対応する英単語を答えるプログラムを書いてみよう.
import java.io.*;
class Test8{
  public static void main(String[] args) throws IOException{
  // 入力をするためには,System.inからBufferedReaderを作らなくてはいけない
    BufferedReader d=new BufferedReader(new InputStreamReader(System.in));
    System.out.print("月(1-12)を入力して下さい  ");
    // 入力をおこなう前に, バッファリングされていた出力を出してします
    System.out.flush();
    String s=d.readLine();
     // 文字列をint型に変換する. 
    int month=Integer.parseInt(s);
    // 入力した月が1より小さい時,12より大きい時は次の if 文を実行します
    if(month<1 || month>12) System.out.println(month+"月はありません");
    if(month==1) System.out.println("1月は January です. ");
    if(month==2) System.out.println("2月は Febrary です. ");
    if(month==3) System.out.println("3月は March です. ");
    if(month==4) System.out.println("4月は April です. ");
    if(month==5) System.out.println("5月は May です. ");
    if(month==6) System.out.println("6月は June です. ");
    if(month==7) System.out.println("7月は July です. ");
    if(month==8) System.out.println("8月は August です. ");
    if(month==9) System.out.println("9月は Sepember です. ");
    if(month==10) System.out.println("10月は October です. ");
    if(month==11) System.out.println("11月は November です. ");
    if(month==12) System.out.println("12月は December です. ");
  }
}
ここで,
    if(month<1 || month>12) System.out.println(month+"月はありません");
の「||」は複数の条件式の論理和をあらわす.(A||B)は「AまたはB」という意 味で,すなわち条件Aか条件Bのどちらかが真になると真になる.この条件式は 「monthの値が1より小さいとき,またはmonthの値が12より大きいとき」とい う意味である.

この逆が「&&」で論理積となる.(A&&B)は「AかつB」という意味で,条 件Aか条件Bの両方が真のときのみ真になる.

これで動くことは動くがあまりすっきりしないプログラムである. これを,

ように書き直してみよう.
import java.io.*;
class Test9{
  public static void main(String[] args) throws IOException{
  // 入力をするためには,System.inからBufferedReaderを作らなくてはいけない
    BufferedReader d=new BufferedReader(new InputStreamReader(System.in));
    System.out.print("月(1-12)を入力して下さい  ");
    // 入力をおこなう前に, バッファリングされていた出力を出してします
    System.out.flush();
    String s=d.readLine();
     // 文字列をint型に変換する. 
    int month=Integer.parseInt(s);
    if(month<1 || month>12) System.out.println(month+"月はありません");
    else {
     String mname="";
     if(month==1) mname="January";
     else if(month==2) mname="Febrary";
     else if(month==3) mname="March";
     else if(month==4) mname="April";
     else if(month==5) mname="May";
     else if(month==6) mname="June";
     else if(month==7) mname="July";
     else if(month==8) mname="August";
     else if(month==9) mname="September";
     else if(month==10) mname="October";
     else if(month==11) mname="November";
     else if(month==12) mname="December";
     System.out.println(month+"月は "+mname+" です. ");
   }
  }
}
これで, すっきりとしたことはすっきりとしたが, else ifの繰り返しはまだ まだうっとおしい. 前のページのプログラムの
     else if(month==5) mname="May";
     else if(month==6) mname="June";
のような, 整数の値によって, 変数の値が変わるといったパターンを簡潔にプ ログラムするために, 多くのプログラム言語では配列が用意されている.
配列 を使ってプログラムを書き直すと次のようになる.
import java.io.*;
class Test10{
  public static void main(String[] args) throws IOException{
  // 入力をするためには,System.inからBufferedReaderを作らなくてはいけない
    BufferedReader d=new BufferedReader(new InputStreamReader(System.in));
    System.out.print("月(1-12)を入力して下さい  ");
    // 入力をおこなう前に, バッファリングされていた出力を出してします
    System.out.flush();
    String s=d.readLine();
     // 文字列をint型に変換する. 
    int month=Integer.parseInt(s);
    // 文字列の配列型の変数 mnames を宣言し,{}で囲まれた初期値を入れる.
    String mnames[]={"January","Febrary","March","April","May","June",
                     "July","August","September","October",
                     "November","December"};
    if(1<=month && month<=12)
      System.out.println(month+"月は "+mnames[month-1]+" です. ");
    else 
      System.out.println(month+"月はありません");
  }
}

上のように
String mnames[]
と書くと文字列の配列を入れるmnames という名前の変数を宣言したことにな る. '='の右側の内容で配列の内容を初期化している. 配列の要素数(大きさ)は この例では12である.

配列型の変数の参照は 「変数名[添字]」のようにしておこなう. 添字は1で はなく0から始まることに注意しよう. 添字はint型でなくてはいけない.

float型,double型の変数を添字に使うのはキャスト演算子「(型名)式」でint 型に変換すれば可能だが,そうする必要がある場合の多くはその変数は本来 int型にすべきである.特に,ループの繰り返しを判定する変数などを, float, doubleにすると誤差により,ループの回数が意図しない回数になる可 能性がある.この場合は大(double)は小(int)を兼ねない.

注意)

    String mnames[]={"January","Febrary","March","April","May","June",
                     "July","August","September","October",
                     "November","December"};
    String mnames[];
    mnames={"January","Febrary","March","April","May","June",
            "July","August","September","October",
            "November","December"};
のように, 宣言と代入に分けて書くことはできない.

配列と繰り返し

配列の利用法としては, 前のページの例のように読み出し専用の表として利 用するだけでなく, データ領域として利用することもできる. 有名な「エラ トステネスのふるい」のプログラムをJavaで書いたものを下にあげる.
class Test11{
  public static void main(String[] args{
   int n=1000,i,k;
   int p[]=new int[n+1];
   for(i=2; i<=n; i++) p[i]=1; // i++はi=i+1と同じ意味
   for(i=2; i<=n; i++) 
     if(p[i]==1){
        System.out.print(i+" ");
        for(k=2; i*k<=n; k++) p[i*k]=0;
     }
  }
}
 このプログラムでは p という配列が使われている. iが素数の可能性がある
時はp[i]が1, 合成数の時はp[i]が0になるように計算していく. 配列の宣言と
作成は,
   int p[]=new int[n+1];
の部分である. これは,
   int p[];
   p=new int[n+1];
という2つの文に分けて書いても良い(続けて書かなくても良い). newは配列や オブジェクトの生成を表す予約語で, 次のintは要素の型を示す. [n+1]は作成 する配列の大きさ(要素数)が n+1 であることを示す. 配列の大きさを宣言時 に決定しなくてもよいのは, Javaの特徴の1つである.

上のプログラムで素数が求まる原理が分かりにくいかもしれない. はいぱーワークブック「プログラミング」でも 配列によるチェックのページでほとんど同じプログラムを扱っているので, 分からない人はそちらの説明を見て欲しい.

注)上のプログラムでは int の配列を使っているが, よりJavaらしく書くなら boolean(真偽値を表す型)の配列を使って

class Test12{
  public static void main(String[] args){
   int n=1000,i,k;
   boolean p[]=new boolean[n+1];
   for(i=2; i<p.length; i++) p[i]=true;
   for(i=2; i<p.length; i++) 
     if(p[i]){
        System.out.print(i+" ");
        for(k=2; i*k<=n; k++) p[i*k]=false;
     }
  }
}
のように書く. なお配列型の変数に .lengthをつけて p.lengthのようにする と, その配列の要素数を返す. これまで, 呪文のように打ち込んできた
  public static void main(String[] args){
の「String[] args」の部分は, 実は文字列の配列である引数(「ひきすう」と 読む. 外から値を渡すためのものだが, 中から見ると初期化済の変数と思って 良い)だとわかる. 実は, java を起動する時に
java プログラム名 a1 a2 .. an
のように後ろに空白で区切って文字列をいくつか書くと
args[0] <- "a1"
args[1] <- "a2"
..
args[n-1] <- "an"
のように配列argsの中に渡すことができる. この機能を利用して, 次の プログラムを書いてみる.
class Test13{
  public static void main(String[] args){
    for(int i=args.length-1;i>0;i--)
      System.out.println(args[0]+args[i]);
  }
}
このプログラムをコンパイルして,
java Test13 I can read this file.
と実行すると,
ktanaka@ux019> java Test13 I can read this file.
Ifile.
Ithis
Iread
Ican
という出力が得られる.
次に進む