制御構造

1.単純な分岐 − 等価演算子、関係演算子

単純な分岐とは、条件式に1つの式だけを使った選択構造である。

おもに式としては、等価演算子(=)、関係演算子(< >)が使用される。変数や式が単独で設定されることもある。その場合は、その評価値が0ならば偽、0以外ならば真という判定になる。

 

例 変数の場合

a = 0;

if(a)

{

 printf(“aは0ではありません。\n”);

}

else

{

printf(“aは0です。\n”);

}

<実行結果>

aは0です。

 

 

 

例 式の場合

a=0,b=1;

if(a*b)

{

printf(“a*bは0ではありません。\n”);

}

else

{

 printf(“a*bは0です。\n”);

}

<実行結果>

a*bは0です。

 

 

 

 

 

括弧の用い方に関して、基本的に4つの方法がある。

 

パスカルスタイル

while (test)

           {

           statement;

           }

 

改変パスカルスタイル

 

while (test)

{

              statement;

}

 

KernighamRitchieスタイル

while (test){

              statement;

}

改変Kernigham, Ritchieスタイル

while(test){

              statement;

              }

どれを用いるかは自由だが、1つのプログラムでは統一した用い方をしなければならない。

 

2.分岐条件の組み合わせ − 論理演算子

分岐の条件は範囲の指定などのときに、複数組み合わせられる。その組み合わせには、主に論理積&&と、論理和||の演算が用いられる。

例 論理積(&&)の場合:xがaからbの間にある場合

a =1;x=2;b=3;

if(a <=x && x <=b)

{

printf(“xaとbの間にある。\n”);

}

else

{

printf(“xaとbの間にない。\n”);

}

 

<実行結果>

xaとbの間にある。

 

 

 

 

論理和(||)の場合:xがa以下またはb以上にある場合

a=1;b=2;x=3;

if(x < a|| b < =x)

{

printf(“xaとbの間にない。\n”);

}

else

{

printf(“xaとbの間にある。\n”);

}

<実行結果>

xaとbの間にない。

 

 

 

 

 


if文:もし〜ならば〜する

このダイアグラムをフローチャートという。フローチャートはJIS規格として規定されているが、プログラムの作り方の研究が進むにつれて、その欠点が指摘され、現在ではあまり使われていない。フローチャートに変わるものとして、NSチャートやHCPチャートなどが開発されている。とはいってもいまだにJIS規格のフローチャートを用いている場合があるので、多少の解説をしておく。フローチャートとは、アルゴリズムの各段階の処理を箱の中に記述し、各箱を線や矢印で結んで、計算順序を示すものである。

 

例題4.1 if文の例 2数の比較

2つの異なる数字を読み取って比較し、大きい方を求めるプログラム(if文だけを使って)を作成しよう。

実行例

          

考え方

変数abに呼び込んだ値を入れる。つぎに、aとbの値がどちらが大きいかの比較をする。

もしaがbより大きいならばmaxaである。

もしbaより大きいならばmaxはbである。

 

では、プログラムを書いてみよう。

 

#include <stdio.h>

int main ()

{

              int max,get_a, get_b;

printf(“2つの整数を入力\n”);

              scanf(“%d %d”,&get_a,&get_b);

              if (get_a > get_b) {

              max = get_a;

              printf(“大きい方は%d\n”,max);

              }

              if (get_b > get_a) {

              max = get_b;

              printf(“大きい方は%d\n”,max);

              }

}

 

if-else 文:そうでなければ〜する

上の例題でget_a > get_bが正しければ、maxget_a。そうでなければmaxget_bと直せる。つまりif-else文を用いて書いたほうが分かりやすい。 読んで分かりやすいプログラムを書くように、心がけよう。ソフトウェア工学上、大事なことである。

 


例題4.2 if-else 文の例 2数の比較

2つの異なる数字を読み取って比較し、大きい方を求めるプログラムを作成しよう。

実行例

             

考え方

もしaがbより大きいならばmaxaで、そうでなければmaxはbである。

 

解答

#include <stdio.h>

int main ()

