# R e p o r t 2

 今回の課題
  • 制御文と配列を用いてオリジナルのJavaアプリケーションによる初 級問題(なるべく短い行数で)を作成し、模範解答例を示せ。併せ て、同様な動作を行うC言語のソースコードを示せ。
  • 課題のWebページは、必ずスタイルシートを用いて作成すること。

 問題:ソースコード(test2.java)
01:
02:
03:
04:
05:
06:
07:
08:
09:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
49:
50:
51:
52:
53:
54:
55:
56:
57:
58:
59:
60:
61:
62:
63:
64:
65:
66:
67:
68:
69:
70:
71:
72:
73:
74:
75:
import java.io.*;

public class test2 {
    public static void main(String args[]) throws IOException {

        int year = 0, month = 0, day = 0;
        int leapmonth[]   = {0,31,29,31,30,31,30,31,31,30,31,31,31};
        int normalmonth[] = {0,31,28,31,30,31,30,31,31,30,31,31,31};
        int T = 1;

        while (T == 1) {
        System.out.println("This program cannot output a day of the week
        before October 15, 1582 because it uses Gregorian.\nPlease input the date.");

        System.out.print("Year   => ");
        BufferedReader br1 = new BufferedReader(new InputStreamReader(System.in));
        String str1 = br1.readLine();
        year = Integer.parseInt(str1);

        if (year < 1582) {
            continue;
        }

        System.out.print("Month  => ");
        BufferedReader br2 = new BufferedReader(new InputStreamReader(System.in));
        String str2 = br2.readLine();
        month = Integer.parseInt(str2);

        if (1 > month || month > 12) {
            continue;
        }

        System.out.print("Day    => ");
        BufferedReader br3 = new BufferedReader(new InputStreamReader(System.in));
        String str3 = br3.readLine();
        day = Integer.parseInt(str3);

        if ( ( B ) ) {
          if (day > leapmonth[month])
            continue;
        }else{
          if (day > normalmonth[month])
            continue;
        }

        if ( ( A ) ) {
            continue;
        }else{
            break;
        }
        }

        String week[] = {"Sunday","Monday","Tuesday","Wednesday","Thrusday","Friday","Saturday"};

        int a = (year - 1) / 4;
        int b = (year - 1) / 100;
        int c = (year - 1) / 400;
        int d = a - b + c;
        int e = 0;
        int f = (year - 1) * 365 + d;

        if( ( B ) ) {
            for (int count = 0; count <= month-1; count++)
                e = e + leapmonth[count];
        }else{
            for (int count = 0; count <= month-1; count++)
                e = e + normalmonth[count];
        }

        int g = e + f + day;
        int h = (g % ( C ));
        System.out.println(year + "/" + month + "/" + day + " (" + week[h] + ") ");
    }
}
       
◎実行結果

This program cannot output a day of the week before October 15, 1582
because it uses Gregorian.
Please input the date.
Year   => 2006
Month  => 11
Day    => 20
2006/11/20 (Monday)

◎問題

上記のプログラムは、年月日を入力すると、その日付の曜日を出力するプログラムである。
ただし、1582年10月14日以前の日付は入力を受け付けない。
閏年とは、平年は2月28日までしかないが、1日増えて2月29日ができる年である。
閏年の条件は
  • 4で割り切れる年
  • 例外として100で割り切れる年は閏年とない
  • 例外の例外として400で割り切れる年は閏年とする
問1.上記のソースコードの空欄A~Cに入るものとして最も適切なものを選択肢1~4より選べ。
  • A 1. year = 1582 && month = 10 || year != 1582 2. year == 1582 && month == 10 && day < 15 || year == 1582 && month < 10 3. year == 1582 && month == 10 && day < 14 || year == 1582 && month < 10 4. year < 1582 || year == 1582 && month 10 && day 15 || year == 1582 && month < 10
  • B 1. year % 4 == 0 && year % 100 == 0 || year % 400 != 0 2. year % 4 != 0 && year % 400 != 0 3. year % 4 != 0 && year % 100 == 0 || year % 400 != 0 4. year % 4 == 0 && year % 100 != 0 || year % 400 == 0
  • C 1. 6 2. 7 3. 8 4. 5
問2.1988年10月31日と入力したとき、変数eの値とその日の曜日を求めよ。

