第4回(2011年11月2日)


今日の演習

 今日は以下の内容で演習を行います.


今日の目標


変数(前回の復習)

全てのプログラミング言語には変数と呼ばれるものがあります.変数は,データ(数値であったり,文字列であったり)を一時的に保存しておく箱によくたとえられます.コンピュータープログラムは,そのような変数と呼ばれる箱に入ったデータを処理することにより,有用な仕事をします.また,変数を用いることで,より柔軟な処理を行うことができます.

変数には,整数型実数型文字型と数種類ありますが,まずは整数型変数を扱います.整数型変数は,整数値を保存するための箱です(実数値は保存できない).


C言語における変数の宣言と変数の使用

 C言語では,変数を使う場合には関数のはじめの部分で全て宣言しておく必要があります.

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

#include <stdio.h>

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

    /* 整数型変数 a に値 5 を代入 */
    a = 5;
    /* 整数型変数 b に値 12 を代入 */
    b = 12;

    /* 整数型変数 c に a+b の結果を代入 */
    c = a+b;

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

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

整数型変数は
  int  a, b, c;

実数型変数(単精度浮動小数点数型)
  float  u, v, w;

実数型変数(倍精度浮動小数点数型)は
 double x, y;

というように宣言します.

printf 関数の中で用いられる %d のことを,変換文字列といいます.%d の d は decimal(10進数)の頭文字の d に由来します.つまり, %d は対応する変数または数値を,10進数整数として表示する働きをもちます.対応する変数または数値とは,今の場合は整数型変数 a,b,c の3つということになります.(変換文字列と, printf 関数の第2引数以降の引数の数は一致させます.)

本演習で使用する代表的な変換文字列を示しておきます.

%d

10進数で出力する

%f %lf

浮動小数点数として出力する (%lf は倍精度浮動小数点時)

このような変換文字列を,変数の型や表示したい様式にあわせて使うことになります.

注意:C言語の実数型(浮動小数点数型)には float (単精度浮動小数点数型)のほかに double (倍精度浮動小数点数型)があります.名前からわかるように,倍精度浮動小数点数型の方が,より高精度に数値を表現することができます(通常単精度浮動小数点型は32bitであって,倍精度浮動小数点型は64bitで表現される).倍精度浮動小数点数型を用いる場合,変換文字列として%lfを用いる必要があるなど,説明が煩雑になるので,演習のホームページでは実数型としては float を用いるよう統一しています(場合によって double を用いることもあります).参考のために,先のサンプルプログラムの倍精度浮動小数点数型を用いたバージョンを以下に示します.(ここでは printf 関数のみ使っているので,実際には printf 関数内の変換文字列は %f, %lf 双方どちらでもよい.後にでてくる scanf 関数の場合には double 型を用いる場合には %lf を用いる必要がある.)


補足 C言語では + の他にも次のような演算ができる.

+

加算

-

減算

*

乗算

/

除算

%

剰余 (整数のみ)

 


scanf 関数

 キーボードから数値データを入力するには scanf 関数という標準関数を用います.printf 関数は出力を行う関数でしたが,scanf 関数は入力を行う関数です.

scanf 関数による整数値の入力

 scanf 関数を用いてみます. キーボードから入力された整数値データをそのまま画面に表示するプログラムです.

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

 1: #include <stdio.h>
 
2: 
 
3: main()
 
4: {
 
5:     int i;
 
6: 
 7:     printf("整数値を入力してください: ");
 
8:     scanf("%d", &i);
 
9:     printf("入力された整数値は %d です.\n", i);
10: }

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

8行目のscanf関数のダブルクォーテーションで囲まれた文字列は,printf 関数と同様の変換文字列です.ただし,printf 関数のように通常の文字列と変換文字列が両方書くことはできず,scanf 関数では変換文字列のみ書くことができます

間違った例