{

              int max,get_a, get_b;

printf(“2つの整数を入力\n”);

              scanf(“%d %d”,&get_a,&get_b);

              if (get_a > get_b) {

              max = get_a;

              printf(“大きい方は%d\n”,max);

              }

              else {

             max = get_b;

              printf(“大きい方は%d\n”,max);

              }

}

 

while文:〜の間〜する

例題4.3 素数判定

与えられた数が素数かどうか判定するプログラムを作成せよ。

実行例

          

考え方

素数とは1とその数自身でしか割ることができない数である。そこで、与えられた数をnとし、nを2から順にn-1までの数で割っていき、割り切れなければ素数であることが示せる。i=2から順に割っていくということをプログラムで書くと、inより小さい間は実行するとなるのでwhile(i < n)と表わせる。次に、whileループを実行中あまり(remainder)の最小値(min_remainder)を求める。やがて、inに到達しwhileループが終了する。その後、あまりの最小値(min_remainder)の値が0か0以外かを調べれば、nが素数かどうかの判定ができる。プログラムに書くと次のようになる。


解答

/*素数判定*/

#include <stdio.h>

 

int main()

{

              int get_num,min_remainder=1,remainder,index=2;

              printf("整数を入力してください\n");

              scanf("%d",&get_num);

    if(get_num==1)

        {

            min_remainder=0;

        }

              while(index < get_num)

              {

                  remainder = get_num%index;

                  if(remainder < min_remainder)

                  {

                      min_remainder=0;

                  }

                  index++;

              }

              if(min_remainder !=0)

              {

                  printf("%dは素数です\n",get_num);

              }

              else

{

            printf("%dは素数ではありません\n",get_num);

  }

}

もう少しよく考えてみよう。2で割り切れる数(偶数)は2以外素数ではない。また、素数でない数(合成数)の約数は対になっているので、nの平方根までの数をチェックすればよいことが分かる。この考えを用いて、もう一度プログラムを書いてみよう。


 

#include <stdio.h>

void main(void)

{

              int get_num,index=2,remainder,min_remainder=1;

              printf("整数を入力してください\n");

              scanf("%d",&get_num);

              if (get_num==1)

              {

                            min_remainder=0;

              }

              if(get_num > 2 && get_num%2 == 0)

              {

                            min_remainder=0;

              }

              while (index*index <= get_num) /* =が必要となる*/

              {

                            remainder = get_num%index;

                            if(remainder < min_remainder)

                            {

                               min_remainder=0;

                            }

                            index++;

              }

              if(min_remainder != 0)

              {

                            printf("%dは素数です\n",get_num);

              }

              else

              {

                            printf("%dは素数ではありません\n",get_num);

              }

}

 

こういうプログラムを実行させるとき、windowsを用いている人は、その都度エグゼファイル(実行ファイル)を立ち上げなければならず、面倒であると感じたでだろう。そこで、好きな回数だけ実行させられる方法を示す。

              int choice=0;

              do

              {

              choice =1;

              printf ("続ける場合は0をやめるときは0以外の数字キーを押してください");

              scanf(“%d”,&choice)

              }while(choice==0);と入れておく。これにより0を押せば続行できるし、止めたければ0以外のキーを押せばよい。

 

ループからの脱出

while,for,do-while文を用いるとき、気をつけなければならないのは、無限ループにおちいりやすいことである。このようなことを避けるために、ループの条件は点ではなく、区間とするべきである。さて、ループからどうしても脱出する必要があるときには、if文とbreak文を用いる。例えば、キーボードからデータを入力して、0を入力したら終了したい場合を考えよう。このときは、

while(scanf(“%d”,&data))

{

              if (data == 0)

              {

                            break;

              }

}

または、数字以外を入力したら終了したければ、

while(scanf(“%d”,&data) != 0)

{

}

と書けばよい。whileループの条件はscanf(“%d”,&data)であるが、scanfは呼び込みに成功すると1を返し、失敗すると0を返す関数なので、このループは入力がある限り続行される。次に、入力が0のとき、if文の条件が真となるので、次のbreak文に到達し、ここで、whileループから脱出する。

 

例題4.4 データをキーボードから入力し、入力したデータの平均、最大値、最小値を求めるプログラムを作成しよう。ただし、0を入力した時点で終了するとする。