 解答
◎プログラムの説明
    このプログラムは入力された年月日をもとに曜日を出力するものである。
    計算できない、存在しない年月日を入力されたらcontinueにより最初から入力を要求するようになっている。

◎解答
 問1
  • A 解答番号 2 解答 year == 1582 && month == 10 && day < 15 || yea = 1582 && month < 10  L39にcontinueがあることと、問題文に「1582年10月14日以前の日付は入力を受け付けない」とあることから、空欄Aには 問題文の記述に則した条件がはいると推測する。 ただし、1581年以前の場合はL20のif文ですでに記述されているため、「year < 1582」という条件は不要。  よって、ここで必要な条件は「1582年の10月の15日より前、または1582年の10月より前の時」になるので答えは 2 となる。
  • B  解答番号 4 解答 year % 4 == 0 && year % 100 != 0 || year % 400 == 0  L54のif文内のfor文で「leapmonth」と「normalmanth」で使い分けている事から、空欄Bには閏年の条件が入ると推測する。  問題文にある閏年の条件より「4で割り切れて、かつ100で割り切れない、または400で割り切れる年」となるので答えは 4 となる。
  • C  解答番号 2 解答 7  一週間は7日あるので7で割ればいいのでは?という発想ができたら勝ち組。 L45の配列weekは要素が7つまでしかないことと、L64で出力するときに「week[h]」としているので 変数hの値は0~6までしか取らないので、0~6の値を出すためには7で割ってその剰余を使えば良いので、答えは 2 となる。
問2    曜日を求めるには実際に変数year,month,dayに値をいれて計算するしかない。    変数eは、L54~60の部分で求められる。   1988年は閏年なので、上で空欄Bで求めた通り配列leapmonthを用いたfor文(L55,56)を使う。    変数month値は10なので、10回L56の「e = e + leapmonth[count]」を実行するので、   leapmonth[0]~leapmonth[9]までの値を全て足した値が変数eの値となる。   答えは、月曜日 変数 e = 274 となる

 C言語によるソースコード(cal.c)

01:
02:
03:
04:
05:
06:
07:
08:
09:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
49:
50:
51:
52:
53:
54:
55:
56:
57:
58:
59:
60:
61:
62:
63:
64:
65:
include 

int main () {

  int leapmonth[13]   = {0,31,29,31,30,31,30,31,31,30,31,31,31};
  int normalmonth[13] = {0,31,28,31,30,31,30,31,31,30,31,31,31};
  char week[7][10] =
  {"Sunday","Monday","Tuesday","Wednesday","Thrusday","Friday","Saturday"};
  int year = 0, month = 0, day = 0, count = 0;

  for (; count < 1;) {

  printf("This program cannot output a day of the week before October
  15, 1583 because it uses Gregorian.\n");
  printf("Please input date\n\n");

  printf("Year   => ");
  scanf("%d", &year);
  if (year < 1583) {
    continue;
  }

  printf("Month  => ");
  scanf("%d", &month);
  if (1 > month || month > 12) {
    continue;
  }

  printf("Day    => ");
  scanf("%d", &day);
  if (year % 4 == 0 && year % 100 != 0 || year % 400 == 0) {
    if (day > leapmonth[month]) {
      continue;
    }
  }else if (day > normalmonth[month]) {
    continue;
  }

  if (year == 1582 && month == 10 && day < 15 || year == 1582 && month < 10) {
    continue;
  }else{
    break;
  }
  }

  int a = (year - 1) / 4;
  int b = (year - 1) / 100;
  int c = (year - 1) / 400;
  int d = a - b + c;
  int e = 0;
  int f = (year - 1) * 365 + d;
  int count2 = 0;

  if (year % 4 == 0 && year % 100 != 0 || year % 400 == 0) {
    for (;count2 <= month - 1; count2++)
      e = e + leapmonth[count2];
  }else{
    for (;count2 <= month - 1; count2++)
      e = e + normalmonth[count2];
  }

  int g = e + f + day;
  int h = (g % 7);
  printf("%d/%d/%d(%s)\n",year,month,day,week[h]);
}
 ◎考察
   
   ◆JavaはC言語と比べると、文字列の配列が非常に簡単に出来た。
   ◆数値の入力はC言語が簡単にできる。
   ◆制御文の使い方には違いがなかった。


 感想
 どんどん書いてるうちに気がつけばソースが100行超えていたので、htmlに写す時にソースを削りまくりました。無駄に頑
張りました。
 このプログラムを作る時に閏年について色々調べていたら、いままで知らなかったことが沢山あって困りました。
 1582年10月15日までは閏年の条件は4年に一回だけだった。
 1582年の10月4日~10月14日は存在しない(一部の国、日本では明治5年の何月かが10日間ほど存在しない)など、
明日つかえる無駄な知識を貯える事ができました^^^^^^^

  上記の無駄な知識の関係で西暦1年1月1日からの曜日を出力するプログラムは恐ろしい行数になるので断念しました。