scanf("整数値を入力してください: %d, &i);

このサンプルプログラムのように整数型変数 i に値を入力する場合は整数型変数の変換文字列である %d をかきます.そのあとには コンマ に続いて &i とかかれています.scanf 関数では,変換文字列に続いて,入力されたデータを格納する変数名がきますが,変数名の頭に & をつける必要があります.& をつけねばならない理由はもちろんあるのですが,ここでは scanf 関数では変数の頭に必ず & をつけると覚えてください.

上の例のように整数型変数は
  scanf("%d", &i);

実数型変数(単精度浮動小数点数型)
  scanf("%f", &a);

実数型変数(倍精度浮動小数点数型)は
  scanf("%lf", &b);

とします。


円の面積を求めるプログラム

これらを全て使うと円の半径を打ち込んだらその円の面積を表示させるプログラムができます.

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

 1: #include <stdio.h>
 2:
 3: main()
 4: {
 5:     float pi, r, s;
 6: 
 7:     pi = 3.14159;
 8:    
 9:     printf("円の半径を入力してください:");
10:     scanf("%f", &r);
11:
12:     s = pi*r*r;
13:
14:     printf("円の面積は %f です.\n", s);
15: }

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

このプログラムをターミナルでコンパイルし,実行すると,

円の半径を入力してください:

と表示され,その状態でとまります.そこで,メッセージどおりに,面積を求めたい円の半径を入力します.例えば, 3.2 と打ち込んで,Enter キーをおしてみましょう.半径 3.2 の円の面積が求まったでしょうか?


確認問題

 実数値 a, b の入力を促し、入力すると a+b の結果を表示するプログラムを作成せよ.次に a/b の結果を表示するようにせよ.(ヒント:まず実数 a の入力を促し、a の入力後、実数 b の入力を促し、b の入力後、計算して表示.) 

* 実はこれまでの知識だけで作成しますと、b を0 としたときに不都合がでます.この問題を回避するには次に説明します,条件分岐が必要となります. 


(今日はここから)処理が実行される順番.

プログラム中の処理の数が少しづつが増えてきました。(変数の宣言、入力、演算、出力。。。。)ここまでの作業でもう気づいていると思われますが、コンピューターがプログラムを実行する場合、プログラムに書かれている順序で処理が行われます。ですので、処理の配置を適切に行わないと、当然正しく動きませんので、ご注意ください。(例えば先ほどの円の面積を求めるプログラムで, printf() と scanf() の順序を変えたりしてもらうと、分かると思います。)


条件分岐(if 文, if-else 文)

ブロック文

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

if 文, if-else 文

 プログラムを作成していると、条件によって処理を分岐させたい場合がよく出てきます.例えば、先ほどの確認問題(割り算)等です。(下のプログラムは解答例です。確認しつつファイル名を1102-1.c としてエディターで打ち込んでください.)

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

#include <stdio.h>

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

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

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

    /* 実数型変数 c に a/b の結果を代入 */
    c = a/b;

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

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

 このプログラムを実行し、実数 a,b をそれぞれ入力すると、a/b の結果を画面に出力します.ところで、 b として 0 を入力するとどうなるでしょうか?やってみると分かりますが、なにかエラーが出ます.このように、実数型に限らず 0 で割ろうとすると実行時にエラーになる(コンパイルは成功する)ので、それを回避することを考えねばなりません.そこで、条件文が登場します.まずは、サンプルプログラムでみてみましょう.先の 1102-1.c を次のように変更してください(説明の為に色をつけていますが、色は無視してください).

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

#include <stdio.h>

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

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

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


   /* b が 0 であるかによって分岐 */
   if (b == 0.0)
   {
     printf("0 での割り算はできません.\n");
   }

   else
   {
      /* 実数型変数 c に a/b の結果を代入 */
      c = a/b;

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

   }
}

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

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


典型的な if-else 文

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

パターン1

文0

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

文3

 

パターン2

文0

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

文2

 

パターン1とパターン2の違いは else 文が有るか無いかの違いです.

より複雑なものとして、次のパターン3 (3N) があります。

 

パターン3

文0

if (条件1)
{
    条件が真であれば実行するブロック文・・・・ブロック文1
}
else if (条件2)
{
    条件1が偽かつ条件2が真であれば実行するブロック文・・・・ブロック文2
}
else
{
    条件1,2 どちらも偽であれば実行するブロック文・・・・ブロック文3
}

文4

 

パターン3N

文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


フローチャートによる説明

 上記パターン1とパターン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

2つの実数 s, t を入力すると、その差の絶対値を表示するプログラムを作成せよ.

課題2

整数 m が入力されると、それが奇数か偶数かを判定するプログラムを作成せよ.

(注:剰余を求める演算子 % を利用. これは整数型変数m, n に対し、m%n は m を n で割ったときの余りを与える.この演算子は整数型変数にのみ利用可能.)

課題3

 2つの実数 s, t を入力すると, s > t, s = t, s < t か判定して表示するプログラムを作成せよ.(If-else文のパターン3を参考)

課題4

 3つの実数, a, b, c を入力すると, x に関する2次方程式, ax2 + bx + c = 0 が実数解を持つか判定し, 表示するプログラムを作成せよ.

課題5

以下のような動作をする三択問題を出すプログラムを作成せよ。問題は計算問題でもクイズでも何でもよいが、以下の問題とは違う物を作成せよ。

実行するとまず

3 + 5 = ?
(1) 3
(2) 8
(3) 10

等と問題が表示され、整数値 1, 2, 3 何れかを入力すると、正解か不正解かを判定し表示する。


論理演算子をつかった込み入った条件式

 ときには、

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

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

例えば、うるう年は

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

のどちらかに当てはまる年のことです.例えば入力された年(西暦)を上の条件に照らし合わせ、うるう年かどうかを判定するプログラムは次のようになります.if 文の中身に注意しつつ, ファイル名を 1102-2.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 文を一つにまとめて次のように書くこともできます.

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

#include <stdio.h>

main()
{
    int n;

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

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

}

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

課題6

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


今日新しく学んだ事

  • 条件分岐

戻る