実行例

             

考え方 

1. 最大値と最小値を見つけるには、まず、1個データを読んで、その値を最大値と最小値にしておく。これを行うプログラムは次のようになる
int max,min,ini;
scanf("%d",&ini);
max = min = ini;

2. 0を入力したら終了しなくてはならないので、while文の中にif文とbreak
使ってwhileからの脱出をはかる。関数scanf( )はうまくいけば1を返し、失敗する
と0を返す関数なので、次のようになる。
int data
while(scanf("%d",&data))
{
    if(data == 0)
    {
        break;
    }
3. 0以外のときは、新しく読み込んだデータと1個目のデータとを比較し、新し
いデータが1個目より大きければ、それをmaxとおき、小さければminとおく。次に
データを読み込んだときに、読み込んだデータとmax,minを比較する。次のようにな
る。
int max,min;
if(data > max)
{
    max = data;
}
if(data < min)
{
    min = data;
}
4. 平均は読み込んだデータの和sumを読み込んだ回数nで割ってやればよい。ただ
し、sumnも整数型なので、平均を出すときには実数型に変えてやらなければならな
い。これはキャストと呼ばれるものを使って行う。次のようになる。
sum = sum + data;
n++;
printf("
平均は%d",(float)(sum/n));

以上をまとめると次のようなプログラムになる。

#include<stdio.h>

void main(void)
{
    int data,sum,n,max,min,ini;
    printf("
数学の成績を入力してください。\n");
     scanf("%d",&ini);
     sum = ini;
     max = min = ini;
     n = 1;
    while(scanf("%d",&data))
  {
    if(data == 0)
    {
       break;
    }
    else
    {
        sum=sum+data;
        n++;
        if(data > max)
        {
            max = data;
        }
        if(data < min)
        {
           min = data;
        }
    }
    }
    printf("
平均点は%f\n",(float)(sum/n));
    printf("
最高点は%d\n",max);
    printf("
最低点は%d\n",min);
    printf("
回数%d",n);
}

 

Switch文について

C言語にはelse-if文の代わりにswitch文とよばれるものがある。switch文で書けるものはすべてelse-if文で書ける。しかし、逆は真ではない。とは、言うものの、switch文で書かれたプログラムを読むこともあると思うので、簡単にswitch文の紹介をする。

switch ()

{

              case 定数式:文

              case 定数式:文

              default:文

}

switch文の動作

「ステップ1」

              式の値を求める

「ステップ2」

              式の値が

(1)       caseの定数式と等しい場合、

そのcaseに続く文にプログラムの制御が移り、実行される。

(2)       どのcaseとも等しくないが、defaultが存在するとき、

defaultに続く文にプログラムの制御が移り、実行される。

(3) どのcaseとも等しくなく、defaultが存在しないとき、

プログラムの制御は、switch文の次の文に移る。

 

caseには1つ以上の数値を持つ定数あるいは定数式による名札を付ける。Defaultとい名札の付いたcaseは、他のcaseのどれもが満足されなかったときに実行される。

 

例題4.5 順位の判定

入賞者の判別を行うプログラムを作成しよう。

実行例

          

解答

 

#include <stdio.h>

 

void main (void)

{

              int rank;

              printf(“あなたの順位は?>>> “);

              scanf(“%d”,&rank);

 

switch (rank)

{

             case 1: //caseと1の間にはスペースが入る

                           printf(“優勝者には、海外旅行です\n”);

                           break;

             case 2:

                           printf(“2位のあなたには、国内旅行です\n”);

                           break;

             case 3:

                           printf(“3位のあなたには、図書券です\n”);

                           break;

             default:

             printf(“タオルをどうぞ\n”);

                           break;

}

 

else-if文:もし〜ならば〜し、そうでなければ〜し、そうでなければ〜し、。。。そうでなければ〜する。

例題4.6 うるう年の判定

西暦年数yearを入力し、うるう年かを判定するプログラムを作成せよ。

実行例

             

考え方 うるう年とは400で割り切れる年数。または、4で割り切れ、かつ100で割り切れない年数のことである。

例えば1900年はうるう年ではない。

これをプログラムにするには、if (year % 400 == 0)ならばうるう年。else if (year % 4 == 0 && year % 100 != 0)ならばうるう年。else うる年ではない。ではプログラムを書いてみよう。

 

解答

#include <stdio.h>

void main(void)

{

             int year;

             printf("西暦年を入力してください\n");

             scanf("%d",&year);

             if(year%400 == 0)

             {

                           printf("%dはうるう年です",year);

             }

             else if(year%4 == 0 && year%100 != 0)

             {

                           printf("%dはうるう年です",year);

             }

             else

             {

                                         printf("%dはうるう年ではありません",year);

             }

}

if(year%400 == 0)以降は次のように書くこともできる。

if(year%400 == 0 || (year%4 == 0 && year%100 != 0))

やってみよう。

 

例題4.7 2次方程式の解

ax2 + bx + c = 0の解を求めるプログラムを作成しよう。

実行例

          

考え方

判別式はD = b2 – 4acで与えられ、解の公式より、解はx = (-b ± D)/2aで与えられる。よって

「係数aが0であり、係数bが0ならば、 (条件1)

              解はない           (文1)

「係数aが0であり、係数bが0でなければ(条件2)

              x = -c/b                       (文2)

「係数aが0でなく、判別式が正ならば  (条件3)

              実数解が2つ          (文3)

「係数aが0でなく、判別式が0ならば  (条件4)

              実数解は1つ          (文4)

「係数aが0でなく、判別式が負ならば  (条件5)

              複素数解が2つ         (文5)

これらは全て複数のif文を組み合わせて判断を行わなければ解けない。つまりswitch文では書けないということである。

ではプログラムを書いてみよう。

 

解答

#include <stdio.h>

#include <math.h>

 

void main(void)

{

             double a,b,c,D,x1,x2,x3,x4;

             printf("ax^2+bx+c=0の実数a,b,cを入力してください\n");

            

             scanf("%lf %lf %lf",&a,&b,&c);

             D = b*b -4*a*c;

             x1 = (-b + sqrt(D))/(2*a);

             x2 = (-b - sqrt(D))/(2*a);

 

             if(a == 0.0 && b == 0.0)

             {

                           printf("解はありません\n");

             }

             else if(a == 0.0 && b != 0.0)

             {

                           x1 = -c/b;

                           printf("解は%lfです\n",x1);

             }

             else if (D >0.0)

             {

                           printf("解は%lf%fです\n",x1,x2);

             }

             else if(D == 0)

             {

                           printf("解は重解となり%fです\n",x1);

             }

             else

             {

                           x3 = -b/(2*a);

                           x4 = sqrt(-D);

                           printf("解は%lf+i%f%lf - i%fです\n",x3,x4,x3,x4);

             }

}

 

列挙型を用いたif

enum {Female,Male} sex;

 

if(条件= = )

{

              sex = Male;

}

else

{

              sex = Female;

}

これで、列挙変数sexMaleFemaleしか取らないことを、文法的にきちんと宣言した。

列挙変数は列挙子に明示的に値が与えられなければ、書かれた順序に「0」から始まる順序数(ordinal number)となる。よって、この例ではFemaleは0、Maleは1となるので、条件が真ならば、sexMaleとなる。

 

例題4.8列挙型enum {Female,Male}sex;scanfで読み込んだ値を代入し、出力するプログラムを作成しよう。

 

解説 列挙型enum {Female,Male}sex;に入力するには、0または1をキーボードから打つ。

出力するには

printf(“%c”,(self_data.sex = = 0)? ‘F’:’M’;)を用いる。これは3項演算子と呼ばれるもので、次のように用いる。

              式1?式2:式3

の形式をとり、式1が真ならば、式2の値が式の値となり、偽ならば式3が式の値となる。

解答 

#include <stdio.h>

#include <string.h>

 

void main(void)

{

             enum {Female,Male}sex;

 

             printf(" 性別> \n");

             scanf("%d",&sex);

             printf("\n SEX\n");

             printf("%3c\n",(sex==0)? 'F':'M');

}

 

C入門 / 次の章