三項演算子
処理ではなく値を切り替えたい
ここまでの if 文は「どの処理を実行するか」を分けるものでした。しかし実際に書きたいことの中には、処理はひとつで、入れる値だけが条件で変わる場面がよくあります。
int high;
if (a > b) {
high = a;
} else {
high = b;
}やっていることは「high に入れる値を選ぶ」だけなのに5行かかっています。しかも high を宣言と別の行で初期化することになり、代入し忘れの隙も生まれます。こういうときに使うのが三項演算子です。
int high = (a > b) ? a : b;読み方は「a > b が真なら a、偽なら b」です。C で唯一、値を3つ取る演算子なので三項演算子と呼ばれます。条件演算子と呼ぶこともあります。
if 文との決定的な違い
三項演算子は文ではなく式です。つまり全体がひとつの値になります。だから代入の右辺にも書けますし、printf の引数にもそのまま書けます。
printf("高いほうは%d点です\n", (a > b) ? a : b);逆に、値にならないものは書けません。? : の左右に printf(...) を並べるようなことは、できてもコードが読みにくくなるだけです。三項演算子は「値を選ぶ」ときだけに使い、「処理を選ぶ」ときは if 文を使う、と役割を分けてください。
左右の型はそろえる
? : の左右は、最終的にひとつの値になるので同じ型にそろえます。片方が int でもう片方が double だと、結果は double に引き上げられます。書式指定子とずれると表示が壊れるので、迷ったら同じ型を書きます。
合否の表示にも使えます。文字列はまだ扱っていないので、ここでは合格を意味する 'P'、不合格を意味する 'F' という1文字で切り替えてみます。
char mark = (score >= 60) ? 'P' : 'F';
printf("判定は%cです\n", mark);char 同士なので型はそろっており、%c でそのまま表示できます。
入れ子にしすぎない
三項演算子は中にもう一段書けますが、(a > b) ? ((a > c) ? a : c) : ((b > c) ? b : c) のようになると、もう誰も読めません。2段以上になったら素直に else if に戻してください。短く書くことが目的ではなく、読み手が1行で意図をつかめることが目的です。
かっこを付けておく
条件の部分をかっこで囲むかどうかは自由です。a > b ? a : b でも動きます。三項演算子は代入や比較よりも優先順位が低いので、たいていは意図どおりに解釈されます。それでも条件をかっこで囲んでおくと、どこまでが条件でどこからが選ばれる値なのかが目で追えます。優先順位を暗記して短く書くより、かっこで意図を示すほうが事故が減ります。
printf の引数に直接書くときは1つに絞る
次のように書くと、条件を2回評価することになります。
printf("%d点で%cです\n", (a > b) ? a : b, ((a > b) ? a : b) >= 60 ? 'P' : 'F');動きはしますが、同じ条件を2回書いているので片方だけ直す事故が起きます。いったん変数に受けてから printf に渡すほうが、行数は増えても安全です。
要件
- scanf で整数を2つ読む
- 高いほうの点数を「高いほうは80点です」の形で表示する
- 高いほうが60以上なら 'P'、そうでなければ 'F' を選び、「判定はPです」の形で表示する
- 値の選択は if 文ではなく三項演算子で書く
入出力例
main("80 65") → "高いほうは80点です
判定はPです"
main("40 55") → "高いほうは55点です
判定はFです"
main("60 60") → "高いほうは60点です
判定はPです"
main(12, 100) → "高いほうは100点です
判定はPです"