3.処理の選択

Copyright(C) 13Jan2003 coskx

このページでは「処理の選択」の記述方法を解説する。
ここで修得して欲しい内容は以下の通りである。
1.if文による処理の制御が分かる。
2.if-else文による処理の制御(二者択一)が分かる。
3.if-else if-...else文による処理の制御について,最初に真になったところが実行されること(多者択一)を理解する。
4.switch case文も多者択一であることを理解する
5.「処理の繰返し」と「処理の選択」が合成された処理の流れを追跡することができる。
6.課題の実現方法を考え,「処理の繰返し」「処理の選択」を組み合わせてプログラムを作成することができる。



 3.1  if文 (条件実行)


「ある条件Aが成り立った時だけある処理Bを行なう」という表現の記述方法である。日本語での表 現例を次に示す。

日本語の例 C言語風表現例 C言語での表現例
天気予報が雨なら傘を持
って出かける。
if (天気予報が雨) {
    傘を持つ
}
出かける
 
countの値が5の倍数なら
コンソール画面で改行を
行なう。
if (countの値が5の倍数) {
    コンソール画面で改行を行なう
}
if (counter%5==0) {
    printf("\n");
}


次のプログラムは1から10までの数について3の倍数を見つけるプログラムである。3の倍数が見つかったら,「3の倍数」と表示すること にしている。

List 3.1.1 if文 

#include <stdio.h>

int main()
{
    int num;
    for (num=1;num<=10;num++) {
        printf("%3d:",num);
        if (num%3==0) {
            printf("3の倍数です");
        }
        printf("\n");
    }
    return 0;
}

実行結果
  1:
  2:
  3:3の倍数です
  4:
  5:
  6:3の倍数です
  7:
  8:
  9:3の倍数です
 10:
補足

if (num%3==0) {
    printf("3の倍数です");
}

これの意味は「もし,numの値を3で割ったあまりが0だったら
(numの値が3の倍数だったら)「3の倍数です」と表示する」という意味となる。

条件が成り立った場合に行なう処理が1文だけなので
if (num%3==0) printf("3の倍数です");
と記述可能である。

条件の記述について

