第5回(2011年11月9日)


今日の演習

 今日は以下の内容で演習を行います. 前回に引き続き重要な内容なので,集中して取り組んでください.


今日の目標


条件分岐(if 文, if-else 文 *先週の復習 各自で)

ブロック文

 if 文や for(今日紹介します.), while 文ではブロック文と呼ばれるものが使われます.ブロック文とは、文を一まとめにしたもので、{ と } で囲まれています.

if 文, if-else 文

 プログラムを作成していると、条件によって処理を分岐させたい場合がよく出てきます. 例えば、 0 で割ろうとすると実行時にエラーになる(コンパイルは成功する)ので, それを回避するときなどです.

- - - - - - - - - - - - - - - -

#include <stdio.h>

main()
{
    /* 整数型の変数 a, b, c を用意する */
    int  a, b, c;

    /* 整数型変数 a に入力 */
    printf("整数 a を入力してください:");
   scanf("%d", &a);

    /* 整数型変数 b に入力 */
    printf("整数 b を入力してください:");
   scanf("%d", &b); 

   /* b が 0 であるかによって分岐 */
   if (b == 0)
   {
     printf("0 での割り算はできません.\n");
   }
   else
   {
      /* 整数型変数 c に a/b の結果を代入 */
      c = a/b;

      /* 変数 c の内容を画面に表示 */
      printf("a/b=%d\n", c);

   }
}

- - - - - - - - - - - - - - - -

 if (b == 0) からが条件文です.このプログラムでは、入力された b の値が 0 に等しければ青色の部分が実行され、それ以外の場合は赤色の部分が実行されます.


典型的な if-else 文

 if-else 文には重要なものとして次のようなパターンがあります.

パターン1

文0

if (条件)
{
    条件が真であれば実行するブロック文・・・・ブロック文1
}
else
{
    条件が偽であれば実行するブロック文・・・・ブロック文2
}

文3

 

パターン2

文0

if (条件)
{
    条件が真であれば実行するブロック文・・・・ブロック文1
}

文2

 

 

パターン3

文0

if (条件1)
{
    条件が真であれば実行するブロック文・・・・ブロック文1
}
else if (条件2)
{
    条件1が偽かつ条件2が真であれば実行するブロック文・・・・ブロック文2
}
・・・・・・
else if (条件N)
{
    条件1〜条件N-1が全て偽かつ条件Nが真であれば実行するブロック文・・・・ブロック文N
}
else
{
    条件1〜条件Nが全て偽であれば実行するブロック文・・・・ブロック文N+1
}

文N+2


条件式

 if 文の条件の部分には条件式が入ります.条件式は関係演算子という演算子を使って記述します.関係演算子は2つの値の大小関係や等値関係を判定するものです.関係演算子には次のものがあります.

演算子 説明 記述例 記述の意味
> 大きい if (a > 100) a が 100より大なら
>= 大きいか等しい if (a >= 100) a が 100以上なら
< 小さい if (a < 100) a が 100より小なら
<= 小さいか等しい if (a <= 100) a が 100以下なら
== 等しい if (a == 100) a が 100なら
!= 等しくない if (a != 100) a が 100でないなら

等しいをあらわす条件式は == とイコール2つであることに注意してください.= とイコール1つの場合は変数への代入をあらわしていました(先週の内容).if 文の条件を書く部分に誤って代入式を書いたとしても、文法的には間違っていないので、コンパイルが成功してしまいます(期待した動作はしませんが).気をつけてください.


課題1

 入力された自然数が、7 の倍数かどうか判定するプログラムを作成せよ.

(注:剰余を求める演算子 % を利用. この演算子は整数型変数にのみ利用可能.)

課題2

 自然数 a, b を入力すると, a が b の倍数かどうか表示するプログラムを作成せよ.(b = 0 が入力された場合には、計算できない事を表示する.)


論理演算子をつかった込み入った条件式(今日はここから)

 ときには、

「a>10」 かつ 「a<100」 なら
「a==100」 または 「a==200」 なら

といった、場合を扱いたいときがあります.このような「かつ」「または」に相当する論理演算子を使うことで、より複雑な条件をあらわすことができます.

例えば、うるう年は

4で割り切れ かつ 100で割り切れない年」
「400で割り切れる年」

のどちらかに当てはまる年のことです.入力された年(西暦)を上の条件に照らし合わせ、うるう年かどうかを判定するプログラムは次のようになります.(先週打ち込んでない人は 1109-0.c として打ち込んで実行してみてください.途中でてくる % は剰余を与える演算です.)

- - - - - - - - - - - - - - - -

#include <stdio.h>

