いきなりですが問題です.次のプログラムを,Javaで書き直しましょう.
/* ordinal.c */ #include <stdio.h> int main(void) { int n; for (n = 1; n <= 120; n++) { int d1 = n % 10; int d10 = (n / 10) % 10; printf("%d", n); if (d10 == 1) { puts("th"); } else if (d1 == 1) { puts("st"); } else if (d1 == 2) { puts("nd"); } else if (d1 == 3) { puts("rd"); } else { puts("th"); } } return 0; }
「1st」「2nd」「3rd」「4th」…と,序数を出力するプログラムです.int型の変数nを1から120まで増やし,その値に応じて,「st」「nd」「rd」「th」のいずれかをつけて出力します.どれをつけるかは,値の一の位と十の位の数で決まるので,判定に先立ち,2つの変数d1とd10に格納しています.判定ですが,まず,十の位の数が1のときは,一の位の数にかかわらず「th」をつけます(11,12,13はそれぞれ「eleventh」「twelfth」「thirteenth」です).そうでないときは,一の位の数が1なら(firstの)「st」,2なら(secondの)「nd」,3なら(third)の「rd」をつけ,それ以外のときは「th」です.
「puts」がなじみでない人のために,記しておくと,この関数は(文字列の)引数に続けて,改行を出力します.ですのでputs("th");は,printf("th\n");と同じ処理をします.
Cの開発環境がきちんと整備されているシェル上で,コンパイルするには,たとえばcc -o ordinal ordinal.cと実行します.これにより,ordinalというファイルが作られ,実行属性もつきます(実行ファイルです).そして./ordinalのコマンドで実行します.2つのコマンドの先頭については,次のように理解しましょう.ccというコマンドは,コマンドサーチパス上にあるので,先頭に「./」をつけないのに対し,コンパイルして作ったファイルは,カレントディレクトリ上のファイルであることを明示するため,先頭に「./」をつけます.
Javaで書き直すと,次のようになりました.
/* Ordinal.java */ public class Ordinal { public static void main(String[] args) { int n; for (n = 1; n <= 120; n++) { int d1 = n % 10; int d10 = (n / 10) % 10; System.out.print(n); if (d10 == 1) { System.out.println("th"); } else if (d1 == 1) { System.out.println("st"); } else if (d1 == 2) { System.out.println("nd"); } else if (d1 == 3) { System.out.println("rd"); } else { System.out.println("th"); } } } }
先に,共通するところを挙げると,変数の宣言,演算と代入,そしてfor文とif文は,Cとまったく同じです.intやdoubleといった型名も,Javaで問題なく使用できます.なお,for文に関しては,Javaでは「for (int n = 1; n <= 120; n++)」と書くことで,変数nのスコープ(有効範囲)をこのforループの中だけとし,mainの直後の宣言を取り除くこともできます.
もちろん違いもあります.まずmain(Cでは関数,Javaではメソッド)の書式が異なります.それぞれの言語で,そう書くのが慣習です.「void」が,Cではカッコの中,Javaではmainの直前にありますが,Cで書いたほうでは,コマンドライン引数をとらないという意味になり,Javaのほうは,戻り値を(例えば終了ステータスとしてシェルなどに)渡さないことを表します.Cで書いた,main関数の中身を,Javaに貼り付ける際には,最後のreturn文を,コピーしないようにしましょう.
出力処理も,異なります.Javaアプリケーションでは,「System.out.print」と「System.out.println」が好んで用いられます.どちらも,引数はObjectすなわち任意のオブジェクトであり,intでもdoubleでも任意のクラスでもかまいません.実引数のクラスに応じて,出力をしてくれます.printとprintlnの使い分けは,簡単です.lnなしは改行をせず,lnありにすると,改行をしてくれます.それと,Javaでも「System.out.printf」を使って,Cと同じ書式で変数の値を変換し(指定によっては右揃えや0詰めなどもして),出力することができます.
コンパイルと実行のコマンドも,違ってきます.その前にファイル名とクラス名について,見ておきます.上記についてファイル名はOrdinal.javaとし,そこでOrdinalクラスを定義しています.このように,ファイル名(から「.java」を取り除いたもの)と,定義したいクラス名を同じにしておくのが,Javaアプリケーションのプログラミングにおける慣習となっています.クラス名について,先頭は大文字にしておくのが無難です.
javacとjavaが利用可能なシェル上で,コンパイルは,javac Ordinal.javaというコマンドによってなされます.ファイルに対する処理なので,Ordinal.javaというファイル名を指定します.エラーがなければ,Ordinal.classというファイルが作られます.実行は,java Ordinalとします.こちらはクラスを指定するため,「.java」も「.class」もつけません.ですが実際のところは,javaコマンドはOrdinal.classのファイルの中身に基づき,mainメソッドを実行することとなります.
CとJavaとの共通点・相違点は,先週月曜の演習初回でも解説しましたので,本日の記事はそのおさらいとなります.ただし,その際にはWindowsとEclipseを使ったので,Cのコンパイルはせず,JavaはEclipseが自動でやってくれました.Linux環境でシェルを用いたJavaのコンパイルと実行については,昨日の演習2回目で実施する予定でしたが,暴風警報発令のため授業休止となり,次週に持ち越しです.