「aはbに等しい」という条件は「a=b」ではなく「a==b」と書く。
「a=b」では,bの値をaに代入するという意味になってしまう。

   if(a=b) {
という表現は文法上誤りではないので,
コンパイルエラーにならないので注意が必要である。

「if(a=b) { 」はbの値をaに代入し,aの値が0でなかったらの意味になる。



次のプログラムは数当てゲームである。コンピュータが内部に持つ秘密の番号(1から100までの整数のうちの1つ)を人間が当てるゲーム である。人間が適 当な答えを与えると「大きすぎ」とか「小さすぎ」とコンピュータが答え,当たるまでこれを繰り返す。当たったら,何回の試行で当たったか を表示する。

List 3.1.2 数当てゲーム

#include <stdio.h>
#include <stdlib.h>

int main()
{
    int secretNumber; /*コンピュータの秘密の数*/
    int yourNumber;   /*人間が入力した値をしまうところ*/
    int counter;      /*試行回数カウンタ*/
    /*1から100までの間の乱数をセット*/
    secretNumber=rand()%100+1;
    printf("=== 数当てゲームです。 ===\n");
    printf("私は1から100までの整数を1つ隠しています。\n");
    printf("整数を1つ入力して当ててください ");
    scanf("%d",&yourNumber);
    counter=1;
    while (yourNumber!=secretNumber) { /*「!=」は「等しくない」の意味*/
        if (yourNumber<secretNumber) {
            printf("%d回目 %dは小さすぎです\n",counter,yourNumber);
        }
        if (secretNumber<yourNumber) {
            printf("%d回目 %dは大きすぎです\n",counter,yourNumber);
        }
        printf("もう一度,整数を1つ入力して当ててください ");
        scanf("%d",&yourNumber);
        counter++;
    }
    printf("%d回であたりました\n",counter);
    return 0;
}

実行結果
=== 数当てゲームです。 ===
私は1から100までの整数を1つ隠しています。
整数を1つ入力して当ててください 50
1回目 50は大きすぎです
もう一度,整数を1つ入力して当ててください 25
2回目 25は小さすぎです
もう一度,整数を1つ入力して当ててください 38
3回目 38は小さすぎです
もう一度,整数を1つ入力して当ててください 44
4回目 44は大きすぎです
もう一度,整数を1つ入力して当ててください 41
5回目 41は小さすぎです
もう一度,整数を1つ入力して当ててください 42
6回であたりました
補足 「secretNumber=rand()%100+1」 について

rand()は1から32767までの間の乱数を1つは発生する文(本当 は関数と呼ぶ)である。
rand()%100;  は0から99までの数の1つになる
rand()%100+1; は1から100までの数の1つになる

条件の記述について 

「!=」は「≠」の意味である
ほかにも
「<=」は「≦」の意味であり
「>=」は「≧」の意味である。

練習3.1

次のプログラムの実行結果を予想しなさい。
List 3.1.3 forループとifのプログラム

#include <stdio.h>

int main()
{
    int i;
    for (i=0;i<8;i++) {
        printf("%d:\n",i);
        if (i%2==0) {
            printf("Hello.\n");
        }
        if (i%3==0) {
            printf("What's up?\n");
        }
        if (5<i) {
            printf("I understand.\n");
        }
    }
    return 0;
}

実行結果の予 想1 実行結果の予 想2 実行結果の予 想3
0: Hello. What's up?
1:
2: Hello.
3: What's up?
4: Hello.
5:
6: Hello. What's up? I understand.
7: I understand.
0:
1:
2:
Hello.
3:
What's up?
4:
Hello.
5:
6:
Hello.
What's up?
I understand.
7:
I understand.
0:
Hello.
What's up?
1:
2:
Hello.
3:
What's up?
4:
Hello.
5:
6:
Hello.
What's up?
I understand.
7:
I understand.

複数の条件の取り扱い 条件の記述について

数学の表現

より正確な数学の表現

C言語の表現

a<bかつc<d

a<b and c<b

a<b && c<b (「a<b & c<b」でないことに注意

a<bまたはc<d

a<b or c<b

a<b || c<b

練習3.2

次の表現をC言語の表現に直しなさい
a,bは整数として
a<-3,6<aならbを1増加させる

(1)

(2)

(3)

if (a < -3, 6 < a) {
    b++;
}
if (a < -3 && 6 < a) {
    b++;
}
if (a < -3 || 6 < a) {
    b++;
}
a,bは整数として
-3≦a≦6ならbを1増加させる

ただし,
「<=」は「≦」の意味であり,「>=」は「≧」の意味である。

(1)

(2)

(3)

if (-3 <= a <= 6) {
    b++;
}
if (-3 <=a && a <= 6) {
    b++;
}
if (-3 <= a || a <= 6) {
    b++;
}

 課題3 その1

(1)キーボードから1つの整数を読み込み,その値が偶数なら「even number」と表示するプログラムを作りなさい。
偶数かどうかは2で割ったあまりが0であるかどうかを検査すればよい。 (p03ex01.c)
検証は,プログラムを5回動かして,1,2,3,4,5の5個の値について行いなさい。

実行例

>p03ex01.exe
1

>p03ex01.exe
2
even number

>p03ex01.exe
3

>p03ex01.exe
4
even number



 3.2  if else 文 (条件による処理の二者択一)

「ある条件Aが成り立ったら処理Bを行ない,そうでなかったら処理Cを行なう」という表現の記 述方法である。日本語での表現例を次に示す。
日本語の例 C言語風表現例 C言語での表現例
天気予報が雨なら映画館
でデートし,
そうでなければディズニ
ーランドでデートする。
if (天気予報が雨) {
    映画館でデート
} else {
    ディズニーランドでデート
}
 
ある数numberが奇数なら
3倍して1を加え,
そうでなかったら2で割
り,numberの値とする。

if (numberが奇数) {
    numberにnumber*3+1を代入
} else {
    numberにnumber/2を代入
}

if (number%2==1) {
    number=3*number+1;
} else {
    number=number/2;
}


次のプログラムはキーボードから入力された正整数に対して次の処理を行なう。
正整数が奇数なら3倍して1を加え,そうでなかったら2で割る。そうして出来た新しい正整数に対して同じ処理を繰り返す。
そして1になるまでこれを続ける。
表示では,何回目の処理かがわかるようにし,5つごとに改行する。

List 3.2.1 if else文

#include <stdio.h>

int main()
{
    int number,counter;
    printf("正整数を入力してください ");
    scanf("%d",&number);
    counter=0;
    printf("%d [%d] ",number,counter);
    while (number!=1) {
        if (number%2==1) {
            number=3*number+1;
        } else {
            number=number/2;
        }
        counter++;
        printf("%d [%d] ",number,counter);
        if (counter%5==4) {
            printf("\n");
        }
    }
    printf("\n");
    return 0;
}

実行結果(2回)

正整数を入力してください 20
20 [0] 10 [1] 5 [2] 16 [3] 8 [4]
4 [5] 2 [6] 1 [7]

正整数を入力してください 30
30 [0] 15 [1] 46 [2] 23 [3] 70 [4]
35 [5] 106 [6] 53 [7] 160 [8] 80 [9]
40 [10] 20 [11] 10 [12] 5 [13] 16 [14]
8 [15] 4 [16] 2 [17] 1 [18]

補足

if (number%2==1) {
    
number=3*number+1;
} else {
    
number=number/2;
}

この部分の意味は次のようになる。
numberが奇数なら
    number=3*number+1
そうでなかったら
    number=number/2

条件が成り立った場合に行なう処理あるいは成り立たなかった場合に行なう 処理が1文だけなので
if (number%2==1) number=3*number+1;
else number=number/2;

という書き方もある。

練習3.3

次のプログラムの実行結果を予想しなさい。
List 3.2.2 forループとif-elseのプログラム

#include <stdio.h>

int main()
{
    int i;
    for (i=0;i<8;i++) {
        printf("%d:\n",i);
        if (i%2==0) {
            printf("Hello.\n");
        } else {
            printf("What's up?\n");
        }
        if (5<i) {
            printf("I understand.\n");
        }
    }
    return 0;
}

実行結果の予 想1 実行結果の予 想2 実行結果の予 想3
0:
Hello.
What's up?
1:
2:
Hello.
3:
What's up?
4:
Hello.
5:
6:
Hello.
What's up?
I understand.
7:
I understand.
0:
Hello.
1:
What's up?
2:
Hello.
3:
What's up?
4:
Hello.
5:
What's up?
6:
Hello.
I understand.
7:
What's up?
I understand.
0:
Hello.
1:
2:
Hello.
3:
What's up?
4:
Hello.
5:
6:
Hello.
I understand.
7:
I understand.

 課題3  その2

(2)キーボードから1つの整数を読み込み,その値が偶数なら「even number」,そうでないなら「odd number」と表示するプログラムを作りなさい。 (p03ex02.c)
検証は,
プログラムを5回動かし て,1,2,3,4,5の5個の値について行いなさい。

 

 3.3  if else if else文 (条件による処理の多者択一)

「ある条件Aが成り立ったら処理Bを行ない,そうでなく条件Cが成り立ったら処理Dを行ない, いずれでもなかったら処理Eを行なう」という表現の記述方法である。日本語での表現例を次に示す。
日本語の例 C言語風表現例 C言語での表現例
天気予報が雨なら映画館でデートし,
そうでなく,資金が十分だったら
ディズニーランドでデートし,
いずれでもなかったら
上野公園でデートする。
if (天気予報が雨) {
    映画館でデート
} else if (資金はOK) {
    ディズニーランドでデート
} else {
    上野動物園でデート
}
 
試験の点scoreが,
90点以上だったら
 「チョー立派」と表示し,
そうでなく80点以上だったら
 「立派」と表示し,
そうでなく70点以上だったら
 「頑張ったね」と表示し,
そうでなく60点以上だったら
 「まあまあだね」と表示し,
それ以外だったら
 「次がんばってね」と表示する。

if (試験の点scoreが90点以上) {
    「チョー立派」と表示する
} else if (試験の点scoreが80点以上) {
    「立派」と表示する
} else if (試験の点scoreが70点以上) {
    「がんばったね」と表示する
} else if (試験の点scoreが60点以上) {
    「まあまあだね」と表示する
} else {
    「次がんばってね」と表示する
}

if (90<=score) {
    printf("チョー立派\n");
} else if (80<=score) {
    printf("立派\n");
} else if (70<=score) {
    printf("がんばったね\n");
} else if (60<=score) {
    printf("まあまあだね\n");
} else {
    printf("次がんばってね\n");
}

if (天気予報が雨) {
    映画館でデート
} else if (資金はOK) {
    ディズニーランドでデート
} else {
    上野動物園でデート
}
というように使う。択一選択なので「天気予報が雨」で「資金がOK」の場合,映画館とディズニーランドの両方へ行くことはなく,最初に条 件が成立した映画館でデートである。
記述の順番に意味があり,最初に条件が成立したところの処理を行なう。
もし
if (資金はOK) {
    ディズニーランドでデート
} else if (天気予報が雨) {
    映画館でデート
} else {
    上野動物園でデート
}
ならば,「天気予報が雨」で「資金がOK」の場合は,雨でもディズニーランドでデートになる。

また 「else if (...)」はいくつあってもかまわないし,「else」の部分はなくてもよい。

次のプログラムは試験結果の評価プログラムである。試験の点数を評価に変換します。
評価は以下のように行なわれる。
85点以上      優(A)
70点以上84点まで  良(B)
60点以上69点まで  可(C)
59点以下     不可(D)

List 3.3.1 試験結果の評価

/*試験結果の評価を行ないます*/
/*得点を入力すると評価を表示します。*/
/*負の値が入るまで,連続して評価を行ないます。*/
/*   評価   */
/*85点以上      優(A)*/
/*70点以上84点まで  良(B)*/
/*60点以上69点まで  可(C)*/
/*59点以下     不可(D)*/
#include <stdio.h>

int main()
{
    int score; /*得点*/
    printf("試験結果の評価を行ないます\n");
    printf("得点を入力すると評価を表示します。\n");
    printf("負の値が入るまで,連続して評価を行ないます。\n");
    printf("得点 >> ");
    scanf("%d",&score);
    while (0<=score) {
        if (85<=score) {
            printf("%d  優(A)\n",score);
        } else if (70<=score) {
            printf("%d  良(B)\n",score);
        } else if (60<=score) {
            printf("%d  可(C)\n",score);
        } else {
            printf("%d 不可(D)\n",score);
        }
        printf("得点 >> ");
        scanf("%d",&score);
    }
    printf("お疲れ様でした\n");
    return 0;
}

実行結果
試験結果の評価を行ないます
得点を入力すると評価を表示します。
負の値が入るまで,連続して評価を行ないます。
得点 >> 95
95  優(A)
得点 >> 81
81  良(B)
得点 >> 65
65  可(C)
得点 >> 57
57 不可(D)
得点 >> -1
お疲れ様でした
補足

if else if・・・の流れは次のようになる。



if else ifの羅列においては最初に条件が真になった処理が行なわれるため,条件をすべて書かな
くても良い場合がある。
例えば2番目では
70<=score&&score<85
ではなく単に
70<=score
でよい。85<=scoreについての処理はすでに行なわれているからである。

データ数が固定でない場合,ループから抜け出すためにデータの終わりのし るしとして,データには含まれないはずの値(ここでは-1)を使うことは良く行なわれる。

練習3.4

次のプログラムの実行結果を予想しなさい。
List 3.3.2 forループとif-elseifのプログラム    

#include <stdio.h>

int main()
{
    int i;
    for (i=0;i<8;i++) {
        printf("%d:\n",i);
        if (i%2==0) {
            printf("Hello.\n");
        } else if (i%3==0) {
            printf("What's up?\n");
        }
        if (5<i) {
            printf("I understand.\n");
        }
    }
    return 0;
}

実行結果の予 想1 実行結果の予 想2 実行結果の予 想3
0:
Hello.
What's up?
1:
2:
Hello.
3:
What's up?
4:
Hello.
5:
6:
Hello.
What's up?
I understand.
7:
I understand.
0:
1:
2:
Hello.
3:
What's up?
4:
Hello.
5:
6:
Hello.
What's up?
I understand.
7:
I understand.
0:
Hello.
1:
2:
Hello.
3:
What's up?
4:
Hello.
5:
6:
Hello.
I understand.
7:
I understand.

 課題3 その3

(3)キーボードから2整数を読み込み,大小関係を表示するプログラムを作りなさい。  (p03ex03.c)
ただし実行例が次のようになることを検証しなさい。

<<実行例1>>
2数を入力--> 17 7
17 > 7

<<実行例2>>
2数を入力--> -17 7
-17 < 7

<<実行例3>>
2数を入力--> 100 100
100 = 100

(4)キーボードから正整数nを読み込み,実行例のように長さnの棒を「*」で描くプログラムを作りなさい。(p03ex04.c)
ただし,棒の左端から5,10,15,20...の位置は「*」でなく「-」で描かれるようにします。
プログラムを2回動かして,実行例が次のようになることを検証しなさい。

<<実行例1>>
n= 23
****-****-****-****-***

<<実行例2>>
n= 38
****-****-****-****-****-****-****-***

     ヒント

(5)キーボードから複数個の正整数値を読み込み,合計値と平均値(小数第1位まで)を表示す るプログラムを作りなさい。(p03ex05.c)
ただし正整数値をいくつ受け取るかは,プログラミングの時点ではわからないものとする。そして負整数値が入力されたらデータはもうなく なったと判断することとし,負の数は計算には使用しないこととする。また正整数値は1つも入力されないこともあり,このときは最初から負
整数値が入力される。このような場合には合計 値と平均値が求められないので,「no data」と表示して終了すること。
1から10までの整数の合計と平均値,2,4,8,16,32の整数の合計と平均値の算出を検証しなさい。また,最初から-1を入力し, 合計値と平均値は求められない意味の「no data」と表示されることも検証しなさい。

<<実行例1>>
1
2
3
4
5
6
7
8
9
10
-1
sum total 55
mean 5.5

<<実行例2>>
2
4
8
16
32
-1
sum total 62
mean 12.4

<<実行例3>>
-1
no data

ヒント

(6)キーボードから正整数nを読み込み,次の4つに分類し表示するプログラムを作りなさい。(p03ex06.c)
1) 6の倍数 a multiple of 6
2) 2の倍数だが3の倍数ではない a multiple of 2 but not a multiple of 3
3) 3の倍数だが2の倍数ではない a multiple of 3 but not a multiple of 2
4) 2の倍数でも3の倍数でもない not a multiple of 2 or a multiple of 3

