1日目 3日目

2日目

目標

課題 2

カレンダプログラムを自分で作る(1)

前回取り上げたカレンダ表示プログラム cal を自分で作ってみることを考えてみよう。

はじめにkadai02というディレクトリを作成し、そこに移動する。

上位のディレクトリに移動する場合はcd ..と入力する

[tacha@proge1 ~]$ mkdir kadai02
[tacha@proge1 ~]$ cd kadai02
[tacha@proge1 kadai2]$ 

前回学習した hello.cを少し改造して、 次のようなmycal1.cを作ってみた。

main()
{
	printf("                    1\n");
	printf("  2  3  4  5  6  7  8\n");
	printf("  9 10 11 12 13 14 15\n");
	printf(" 16 17 18 19 20 21 22\n");
	printf(" 23 24 25 26 27 28 29\n");
	printf(" 30 31\n");
}

Programming E 受講生の人は、すでに作成してあるので、次のように実行してコピーし、 エディタで開いてみる。以下同様。

[tacha@proge1 kadai2]$ cp ~tacha/kadai02/mycal1.c .
[tacha@proge1 kadai2]$ emacs mycal1.c

コンパイルして実行してみる。今回はccのオプションの一つ -o を 用いて、作成する実行プログラムの名前を指定してみる。

[tacha@proge1 kadai2]$ cc mycal1.c -o mycal1
[tacha@proge1 kadai2]$ ./mycal1
                    1
  2  3  4  5  6  7  8
  9 10 11 12 13 14 15
 16 17 18 19 20 21 22
 23 24 25 26 27 28 29
 30 31
[tacha@proge1 kadai2]$

このプログラムを良く見ると、「1日」が3桁で表されており、 1週間の最後、つまり「7日分」出力したあとに、改行コードが出力されている事に気付く。

というわけで、出力を「1日」分ごとに分解すると次のような mycal2.c を作ることができる。


main()
{
	printf("   ");  /* 日曜日 */
	printf("   ");  /* 月曜日 */
	printf("   ");  /* 火曜日 */
	printf("   ");  /* 水曜日 */
	printf("   ");  /* 木曜日 */
	printf("   ");  /* 金曜日 */
	printf("  1");  /* 土曜日 */
	printf("\n");   /* 7個書いた */
	printf("  2");
	printf("  3");
	printf("  4");
	printf("  5");
	printf("  6");
	printf("  7");
	printf("  8");
	printf("\n");   /* 14個書いた */
...
	printf("\n");   /* 28個書いた */
	printf(" 23");
	printf(" 24");
	printf(" 25");
	printf(" 26");
	printf(" 27");
	printf(" 28");
	printf(" 29");
	printf("\n");   /* 35個書いた */
	printf(" 30");
	printf(" 31");
	printf("\n");   /* 最後には改行 */
}

/**/で挟まれた部分はコメントと 呼ばれるもので、プログラムには影響しない。適切にコメントをつけることで プログラムの可読性が向上するので、上手に利用することが重要である。


繰り返し処理と変数

mycal2.cの先頭部分には、3つの連続した空白を出力するprintfが 6回繰り返されている。 この部分を C で利用可能な繰り返し処理の一つ for を使って書き直してみると次のようになる。

