第 6 章 C 言語入門
6.9 いくつかのプログラム
6.10.8 条件文
条件文とは,条件によって実行を分岐させるための制御文である.
6.10.8.1 if文
最も簡単な条件文は if文である. if文は以下のような構文を持つ.
if (式) 文
ここで,式は省くことはできない. ここで,式は算術型もしくはポインタでなくてはならない.
このようなif文は,次のように制御される.
• 式が0でなければ,文が実行される.
Id: C4.tex,v 1.6 2001-03-15 20:35:03+09 naito Exp
6.10.8.2 if–else 文
if–else文は以下のような構文を持つ.
if (式) 文1 else
文2
ここで,式は省くことはできない. ここで,式は算術型もしくはポインタでなくてはならない.
このようなif–else 文は, 次のように制御される.
• 式が0でなければ,文1が実行される.
• 式が0であれば,文2が実行される.
if–elseは繰り返して使うことができ,次のような形になる.
if (式1) 文1
else if (式2) 文2
else if (式3) 文3
else 文4
この形では, 式1から順番に式が評価される. 式1が 0であれば,式2を評価するという順番で,条件式 が評価されていく.
Example 6.10.15 次の例はnが 0か正か負かを判定している.
int n;
if (n == 0)
printf("n is equal 0\n") ; else if (n < 0)
printf("n is negative\n") ; else
printf("n is positive\n") ;
Remark 6.10.5 上のExampleの最初のif (n == 0)はif (!n)と書くこともできるが,後のif--else との整合性を考えると,ここはn == 0と書いた方が良い.
C の標準関数の中で,int型の変数が 英小文字であるかどうかを判定するための関数として,islower 関数がある. cが英小文字であるときにはislower(c) は 1となり,そうでないときには0 となる. この ような関数を利用するときには,
if (islower(c))
と書けば(そのままこの文章を英語で読めば)非常にわかりやすい.
しかし, Cの標準関数の中で,2つの文字型の配列(文字列)が同一であるかどうかを判定する関数とし て,strcmpがある. char *s, *tに対して,strcmp(s,t)はその辞書式順序に従う差を与える. すなわち, s,tの指し示す文字列が同一内容であるときに0を返すため,
if (strcmp(s,t) == 0)
によって,s, tが等しいときの分岐を表すことになる.
条件式を簡潔に書くことは,プログラムを見易くするために重要なことであるが,条件式を余りに簡潔に しすぎると思わぬバグを産む可能性がある.
Id: C4.tex,v 1.6 2001-03-15 20:35:03+09 naito Exp
if–else文には曖昧な構文がある.
Example 6.10.16 次の例はelseがどちらのifに結び付いているかわかりにくくなった例である.
if (n > 0) if (a > b)
z = a ; else
z = b ;
ここで,文法的にはelse は2番めのifに結び付いている.
このような表現を避けるため,if–elseで制御される文は{}をつけて複文にすることが望ましい.
if (n > 0) {
if (a > b) z = a ; }
else z = b ;
if (n > 0) {
if (a > b) z = a ; else z = b ; }
6.10.8.3 switch文
switch文は以下のような構文を持つ.
switch (式) { case 定数式: 文 case 定数式: 文 default: 文 }
ここで, 式は省くことはできない. 式は整数型でなくてはならない. default はなくても良い. 一つ の switchに許される defaultは高々一つ. case の定数式で重複するものがあってはならない. 一つの switch文には少なくとも257個のcaseラベルを用いることが出来る. また,switchは入れ子にできる.
このようなswitch文は,次のように制御される.
• 式の結果に応じて,定数式で表されたどれかの式に制御が移る.
• もし, defalutが存在し, 式の結果が定数式のどれとも一致しない時には,default が実行されるが, defaultが存在しない時には,どれも実行されない.
ここで,式は,副作用も含めて,全て最初に評価され, 整数への格上げを受けた定数式と比較される.
switchで重要なことは,次のことである.
• マッチした定数式に対応する文が実行された後,制御は次のcaseラベルもしくはdefaultラベルを 持つ文に移され,無条件に実行される.
Example 6.10.17 この例では,nの値によって,結果を印字しようとしているが,期待通りには動かない.
int n ; switch (n) {
case 1: printf("n は 1 だよ\n") ; case 0: printf("n は 0 だよ\n") ; case -1: printf("n は -1 だよ\n") ;
default: printf("n は 1, 0, -1 のどれでもない\n") ; }
これは,n = 1の時,
Id: C4.tex,v 1.6 2001-03-15 20:35:03+09 naito Exp
n は 1 だよ n は 0 だよ n は -1 だよ
n は 1, 0, -1 のどれでもない という結果をうち出す.
このようにswitch文の中で,一つのcaseラベルを実行し,次のcaseラベルに制御が移ってしまうこと
を“Fall Throught” と呼ぶが, Fall Throughtを使う仕様はバグの原因となる.
このようなことを避けるためには,break 文を使う.
Example 6.10.18 上のExampleを改良した.
int n ; switch (n) {
default: printf("n は 1, 0, -1 のどれでもない\n") ; break ;
case 1: printf("n は 1 だよ\n") ; break ;
case 0: printf("n は 0 だよ\n") ; break ;
case -1: printf("n は -1 だよ\n") ; break ;
}
この改良により, この switch 文ではどれか一つのラベルに対する文しか実行しなくなる. 出来れば
defaultラベルを持つ文は一番最後につけよう. その方がわかりやすい.