次の4つの場合で検証することとし,実行例の通りの表示になるようにしなさい。

<<実行例1>>
n=38
38: a multiple of 2 but not a multiple of 3
<<実行例2>>
n=42
42: a multiple of 6
<<実行例3>>
n=53
53: not a multiple of 2 or a multiple of 3
<<実行例4>>
n=63
63: a multiple of 3 but not a multiple of 2


(7)int型変数xをループカウンタとしてforを使ったプログラム で,ループ中にy1,y2,y3,y4を作り,以下に示す表を作りなさい。(p03ex07
.c)
これ以外の変数を用いてはいけない。
ただし,xの範囲は1≦x≦100としなさい。
ヒント
y1,y4はxが偶数か奇数に分けて,xの値より求めればよい。y2,y3はxを 4で割ったあまりで分類

  x     y1      y2        y3          y4
  1      5       1         1           5
  2     10       2         2           0
  3      5       4         3          15
  4     10       3         2           0
  5      5       5         1          25
  6     10       6         2           0
  7      5       8         3          35
  8     10       7         2           0
  9      5       9         1          45
 10     10      10         2           0
 11      5      12         3          55
 12     10      11         2           0
  :      :       :         :           :


(8)正整数nを入力し,nに応じて「*」「-」で以下の模様を描くプログラムを作りなさい。(p03ex08.c)
nは20まで対応しなさい。
検証はn=1,2,3,5,10,20で行ないなさい。

