前に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になります。それ以外の値を入れられることは保証されていません。