main()
{
    int n;

    printf("年=");
    scanf("%d", &n);

    if ((n%4 == 0) && (n%100 != 0))
    {
        printf("うるう年です\n");
    }

    if (n%400 == 0)
    {
        printf("うるう年です\n");
    }
}

- - - - - - - - - - - - - - - -

途中でてくる && が関係演算子で、「かつ」をあらわします.関係演算子には && のほかに次のようなものがあります.

演算子 説明 記述例 記述の意味
&& 論理積(かつ/and) if (a == 3 && b == 4) a が 3 かつ b が 4 なら
|| 論理和(または/or) if (a == 3 || b == 4) a が 3 または b が 4 なら
! 否定(でない/not) if (!(a == 3 && b == 4)) a が 3 かつ b が 4 、でないなら

 関係演算子 && は & が2つであることに注意してください(|| も同様). & 1つでも他の意味がありますので、コンパイルエラーにはなりません.しかし、期待した動作とはならないので注意が必要です.

 先の日本語でのうるう年の定義は

「4で割り切れ かつ 100で割り切れない年」 または 「400で割り切れる年」

と書き直すことができます.つまり、先の2つの if 文を一つにまとめて次のように書くこともできます.


if ( ( (n%4 == 0) && (n%100 != 0) ) || (n%400 == 0 ) )
{
    printf("うるう年です\n");
}



課題3

 入力された整数が、3 の倍数か 7 の倍数であれば、その数値を表示するプログラムを作成せよ.

課題4

正の整数aとbとcをキーボードから入力し, c が a と b の公倍数になっているか判定するプログラムを作成せよ.

繰り返し文

 コンピューターは繰り返し処理が得意です.人間のように飽きてしまうことなく、黙々と処理を繰り返してくれます.

 例えば、画面に Hello! を10回表示したい場合、これまでの知識では次のプログラムとなります.

- - - - - - - - - - - - - - - -

#include <stdio.h>

main()
{
    printf("Hello!\n");
    printf("Hello!\n");
    printf("Hello!\n");
    printf("Hello!\n");
    printf("Hello!\n");
    printf("Hello!\n");
    printf("Hello!\n");
    printf("Hello!\n");
    printf("Hello!\n");
    printf("Hello!\n");
}

- - - - - - - - - - - - - - - -

10回程度であれば、これでも良いかも知れませんが、100回表示せよとなるとこれではどうしようもありません(根気が必要です).そこで、繰り返し文が登場します.

for 文

 繰り返し文には for 文while 文があります.まずは for 文を使ったプログラムを見て見ましょう.繰り返し文を使うと、先のプログラムは次のようになります.ファイル名を 1109-1.c として打ち込み、コンパイルし実行してください.

- - - - - - - - - - - - - - - -

#include <stdio.h>

main()
{
    int i;

    for (i = 0; i < 10; i++)
    {
        printf("Hello!\n");
    }
}

- - - - - - - - - - - - - - - -

上のプログラムで、繰り返し文と呼ばれるのは


for (i = 0; i < 10; i++)
{
    printf("Hello!\n");
}


の部分です.このように書くことで { } で囲まれたブロック文が10回繰り返され、先のプログラムと同様の結果が得られます.

 途中 i++ というものがありますが、これは i = i + 1 と同様であると思ってください.i = i + 1 と書く場合、= が代入をあらわすことを思い出せば、左辺の i に i + 1 の結果を代入すると読め納得できます.(等号だと勘違いすると変なことになります.)

 for 文の括弧の中にはセミコロン ; で区切られた3つの式があります.通常、for 文の中にあらわれる変数は整数型です(実数型の場合もあります).

  • はじめの式は i = 0 となっています.ここで通常初期値設定を行います.つまり、i の初期値を 0 と設定しています
  • 2つめの式は、先の条件分岐のところで現れた条件式で、この場合 i < 10 が真である間ブロック文を繰り返せということを示しています
  • 3つめの式は繰り返しの度に実行される式で i++ によって i が毎回1ずつ増えます

 結果、この for (i = 0; i < 10; i++) は

「はじめに i を 0 とし、i が 10 より小さい間、ブロック文を繰り返し、繰り返しの度に i を1 ずつふやせ.」

と読むことができます.

 例えば、1〜100までの間の数を表示するには次のようなプログラムになります.

- - - - - - - - - - - - - - - -

#include <stdio.h>

main()
{
    int i;

    for (i = 0; i < 100; i++)
    {
        printf("%d\n", i+1);
    }
}

- - - - - - - - - - - - - - - -

 また、2〜100までの間の偶数を表示するには次のようなプログラムになります.

- - - - - - - - - - - - - - - -

