前にbit演算のところでAND演算とかOR演算とかやったと思いますが、それをbit単位でなく、変数単位でやるのが条件文です。
条件文の演算結果は真ならば1、偽であれば0となります。例を見てみましょう。
int a = 10; int tmp = (5 == a);//0になる
条件文は多くの場合大小比較や同値比較と同時に用いられるので、その演算子をまとめておきましょう。
| 演算子 | 意味 |
|---|---|
| == | 等しい |
| != | 等しくない |
| <= | (左は)(右)以下である |
| >= | (右は)(左)以下である |
| < | (左は)(右)より小さい |
| > | (左は)(右)より大きい |
これに加えてAND,OR,NOT演算子があります
| 演算子 | 意味 |
|---|---|
| && | かつ(AND) |
| || | または(OR) |
| ! | 否定(NOT) |
条件式をそれ単体で使うことは、そこまで多くなく、if文やこの後紹介するwhile,for,do-while文と共に用いられます。
if文はプログラムを組む上で無くてはならないものです。例を見てみましょう。
if (条件式) /* 条件式が真の時 */; else /* 条件式が偽の時 */;
この書き方だと処理が一行しか書けません。複数行書くときは{}を使います。
気をつけて欲しいのですが、{}がなくともブロックがあります。その場合は次の;までがブロックとなります。
ところで言うまでもないですが、else節はなくても構いません。
int first_number, second_number, third_number;
int max_number, center_number, min_number;
if (first_number > second_number) { // 1番目の数と2番めの数を比較
max_number = first_number;
center_number = second_number;
} else {
max_number = second_number;
center_number = first_number;
} if (third_number > max_number) { // 3番めの数と上で出した「1番目の数と2番めの数」の大きい方と比較
min_number = center_number;
center_number = max_number;
max_number = third_number;
} else if (third_number > center_number) { // 3番めの数と上で出した「1番目の数と2番めの数」の小さい方と比較
min_number = center_number;
center_number = third_number;
} else { // 3番目の数が最小の時
min_number = third_number;
}
このようにif文 else if のように連ねて書くことも可能です。
if (a == 5) int x = 7; else x = 6; // これはだめ
そもそもif文の中で変数を宣言しないようにしましょう。変数を宣言したい、そう思ったら、直ちにその部分を関数化しましょう。
if文では、else節に正常な動作を書くと、多くの場合ですっきり書けます。
if (条件文) {
// エラー処理
} else {
// 正常動作
}
大切なのが、正常な動作の時の流れがもっとも簡潔であるように書くことです。
また、条件式を書く上での注意ですが、同値比較(==)は「=」が2つですが、ついうっかり1つにしてしまいがちです。そこで、このように書くようにしましょう
if (5 == a)//正しい書き方 if (a == 5)//これも正しい書き方 if (5 = a)//これはコンパイルエラー if (a = 5)//これはコンパイルエラーにならない、aに代入した後のaが0か否かが判別される
constがついた変数や、数値、マクロで定義された値を左側、変数を右側に持っていくようにすることがあります。
こうすることで、書き間違えた時にコンパイルエラーになります。(変更不可能なものに代入しようとしています、など)
エラー処理等、明確に実行文が1行しかない、と言える時を除き、原則{}はつけましょう。あとで文が増えた時に付け忘れるのを防ぐことができます。
if文とは一味ちがう書き方です。見てみましょう。
const int hoge = 17; const int isEven = (hoge % 2) ? 1324 : 2432;
const int hoge = 17; int isEven; if (hoge % 2) isEven = 1324; else isEven = 2432;
if文を使って書くより簡単ですし(スコープの問題がない)、代入する変数にconstが付けられます(ワタシ的にはここが美味しい)
この書きかたですが、「一行で」かけるので、後に説明するプリプロセッサマクロでしばしば用いられます。
・・・って私は教わったんだけど、マクロにして使ったことってないなぁ。それくらいならinline関数にしちゃうし。
if文が高級な条件分岐文とするならば、switch文は低級な条件分岐文といえますが、最大のメリットは、一度の条件式で複数の分岐が作れることです。
char time_when;
switch (time_when) {
case 'a':
puts("朝");
break;
case 'b':
puts("昼");
break;
case 'c':
puts("夜");
break;
default:
break;
}
switch文には必ず「default:」を書きましょう。
「case 'c':」とかは「ラベル」といいます。後述するgoto文にも登場するので頭の片隅においておいてください。
「break;」はswitch文を抜け出すために用います。もし、6行目の「break;」がなかった場合、5行目を実行した後8行目を実行します。つまり必ずしもbreakは必須ではありません。
switch文を「低級な条件分岐文」と表現したのは、コンパイラの最適化段階の表現に近いからです。
このswitch文、あとで出てくる列挙型(enum)とものすごく相性がいいです。#defineをわんさか書こうとしているそこのアナタ、enumを使いましょう。
enum型とは列挙型と呼ばれており、switch文と相性がいいんです。
enum status {
STATE_TITLE,
STATE_MAIN,
STATE_END,
};
ここでstatusはタグ名と言います。タグ名を除いた";"の前まで全体が型となります。enumはtypedefして初めて真価を発揮します。
typedef enum {
STATE_TITLE,
STATE_MAIN,
STATE_END,
} status_t;
typedefするときはタグ名は省略してもいいです。なお、「STATE_ENDのあとになんで","が置けるんだ?」と思ったあなた、よく勉強しています。enumに関しては書けるんです(C89からだっけ・・・?)
実際に例を見ていきましょう
#include "DxLib.h"
#include <stdio.h>
typedef enum {
STATE_TITLE,
STATE_MAIN,
STATE_END,
} status_t;
status_t title()
{
//タイトルを描画
//クリック押されたら
return STATE_END;
}
status_t gameMain()
{
//ゲーム処理
//ゲーム終了したら
return STATE_END;
}
status_t ending(){
//リザルト画面描画
//クリック押されたら
return STATE_MAIN;
}
int main()
{
if(DxLib_Init() == -1)
return -1;
status_t function_status = STATE_TITLE;
//function 'CheckHitKey' is DxLibrary's function.
while (CheckHitKey(KEY_INPUT_ESCAPE)) {
switch (function_status) {
case STATE_TITLE:
function_status = title();
break;
case STATE_MAIN:
function_status = gameMain();
break;
case STATE_END:
function_status = ending();
break;
default:
return -1; // エラー
}
}
DxLib_End();
return 0;
}
このようにゲームなど状態を管理するときに非常に便利です。
まあ、戻り値にするよりポインターか参照(いずれも後述)を使って引数経由でやったほうがいい気もするけど、ケース・バイ・ケースなので。
ていうか教えてないし。
真偽値はブール、ブーリアンなどと呼ばれ、C言語にはC99で専用の型が導入されました。
stdbool.hをincldueすることによりその型をbool型として使えます。
/* * ISO C Standard: 7.16 Boolean type and values <stdbool.h> */ #ifndef _STDBOOL_H #define _STDBOOL_H #ifndef __cplusplus #define bool _Bool #define true 1 #define false 0 #else /* __cplusplus */ /* Supporting <stdbool.h> in C++ is a GCC extension. */ #define _Bool bool #define bool bool #define false false #define true true #endif /* __cplusplus */ /* Signal that all the definitions are present. */ #define __bool_true_false_are_defined 1 #endif /* stdbool.h */
C99のbool型は_Bool型をマクロを使って実装しています(マクロが何かは後ほど)。
実際に使い方を見ましょう。
#include <stdbool.h>
int main()
{
//前略
bool no_first_skip = true;
bool no_dct_decimate = false;
//後略
return 0;
}
C99のbool型は、真と偽はtrueとfalseに対応し、int型に変換すると1と0になります。それ以外の値を入れられることは保証されていません。