n=1

n=2

n=3

n=4

n=5

n=6

n=7

n=8

*

**
**

***
*-*
***

****
*--*
*--*
****

*****
*---*
*---*
*---*
*****

******
*----*
*----*
*----*
*----*
******

*******
*-----*
*-----*
*-----*
*-----*
*-----*
*******

********
*------*
*------*
*------*
*------*
*------*
*------*
********

(9)正整数nを入力し,nに応じて「*」「-」で以下の模様を描くプログラムを作りなさい。 (p03ex09.c)
nは20まで対応しなさい。検証はn=1,2,3,5,10,20で行ないなさい。

n=1

n=2

n=3

n=4

n=5

n=6

n=7

n=8

*

**
**

***
***
***

****
****
****
****

*****
*****
**-**
*****
*****

******
******
**--**
**--**
******
******

*******
*******
**---**
**---**
**---**
*******
*******

********
********
**----**
**----**
**----**
**----**
********
********

(10)二次方程式 x2+bx+c=0 において,bとcをキーボードから実数型変数に読み取って,解くプログラムを作りなさい。(p03ex10.c)
ただし,下記の実行例のように「>>」の後にカンマ区切りでa,bを入力しなさい。そして,下記の実行例のように
(a)2つの実数解を持つ場合は,2つの解を数値で表示
(b)重解を持つ場合は,解を数値で表示
(c)2つの虚数解を持つ場合は,実部と虚部をわかるように表示
することとし,下に示す3つの実行例で検証しなさい。

