TOP >> マニアックなプログラミング
トリッキーコードネット トリッキーなコード

【トリッキーなコード】ifステートメントのスマートな手法

条件分岐の if (hogehoge)や、if (! hogehoge) (← Perlならば unless (hogehoge)) の代わりに、
&&演算子や ||演算子を使って、コードをスマートにまとめてしまおう! という技をご紹介します^^;)
↓ ↓ それがコチラ ↓ ↓
if (A) { B } ⇒ A && B if (!A) { B } ⇒ A || B

Cコード例1)

#include <stdio.h> #include <stdlib.h> int errExit(void) { puts("0での除算はできません。"); exit(-1); return 0; } int main(void) { int a, b; puts("a ÷ b の計算を行います。"); puts("aに該当する数値を入力して下さい。"); scanf("%d", &a); puts("bに該当する数値を入力して下さい。"); scanf("%d", &b); (b == 0) && errExit(); printf("%d ÷ %d = %lf\n", a, b, a/(double)b); return 0; }
「標準入力から2つの数値(便宜上a, bとする)を受け取り、a ÷ b の結果を表示する」 という、しごく単純なプログラムです^^;) さて、数学上のお約束として、0での除算は禁止されています。 その為、bに0が入力された場合は、エラーメッセージを表示して終了させているのですが、 その判定部分に冒頭の技を使用しています。 (b == 0) && errExit(); の部分は、 if (b == 0) { errExit(); } と置き換える事ができます また、errExit()の戻り値がvoid型だと、コンパイル時に 「 '&&' : 無効です。右オペランドには型 'void' が指定されています。」 とVC++に怒られてしまう為、戻り値をint型にしています。 プログラムの実行結果は以下の通り。 トリッキーなコード:ifステートメント トリッキーなコード:ifステートメント 続いてコード例その2

Cコード例2)

#include <stdio.h> #include <stdlib.h> #include <time.h> int processA() { return rand() % 2; } int processB() { return rand() % 2; } int processC() { return rand() % 2; } int main(void) { srand ((unsigned int)time(NULL)); if (processA() && processB() && processC()) { puts("3工程全て正常終了"); } return 0; }
processA(), processB(), processC()は、ランダムで 1 or 0 を返します。 processA(), processB(), processC()は順に実行され、 全ての関数が1を返した場合のみ、「3工程全て正常終了」という文字列が出力されます。 また、順に関数が実行される最中、どこかの関数が0を返した時点で、それ以降の処理は実行されません。 ・・・この例コードは少々意味不明ですが、例えばこれを以下の様に応用することができます。
processA() { /* DataBaseへ INSERT, UPDATE, DELETE SQLが正常に実行されたか否かを 1/0 または true/falseで返す */ } processB() { /* DataBaseへ INSERT, UPDATE, DELETE SQLが正常に実行されたか否かを 1/0 または true/falseで返す */ } processC() { /* DataBaseへ INSERT, UPDATE, DELETE SQLが正常に実行されたか否かを 1/0 または true/falseで返す */ } databaseUpdate() { /* トランザクション開始 */ if (processA() && processB() && processC()) { /* コミット */ } else { /* ロールバック */ } }
↑データベースへのアクセスを例に挙げました^^;) (SQLを順に実行させていきますが、 どこかのタイミングで問題が発生したら、それ以降のSQL実行を停止、即ロールバック。 逆に、全てのSQL実行に成功したら、コミット。)        |    \  __  /    _ (m) _ピコーン       |ミ|    /  .`´  \      ∧_∧  / ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄     (・∀・∩< 閃いたモナー!!     (つ  丿 \_________     ⊂_ ノ       (_) IF-ELSEでダラダラ書くよりも、スッキリしたコードが書けそうな気がします ( ̄0 ̄)オ-ッ! ところで、if (...) の後の {} って、皆さんつけていますか?? if (...) の後に {} をつける↓のコード
if (i == 2) { puts("iは2だよ"); }
と、if (...) の後に {} をつけない↓のコード
if (i == 2) puts("iは2だよ");
は、同じ動作をします。 「じゃあ {} をつけない方が、スッキリしたコードになるから良いんじゃない?」 と思いがちですが、これは必ず {} をつけておいた方が良いです(← もう、習慣にしておきましょう^^;)。 何故なら、コードを修正する際のうっかりミスが、かなり減ります。 私も初心者の頃、独りでコードを書いていた時は、
for (...) for (...) if (...) xxx else xxx
の様な、{} をつけないスタイルがカッコいいと思い込んでいましたが(←中2病w)、多人数での開発を行ってみて、 {} をつけない事がバグの温床になるなぁと、つくづく思い知らされました・・・ orz さて、それでは最後に、Javascriptでのコード例を載せておきます。

Javascriptコード例)

var ans = prompt('2 x 2 = ?', '計算問題'); ans == 4 && alert('正解'); ans == 4 || alert('はずれ');
時と場合によっては、多少便利かな?? といった感じですかね(*´- ω・)?? (ちなみにこの例では、三項演算子を使った方が良いと思いますw)

トリッキーな条件分岐を使う場合の注意

言語によっては、AND,OR演算子がショートカット演算子ではないものもあるので、注意が必要です。 (例えば、Javaでは &&, || 演算子はショートカット演算子ですが、&, | 演算子はショートカット演算子ではありません。 (bit演算子ってわけでもないですよ~)) それと、コンパイラやインタープリタの種類によっては、構文解析を左からではなく右から行うものもあった(ハズ)・・・。
トリッキーコードネット の TOPへ HOTNEWS の 総合TOPへ