#include <stdio.h>

main()
{
    int i;

    for (i = 2; i <= 100; i = i + 2)
    {
        printf("%d\n", i);
    }
}

- - - - - - - - - - - - - - - -

ここでは、初期値を i = 2 とし、毎回の i の増やし方は i = i + 2 と2つずつ増やしています.また、処理は i <= 100 が満たされている間繰り返されますから、2〜100までの間の偶数が表示されます.


プログラムの停止の仕方とファイルの消し方

 プログラムは正しく動作し、正しく停止することが重要ですが、停止しないプログラムを書くのは大変簡単です.停止しないプログラムはたいていの場合、プログラミングミスが原因です.例えば、次のプログラムは停止しません.1109-2.c として打ち込み実行してみてください.

- - - - - - - - - - - - - - - -

#include <stdio.h>

main()
{
    int i;

    for (i = 2; i > 1; i++)
    {
        printf("Hello!\n");
    }
}

- - - - - - - - - - - - - - - -

条件式 i > 1 が真でありつづけるため停止しないわけです.(後の述べる扱える数値の大きさを超えるとおかしなことになるので、そこで停止する可能性はありますが・・.)

 今後、色々なプログラムを作ってもらいますが、何らかのプログラミングミスで停止しないプログラムになっていて、それを実行してしまった場合は、

Ctrl + c  (Ctrl キーを押しながら c のキーを押す)

によって強制的に終了させることができます.覚えておいてください.

 また、エラーのあるプログラムによっては core というファイル名のファイルを作成してしまう場合があります.このファイルは、当面不要なので、消してしまいましょう(ファイルサイズが大きいので).以前、0 での割り算を行うプログラムを実行した人は、多分この core ファイルができているはずです.


 次のサンプルプログラムは1〜5までの和と積を計算し表示します.ファイル名を 1109-3.c として打ち込み実行してください.

- - - - - - - - - - - - - - - -

#include <stdio.h>

main()
{
    /* 変数の宣言 */
    int i, wa, seki;

    /* 変数の初期化(下の説明参照) */
    wa = 0;
    seki = 1;

    /* 繰り返し文:i が 1 から 5 になるまで繰り返し */
    for (i = 0; i < 5; i++)
    {
        /* wa の計算:(古い)wa に i を加えた値を, wa に代入 */
        wa = wa + (i+1);

        /* seki の計算:(古い)seki に i 掛けた値を, seki に代入 */
        seki = seki * (i+1);
    }

    /* 結果を表示 */
    printf("和=%d\n", wa);
    printf("積=%d\n", seki);
}

- - - - - - - - - - - - - - - -

このプログラムは大変短く簡単ですが、実はこのプログラムは数値計算プログラムの基本形と呼べるものです.流れは、

  1. 利用する変数の初期化を行い
  2. 繰り返し文をもちいて
  3. 何らかの計算を繰り返し
  4. 結果を表示する

となっています.このプログラムをよく見て、これまでの内容を疑問なく理解できているか確認してください.(よく分からない人は必ず質問すること.)

 変数は利用する前に必ず初期化(適切な値の代入)を行って下さい.変数は用意した直後の内容は不定です.つまり、なんらかの値を代入する前にその変数の保持している値が 0 である保証はありません.例えば、先の和と積を求めるプログラムで wa =0, seki = 1 を忘れると思ってもいない結果になる可能性があります.i に関しては for 文の中でまず i = 0 と初期化されるのでこの場合問題ありません.

また, wa = wa + (i+1), seki = seki * (i+1) と書く場合、= が代入をあらわすことを思い出せば、左辺の wa (seki) に wa + (i+1) ( seki * (i+1) ) の結果を代入すると読め納得できます.(等号だと勘違いすると変なことになります.)


課題5

1109-3.c を, 整数 n を入力すると 1 〜 n までの和と積を表示するプログラムに改良せよ.(注意:あまり大きな n を入力すると、特に積の値がコンピューターで扱える範囲を超えてしまうので、正確な値がでてこなくなります. それほど大きくない n で試してください.)

課題6

実数 a, 自然数 n を入力すると an を計算し表示するプログラムを作成せよ.

課題7

実数 a, 自然数 n を入力すると a + a2 + a3 + ... + an を計算し表示するプログラムを作成せよ.

課題8

自然数 n を入力すると n 以下の 3 の倍数と 7 の倍数を表示するプログラムを作成せよ.(for 文と if 文を使う. )

課題9

自然数 n を入力すると n が素数がどうか判定するプログラムを作成せよ.


今日学んだ事

  • 条件分岐と条件式の書き方
  • 繰り返し文の書き方

戻る