2次方程式についてのヒント

平方根の計算をするためには
#include <stdio.h>
#include <math.h>
を書いておくこと。
また
double xx,yy;
と宣言されていれば
yy=sqrt(xx);
でxxの平方根がyyに求められる。
例えば
xx=16.0;
yy=sqrt(xx);
ならば,yyには4.0が保存される。

scanfの使い方について,C.ライブラリ関数の説明の scanfを参照しなさい。

実行の様子の例 意味
b,cを入力してください >>4,3
b=4.000000 c=3.000000
real roots: -1.000000, -3.000000

b,cを入力してください >>4,4
b=4.000000 c=4.000000
double root: -2.000000

b,cを入力してください >>4,5
b=4.000000 c=5.000000
complex roots: Real -2.000000, Imaginary 1.000000

x2+4x+3=0
2つの実数解:-1, -3


x2+4x+4=0
重解:-2


x2+4x+5=0
2つの虚数解:-2±i

追跡課題(実行結果を 見ないで,実行結果を予想してみよう)

(1)ループと選択の複合プログラム例(100から200までの素数)

100から200までの素数とその個数を求めるプログラム。
素数とは2以上の整数のうち,2とその数自身以外に約数を持たない数のことである。

List 3.3.3 100から200までの素数とその個数を 求めるプログラム