main ()
{
        int i;

	for (i = 0; i < 6; i = i + 1) {
	        printf("   ");
        }
....

一度に新しいことがたくさん出てきたので順に見ていくことにする。


変数

変数についてはこちらを参照。

forによる繰り返し処理(1)

for文は次のような構成になっている。

 for (最初に1度だけ行う文; 繰り返しを行うかどうかの判定文; 毎回の最後に行う文) {
     <繰り返し処理>
 }

従って、上の文で実行されることは次のようになる。

  1. 変数 i に数値 0 を代入。
  2. printf(" ")を実行。画面に三つの空白が書かれる。
  3. 変数 ii+1 を代入。iの中身は 1 になる。
  4. 判定文を確認。1 は 6 より小さいので、引き続き繰り返す。
  5. printf(" ")を実行。画面に三つの空白が書かれる。
  6. 変数 ii+1 を代入。iの中身は 2 になる。
  7. 判定文を確認。2 は 6 より小さいので、引き続き繰り返す。
  8. printf(" ")を実行。画面に三つの空白が書かれる。
  9. 変数 ii+1 を代入。iの中身は 3 になる。
  10. 判定文を確認。3 は 6 より小さいので、引き続き繰り返す。
  11. printf(" ")を実行。画面に三つの空白が書かれる。
  12. 変数 ii+1 を代入。iの中身は 4 になる。
  13. 判定文を確認。4 は 6 より小さいので、引き続き繰り返す。
  14. printf(" ")を実行。画面に三つの空白が書かれる。
  15. 変数 ii+1 を代入。iの中身は 5 になる。
  16. 判定文を確認。5 は 6 より小さいので、引き続き繰り返す。
  17. printf(" ")を実行。画面に三つの空白が書かれる。
  18. 変数 ii+1 を代入。iの中身は 6 になる。
  19. 判定文を確認。6 は 6 より小さくないので、繰り返しを終了する。

この結果、画面には空白文字が全部で18個書かれることになる。


forによる繰り返し処理(2)と条件文if

次に日付を出力する部分を見てみると、数字が変わっていく点を除けば、やはり for で表現できる事に気付く。 変数と printfを組み合わせればできることに気付くだろうか?

変数の中身を表示させるを 参考に考えると printf(" %2d", i);で表現できることが判る。(判る? :-)

main () 
{
	int i;
	
	for (i = 0; i < 6; i = i + 1) {
		printf("   ");
	}
	for (i = 1; i <= 31; i = i + 1) {
		printf(" %2d", i);
		}
	}
	printf("\n"); /* 最後には改行 */
}

しかし、これでは、1 日から 31日までが一行に(実際には画面の幅で改行されるように見えるが)表現されてしまい、 カレンダにならない。 カレンダにするには、ある特定の場合(今の場合は土曜日である 1, 8, 15, 22, 29日)のあとだけ改行"\n"を出力する必要がある。

このような条件付きで特定の処理をするための方法の一つとして C 言語では if 文を用いる。

if文の基本型は次のような構成になっている。

 if (条件1) {
     <条件1が成立した場合の処理>
 } else if (条件2) {
     <条件1が成立せず、条件2が成立した場合の処理>
 } else {
     <どの条件も成立しなかった場合の処理>
 }

条件が一つで良い場合は else if は不要であるし、条件が成立しない場合が 不要であれば省略もできる。

従って、「1日」の後ろに改行を出す場合は

    if (i == 1) {
        printf("\n");
    }

と書くことができる。ここで、"==" は両辺が等しいことを意味する演算子である。 さきほど使った "<" は数学の場合と同じで左辺が右辺より小さいことを意味するが 等しい場合には "=" ではなく、二つ重ねなければならないことに注意する。

同様に 8, 15, 22, 29 についても引き続き書いても良いが、処理が同じなので条件をまとめることもできる。 論理和演算子を用いると次のようにまとめられる。

    if (i == 1 || i == 8 || i == 15 || i == 22 || i == 29) {
        printf("\n");
    }

あるいは、改行を出力するのが 7で割ってあまりが1の時であることに気付けば、 剰余演算子を用いて表現すると、次のように簡単になる。

    if ((i % 7)  == 1) {
        printf("\n");
    }

条件文の意味は「 i を 7 で割った余り (i % 7) が 1 に等しい(==)」である。

結局、プログラムは次のように書き直すことができる(~tacha/kadai02/mycal4.c)。

main () 
{
	int i;
	
	for (i = 0; i < 6; i = i + 1) {
		printf("   ");
	}
	for (i = 1; i <= 31; i = i + 1) {
		printf(" %2d", i);
		if ((i % 7) == 1) {
			printf("\n");
		}
	}
	printf("\n");
}

1日目 表紙 3日目

tacha@tack.fukui-med.ac.jp
$Id: 02.html,v 1.1 2005/11/03 17:10:53 tacha Exp $