レポート課題3 よくある質問(FAQ)

レポート課題3に関して、だんだん質問が増えてきたので、よくある質問とその回答を掲載します。

質問
javac Report3.java とタイプしたところ、cannot read Report3.java というエラーになりました。何がいけないのでしょうか?
回答

ソースファイル Report3.java がカレントディレクトリにない場合、このエラーが起こります。Report3.javaがカレントディレクトリにあることを確認し、javac Report3.javaを実行してください。確認するには、ls Report3.java とタイプします。Report3.javaという行が画面上に表示されるとカレントディレクトリにファイルが存在することが確認できます。


質問
javac Report3.java とタイプしたところ、エラーが出ず、コンパイルは問題なくできます。しかし、java Report3とタイプして実行しようとすると、Exception in thread "main" java.lang.NoClassDefFoundError: Report3というエラーが表示されて実行できません。何故でしょうか?
回答

ソースファイル Report3.java には、Report3というクラス class Report3 を定義してください。そうしないと、このエラーが表示されます。たとえば Report3.javaというファイルに class Reportを定義してしまうと、コンパイルはうまくいきますが、java Report3とタイプしても実行できません。


質問
13countという名前の変数を整数型で定義しましたが、コンパイルするとエラーになります。
回答

Javaでは数字から始まる変数名を使えません。変数名には、英字、アンダースコア(_)、ドルマーク($)から始まり英数字とアンダースコアとドルマークを含む文字列が使えます。

また、int, double, if, for, whileなど命令に使われる文字列は予約語といって変数名に使うことはできません。ここに挙げた命令は一部ですが、もしエラーがでるようなら変数名を変更してみるとうまくいくかもしれません。

<Javaにおける予約語の例>

abstract boolean break byte case catch char class const continue default do double extends final finally float for goto if implements import instanceof int interface long native new package private protected public return short static super switch synchronized this throw throws transient try void volatile white


質問
java Report3 とタイプしたところ、画面が止まってしまったようになり、いくら待っても実行結果が表示されません。あるいは、Unixのcalコマンドで結果を確かめてみると、正しくない実行結果が表示されます。何がいけないのでしょうか?
回答

この現象が起きている人は、繰り返しの使い方に問題があると思われます。下の(間違いのある)ソースコードを見てみましょう。

     
   int year=2005; 
   int month;
   int day=13;


   for(month=1;month<=12;month++)
   {
       if (month<=2) {month=month+12; year=year-1;} // 繰り返しの変数monthが変更されている
       int r= (year+year/4-year/100+year/400+(13*month+8)/5+day) % 7;
   }

ここで繰り返しにはmonthという変数が使われていますが、繰り返しの処理の中で、この変数が変更されていることに注目してください。 このプログラムを書いた人は、monthは1ずつ加算されて12まで変化し、合計12回の繰り返しが実行されると期待したのですが、実際には、1回目の繰り返し(month=1)で、monthには12が加算されるため、結果的にmonthは13となってしまいます。このため、for命令で、2回目の繰り返しが実行されようとするときに、繰り返しの条件(month<=12)に適合しなくなり、繰り返しの処理はここで終了してしまいます。つまり、繰り返しは、たった一度しか実行されません。

(また、このときyearの値も最初の2005の値から変化して2004になっているため、もし、繰り返しがさらに実行され、month<=2の条件が満たされるとyearはさらに2003, 2002と減算されてしまいます。)

このように、(monthのような)繰り返しを定義する変数の値が、繰り返し処理の中で変更されてしまうと、繰り返しが正常に実行されません。 講義で紹介したZeller3.javaの例を見るとわかると思いますが、上記の間違いを正すためには、my(およびd)という変数を用意して以下のようにプログラムします。

   int y=2005; 
   int m;
   int d=13;
       
   
   for(m=1;m<=12;m++)
   {
            
      int year = y;
      int day = d;
      int month = m;
             
      if (month<=2) {month=month+12; year=year-1;}
      int r= (year+year/4-year/100+year/400+(13*month+8)/5+day) % 7;
 
    }

こうすれば、繰り返しを定義する変数 mと計算のための変数の year, month を独立にするこ とができます。つまり、繰り返しの処理の最初で、year=y month=m という命令によって変数 yearmonth はそれぞれ y m の値の参照により初期化されて、Zellerの計算に利用されますが、繰り返しを定義する変数mは、このZellerの計算で、影響をうけることはなく、繰り返しは正常に実行されます。


質問
講義で説明があったZeller3.javaのソースコードや講義資料にあるプログラムのソースコードの一部は使っても良いのでしょうか?
回答

はい。課題の設問1にはZeller3.javaのソースコードが役に立つと思います。講義資料にあるものであればいくら転用しても構いません。


質問
Zeller3.javaにはusage()というメソッドがありますが、これはどういう意味ですか?課題の解答にusage()メソッドを含める必要がありますか?
回答

usage()は、必要ありません。Zeller3.javaをもとにして、課題を解く場合は、

   
   public static void usage()
   {
      System.out.println("usage: Zeller3 ");
      return;
   }
という部分と、
   if (argv.length!=1) 
   {
      usage(); 
      return;
   }

という部分を削除してください。また、それに続く、(1)int y=Integer.parseInt(argv[0]); という行も、(2)int y; と変更します。(1)の意味は、講義でもやりましたが、java Zeller3 と実行するときに、パラメターを指定した場合、そのパラメターの文字列 (argv[0]) が整数に変換されて変数yに代入されるという意味です。
例えば、java Zeller3 2005 のように2005という文字列をパラメターに指定すると、argv[0]には文字列2005が、そして、yには整数2005が代入されます。
今回の課題では、パラメターは必要ありませんから、(2)のようにします。

usage()は、このプログラムにどのようなパラメターを指定できるか、などプログラムの使い方の説明を表示するメソッドです。オンラインマニュアルが、Unixコマンドの使い方を表示するのと同様に、コマンドが正しくない使い方をされた場合に、正しい使い方を表示するためのメソッドです。課題には特に必要ありませんので、これは削除してください。


質問
Javaのプログラミングは難しすぎます。もう何時間も費やしているのにできません。どうしたらいいですか?
回答

課題を解いていて、何か問題にぶつかったら、メールで質問をしてください。他の人もたくさん質問しています。その際に、ソースコードも添付してくれると詳細なアドバイスができます。