/*********** 100から200までの素数  ***************
100から200までの素数候補を検査し,素数を探す。
ある素数候補の検査の方法は次のとおりである。
2から素数候補まで約数を探して行き,初めて見つかった
約数が素数候補だったらその候補は素数である。
例えば
(1)113を素数候補とした時の約数を2,3,4,...のように順に
探して行くと最初に見つかる約数は113である。だから113
は素数である。
(2)143を素数候補とした時の約数を2,3,4,...のように順に
探して行くと最初に見つかる約数は11である。だから143
は素数ではない。
*************************************************/
#include <stdio.h>

int main()
{
    int k;/*素数候補*/
    int min=100;/*検査対象の最小値*/
    int max=200;/*検査対象の最大値*/
    int n;/*約数候補*/
    int count=0;/*見つかった素数の個数*/
    printf("%dから%dまでの素数を求める。\n",min,max);
    for (k=min;k<=max;k++) {
        n=2;/*約数候補の初期値*/
        while (k%n!=0) n++;
        if (n==k) { /*最初に見つかった約数が素数候補に等しい時*/
            printf("%4d ",k);
            count++;
            if (count%10==0) {
                printf("\n");
            }
        }
    }
    if (count%10!=0) printf("\n");
    printf("素数は%d個見つかりました。\n",count);
    return 0;
}

実行結果
100から200までの素数を求める。
 101  103  107  109  113  127  131  137  139  149
 151  157  163  167  173  179  181  191  193  197
 199
素数は21個見つかりました。

 

(2)ループと選択の複合プログラム例(200から240ま での整数の素因数分解)

200から240までの整数の素因数分解を求めるプログラム。

List 3.3.4 200から240までの素因数分解を求めるプログラム

/********  200から240までの素因数分解  ***********
ある数の素因数分解を求めるには
「2で割りきれるたら2で割る」を繰り返す。
「3で割りきれるたら3で割る」を繰り返す。
「4で割りきれるたら4で割る」を繰り返す。
    :
これを繰り返して,答えが1になるまで繰り返すと素因数
分解が完了する。
例えば180を因数分解することを考える。
素因数候補を2とする
180%2=0 割り切れたので 180/2=90 .....2は素因数
90%2=0  割り切れたので 90/2=45  .....2は素因数
45%2=1  もう割り切れないので素因数候補を3とする
45%3=0  割り切れたので 45/3=15  .....3は素因数
15%3=0  割り切れたので 15/3=5   .....3は素因数
5%3=2   もう割り切れないので素因数候補を4とする
5%4=1   割り切れないので素因数候補を5とする
5%5=1   割り切れたので 5/5=1    .....5は素因数
割り算の答えが1になったので素因数分解完了
結局 180 = 2*2*3*3*5
**************************************************/
#include <stdio.h>

int main()
{
    int k;/*素因数分解対象数*/
    int x;/*素因数分解対象数のコピー(作業用)*/
    int n;/*素因数候補*/
    int count;/*素因数個数*/
    for (k=200;k<=240;k++) {
        x=k;
        n=2;/*素因数候補の初期値は2*/
        count=0;
        printf("%d = ",x);
        while (x!=1) {
            if (x%n==0) { /*xがnで割り切れた場合。nは素因数*/
                x/=n;
                count++; /*素因数個数をカウントアップ*/
                if (count==1) { /*初めて見つかった素因数の時*/
                    printf("%d",n);
                } else { /*二つ目以降の素因数*/
                    printf("*%d",n);
                }
            } else {
                n++; /*次の素因数候補*/
            }
        }
        if (count==1) { /*素因数が1つしか見つからなかった*/
            printf(" 素数");
        }
        printf("\n");
    }
    return 0;
}

実行結果
200 = 2*2*2*5*5
201 = 3*67
202 = 2*101
203 = 7*29
204 = 2*2*3*17
205 = 5*41
206 = 2*103
207 = 3*3*23
208 = 2*2*2*2*13
209 = 11*19
210 = 2*3*5*7
211 = 211 素数
212 = 2*2*53
213 = 3*71
214 = 2*107
215 = 5*43
216 = 2*2*2*3*3*3
217 = 7*31
218 = 2*109
219 = 3*73
220 = 2*2*5*11
221 = 13*17
222 = 2*3*37
223 = 223 素数
224 = 2*2*2*2*2*7
225 = 3*3*5*5
226 = 2*113
227 = 227 素数
228 = 2*2*3*19
229 = 229 素数
230 = 2*5*23
231 = 3*7*11
232 = 2*2*2*29
233 = 233 素数
234 = 2*3*3*13
235 = 5*47
236 = 2*2*59
237 = 3*79
238 = 2*7*17
239 = 239 素数
240 = 2*2*2*2*3*5

 

 3.4  switch case文 (値による処理の多者択一)

