わさっきhb

大学(教育研究)とか ,親馬鹿とか,和歌山とか,とか,とか.

CからJavaへ

いきなりですが問題です.次のプログラムを,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との共通点・相違点は,先週月曜の演習初回でも解説しましたので,本日の記事はそのおさらいとなります.ただし,その際にはWindowsEclipseを使ったので,Cのコンパイルはせず,JavaEclipseが自動でやってくれました.Linux環境でシェルを用いたJavaコンパイルと実行については,昨日の演習2回目で実施する予定でしたが,暴風警報発令のため授業休止となり,次週に持ち越しです.