C プログラミング (C Programming)

[2017/09/27, H.Aman]
[← 演習のページへ戻る]

サンプルプログラム 4 の内容

三つの整数を読み込み,三つとも同じかどうか, それとも二つは同じかどうか, あるいはすべて異なるか,を表示する.
 1:   #include <stdio.h>
 2:  	
 3:   int main(void){
 4: 	 int x, y, z;
 5:
 6:      printf("整数を三つ入力してください:");
 7:      scanf("%d %d %d", &x, &y, &z);
 8:  
 9:      if ( x == y && y == z ){
10:         printf("三つは等しいです\n");
11:      }
12:      else{
13:         if ( x == y || y == z || z == x ){
14:            printf("二つは等しいです\n");
15:         }
16:         else{
17:            printf("すべて異なっています\n");
18:         }
19:      }
20:
21:      return 0;
22:   }

9-19 行目:外側の if ... else 文

 8:  
 9:      if ( x == y && y == z ){
10:         printf("三つは等しいです\n");
11:      }
12:      else{
13:         if ( x == y || y == z || z == x ){
14:            printf("二つは等しいです\n");
15:         }
16:         else{
17:            printf("すべて異なっています\n");
18:         }
19:      }
20:

対象としている三つの整数の関係は次の 3 パターンに分類されます.
  x, y, z の関係  
(1) 三つとも同じ
(2) 二つが同じ
(3) 三つとも異なる

まずは (1) 三つとも同じという場合を考えます.
9 行目で x == y && y == z かどうかを確認しています.
これが(1) に該当するかどうかの確認です.

よくあるミスなのですが
 if ( x == y == z ){ 
と書くのは間違いです.

コンパイルエラーにはならないのですが,うまく動きません

なぜなのでしょう?
この場合,まずは x == y が評価され,
  • x と y が等しければ 1
  • x と y が等しくなければ 0
と解釈されます. その後,== z が続きますので,結局のところ x == y == z というのは
  • x と y が等しければ 1 == z
  • x と y が等しくなければ 0 == z
という意味になります.
つまり,z が 1 (または 0)に等しいかどうかの判定に置き換わってしまうんです. それゆえ,コンパイルでエラーにはならないのですが,うまく動かないという厄介なプログラムになってしまいます.

面倒でも必ず,二つずつを比較して,それらを合成しましょう.
 if ( x == y && y == z ){ 
(これが正解)

なお,複数の条件を合成する場合は次のようにつなぎます.
  目的     条件式  
条件1 と条件 2 の両方とも成立   条件1 && 条件2  
条件1 と条件 2 の少なくとも一方(両方でもOK)が成立 条件1 || 条件2

13-18 行目:内側の if ... else 文

 8:
 9:      if ( x == y && y == z ){
10:         printf("三つは等しいです\n");
11:      }
12:      else{
13:         if ( x == y || y == z || z == x ){
14:            printf("二つは等しいです\n");
15:         }
16:         else{
17:            printf("すべて異なっています\n");
18:         }
19:      }
20:

9 行目の if 文で条件(x == y && y == z)が成立しない場合,この else 部分が実行されることになります.
  x, y, z の関係  
(1) 三つとも同じ
(2) 二つが同じ
(3) 三つとも異なる

サンプルプログラム 3 の場合と同様に, この時点で,(1) ではないことが確定しましたので,後は (2) なのか,それとも (3) なのかを判定すれば良いわけです.

ここで再度,if 文を使って (2) かどうかを確認します.

既に,三つとも同じということは有り得ないと分かっていますので,x, y, z の三つのうちのどれか一組で同じものがあるかどうかが (2) かどうかの決め手になります.
つまり,
  • x == y
  • y == z
  • z == x
いずれかであればよいのです. よって,これらを || でつないだものが if 文の条件式になります(13 行目).

最後に残った (3) の場合ですが,(1) でもなく (2) でもない場合に相当しますので,サンプルプログラム 3 の場合と同様に,最後の else { ... } が対応しています.
よって,わざわざ if ( x != y && y != z && z != x ){ ... } という三つ目の if 文を書く必要はないのです.