「ある変数xの値がAなら処理Bを行ない,Cだったら処理Dを行ない,いずれでもなかったら処 理Eを行なう」という表現の記述方法である。
次のプログラムでは入力された-2から2までの値により,the day before yesterday から the day after tmorrow までを表示する。
もし指定した-2から2以外の値が入力されたら unknown と表示する。
defaultとはどれにも当てはまらない場合の意味である。

List 3.4.1 昨日,今日,明日

#include <stdio.h>

int main()
{
    int day;
    printf("-2から2までの数を入力してください >>");
    scanf("%d",&day);
    switch (day) {
    case -2:
        printf("the day before yesterday\n");
        break;
    case -1:
        printf("yesterday\n");
        break;
    case 0:
        printf("today\n");
        break;
    case 1:
        printf("tomorrow\n");
        break;
    case 2:
        printf("the day after tomorrow\n");
        break;
    default:
        printf("unknown\n");
        break;
    }
    return 0;
}

実行結果(3回の異なる実行結果)

-2から2までの数を入力してください >>2
the day after tomorrow

-2から2までの数を入力してください >>0
today

-2から2までの数を入力してください >>3
unknown

補足

switch (XXX) [
case ◯:
    処理(複数行記述できる)
    break;
case △:
    処理(複数行記述できる)
    break;
case □:
    処理(複数行記述できる)
    break;
default:
    処理(複数行記述できる)
    break;
}

の形になる

switch case文は字下げ(インデント)が規則どおりにならない。

 3.5  三項演算子 (条件による値の二者択一)

「a<bならば変数xの値はpにして,そうでなかったら変数xの値はqにする」という操 作の記述方法である。

次の2つの表現は同じ意味となる。
if else による表現 三項演算子による表現

#include <stdio.h>

int main()
{
    int a,b,x;
    printf("a = ");
    scanf("%d",&a);
    printf("b = ");
    scanf("%d",&b);
    if (a<b) {
        x=1;
    } else {
        x=-1;
    }
    printf("x=%d\n",x);
    return 0;
}

#include <stdio.h>

int main()
{
    int a,b,x;
    printf("a = ");
    scanf("%d",&a);
    printf("b = ");
    scanf("%d",&b);
    x = a<b ? 1: -1;
    printf("x=%d\n",x);
    return 0;
}

 

 3.6 ここまでの内容の修得確認

練習3.5

次のプログラムの実行結果を予想しなさい。
(1)
#include "stdio.h"

int main()
{
    int x,sum,sum2;
    sum=0;
    sum2=0;
    for ( x=1; x<=8; x++ ) {
        sum=sum+x;
        sum2=sum2+x*x;
        printf("x= %d sum= %2d sum2= %3d\n",x,sum,sum2);
    }
    printf("sum  = %d\n",sum);
    printf("sum2 = %d\n",sum2);
    return 0;
}
(2)
#include "stdio.h"

int main()
{
    int x,sum2;
    x=0;
    sum2=0;
    while ( sum2<=200 ) {
        x++;
        sum2=sum2+x*x;
        printf("x= %d sum2= %3d\n",x,sum2);
    }
    printf("The first value = %d\n",x);
    return 0;
}
(3)
#include "stdio.h"

int main()
{
    int day,x,sum;
    sum=0;
    for ( day=1,x=1; day<=7; day++,x=x*2 ) {
        sum=sum+x;
        if (4<=day) {
            sum=sum+20;
        }
        printf("day= %d sum= %4d\n",day,sum);
    }
    printf("The total number = %d\n",sum);
    return 0;
}
(4)
#include "stdio.h"

int main()
{
    int day,x,sum;
    sum=0;
    for ( day=1,x=1; day<=7; day++,x=x*2 ) {
        sum=sum+x;
        if (day%2==1) {
            sum=sum+5;
        } else {
            sum=sum+8;
        }
        printf("day= %d sum= %4d\n",day,sum);
    }
    printf("The total number = %d\n",sum);
    return 0;
}
(5)
#include "stdio.h"

int main()
{
    int day,x,sum;
    sum=0;
    for ( day=1,x=1; day<=7; day++,x=x*2 ) {
        sum=sum+x;
        if (day<3) {
            sum=sum+5;
        } else if (day<5) {
            sum=sum+10;
        } else if (day<7) {
            sum=sum+4;
        } else {
            sum=sum+2;
        }
        printf("day= %d sum= %4d\n",day,sum);
    }
    printf("The total number = %d\n",sum);
    return 0;
}
(6)
#include "stdio.h"

int main()
{
    int day,x,sum;
    sum=0;
    for ( day=1,x=1; day<=7; day++,x=x*2 ) {
        sum=sum+x;
        switch (day) {
            case 2:
                sum=sum+5;
                break;
            case 5:
                sum=sum+10;
                break;
            default:
                sum=sum+2;
                break;
        }
        printf("day= %d sum= %4d\n",day,sum);
    }
    printf("The total number = %d\n",sum);
    return 0;
}
(7)
#include "stdio.h"

int main()
{
    int x,y,len;
    len=5;
    for ( x=1; x<=len; x++ ) {
        if (x==1||x==len) {
            for ( y=1; y<=len; y++ ) {
                putchar('*');
            }
        } else {
            for ( y=1; y<=len; y++ ) {
                if (y==1||y==len) {
                    putchar('*');
                } else {
                    putchar('+');
                }
            }
        }
        putchar('\n');
    }
    return 0;
}

 課題3 その4

(11)a,b,cは整数であり,500≦a<b<c≦1000を満たしている。 a,b,cを3辺の長さとする三角形のうち直角三角形になるものをすべてあげ,総個数を求めるプログラムを作成しなさい。 (p03ex11.c)
三重ループで a2 + b2 = c2 であるかどうか総当りで調べることにします。
表示は,つぎの実行例のようにしなさい。
(Total number of right triangles found は「見つかった直角三角形の総数」)

実行例
 1:  500  525  725
 2:  501  668  835
 3:  504  550  746
 4:  504  672  840
 5:  504  703  865
 6:  504  810  954
 7:  507  676  845
 8:  510  680  850
 9:  510  792  942
10:  513  684  855
11:  516  688  860
12:  519  692  865
13:  520  546  754
14:  520  576  776
15:  520  765  925
16:  522  696  870
17:  522  760  922
18:  525  700  875
19:  528  605  803
20:  528  630  822
21:  528  704  880
22:  531  708  885
23:  532  624  820
24:  533  756  925
25:  534  712  890
26:  537  716  895
27:  540  567  783
28:  540  629  829
29:  540  720  900
30:  540  819  981
31:  543  724  905
32:  546  728  910
33:  549  732  915
34:  552  736  920
35:  555  572  797
36:  555  740  925
37:  558  744  930
38:  560  588  812
39:  560  684  884
40:  560  702  898
41:  561  748  935
42:  564  752  940
43:  567  756  945
44:  570  760  950
45:  573  764  955
46:  576  660  876
47:  576  768  960
48:  579  772  965
49:  580  609  841
50:  580  741  941
51:  582  776  970
52:  585  648  873
53:  585  780  975
54:  588  784  980
55:  591  788  985
56:  594  608  850
57:  594  792  990
58:  595  600  845
59:  597  796  995
60:  600  630  870
61:  600  800 1000
62:  612  759  975
63:  615  728  953
64:  616  663  905
65:  616  735  959
66:  620  651  899
67:  621  672  915
68:  624  715  949
69:  638  720  962
70:  640  672  928
71:  650  720  970
72:  660  693  957
73:  680  714  986
74:  696  697  985
Total number of right triangles found = 74

 

(文章課題)次の内容をまとめてレポートにしなさい。ただし,初めの2行(ファイル名,ID,出席番号,氏名)は,これまでのプログラム と同様な書式で書くこと。 (p03.txt)

1) List 3.1.1において,forループ中で,

        printf("%3d:",num);
        if (num%3==0) {
            printf("3の倍数です");
        }
        printf("\n");

となっているが,

        printf("%3d:",num);
        if (num%3==0) {
            printf("3の倍数です");
            printf("\n");
        }

ではうまく動作しない。その理由を説明しなさい。


2)List 3.3.1 で,
        printf("得点 >> ");
        scanf("%d",&score);
が2か所に書いてあるが,どうして2か所必要なのか説明しなさい。


3)List 3.3.4 で

            if (x%n==0) { /*xがnで割り切れた場合。nは素因数*/
                x/=n;
                count++; /*素因数個数をカウントアップ*/
                if (count==1) { /*初めて見つかった素因数の時*/
                    printf("%d",n);
                } else { /*二つ目以降の素因数*/
                    printf("*%d",n);
                }
            } else {
                n++; /*次の素因数候補*/
            }

のところで

            if (x%n==0) { /*xがnで割り切れた場合。nは素因数*/
                x/=n;
                count++; /*素因数個数をカウントアップ*/
                printf("*%d",n);
            } else {
                n++; /*次の素因数候補*/
            }

このように簡素化すると表示が不自然になる。理由を説明しなさい。