if文

条件分岐を書くときに使う最も基本的な構文

if文(イフぶん、: if statement)は、プログラミング言語において、真理値に従って「もし条件Cが満たされるならば、Xを実行せよ」というような条件付き実行の「」で、制御構造のひとつである。一般的にif文は「もし条件Cが満たされるならば、Xを実行せよ、さもなくばYを実行せよ」というように条件が満たされなかった場合の分岐もオプション(省略可能)として同時にサポートすることが多く、if-else文と呼ばれることもある。

具体的な構文はプログラミング言語によって異なるが一般的に、条件式と、条件式の評価結果の値が「真として扱うべき値」の場合に実行される「then節」と呼ばれる部分があり、「偽として扱うべき値」の場合に実行されるelse節と呼ばれる部分が付く場合もある。「もしAならばX、BならばY、それ以外はZ」というように複数の条件で分岐する場合、C言語のようにif-else文を入れ子にすることで疑似的にelse-if節をサポートする言語もあれば、真のelse-if節をサポートする言語もある。

then節とelse節がになる「条件演算子」がある言語も多い。言語によってはifが文ではなく、条件演算子と同様の「if式」である言語もある。

真偽値

編集

「真として(あるいは、偽として)扱うべき値」について詳説する。条件式の値が真理値をとるブーリアン型でなければならない言語もあるが、そのように限定していない言語もある。C言語にはそもそもブーリアン型が無くintで代用しているが、条件式としては汎整数型のゼロ(0)の他、ヌルポインタ浮動小数点数型の 0.0 なども偽として扱われる。Rubyではnilとfalse以外は真として扱われる。JavaScriptにはtruthyとfalsyという用語があり、falseの他いくつかの値がfalsyで、その他の多くの値はtruthyである。比較的少数の偽になる値の他は、真、という言語が多いが、それと逆に、Dart言語(のproduction mode)のようにtrue以外は偽という言語もある(checked modeではbool以外の型だとエラー)。

構文など

編集

以下ではいくつかの言語やソフトウェアにおける、if文またはそれに類似したものの構文(syntax)などについて述べる。

if文の条件式はスカラー型の式である(構造体共用体のような複合型の式は使えない)[1]C99よりも前の規格では真理値のみを扱うための型は無かったため、従来からint型で代用されてきた。整数値0に等しい値(あるいは暗黙変換によって0に等しくなる値)は偽、他の値は真として扱われる。真を代表して表すための値は整数値1である(比較式の結果はint型であり、0または1となることが保証されている[2])。then節とelse節には、1個の文か、{ }で囲まれる複文(ブロック)を書く。

真の時だけ実行するとき

if (条件式)
 then節

真と偽の両方に振り分けるとき

if (条件式)
 then節
else
 else節

複数の条件で分岐するときは以下のように書くことができる。

int x = f();
if (x == 1) {
    /* x の値が 1 のとき */
}
else if (x == 2) {
    /* x の値が 2 のとき */
}
else {
    /* x の値が 1 でもなく 2 でもないとき */
}

実際には以下のようにif-elseの入れ子となっているだけである。

int x = f();
if (x == 1) {
    /* x の値が 1 のとき */
}
else
    if (x == 2) {
        /* x の値が 2 のとき */
    }
    else {
        /* x の値が 1 でもなく 2 でもないとき */
    }

上記のコードはswitch文で書くこともできるが、比較対象が整数定数でない場合や、1つの条件式にAND条件やOR条件を組み合わせる場合はif文を使う必要がある。ただしあまりに多数の条件分岐をif-elseで記述すると、入れ子階層の上限に達してしまい、コンパイル不能となることもある[3]。C99の規格で保証されている入れ子階層の数は127までである[4]。多数のcaseラベルを含むswitch文はコンパイラによってテーブルジャンプに置き換えられることもあり、その最適化が施された場合は最初のラベルに該当するケースと最後のラベルに該当するケースでパフォーマンスに差はない。一方、if文における最後の分岐に該当する場合、それ以前の分岐における条件式をすべて実行することになり、分岐の数に応じてパフォーマンスが悪化する。

Cでは代入は文ではなく式であり値を返すため、以下のように条件式として代入式を使うこともできる。

int x;
if (x = f()) {
    /* x の値が 0 でないとき */
}
else {
    /* x の値が 0 のとき */
}

しかし不注意なプログラマは比較演算子の==と間違えて=と記述してしまうこともあるため、このような書き方をすると警告を出す仕様になっているコンパイラも多い[5][6]

C++はCから発展した言語であり、構文なども概ね上位互換だが、細かな仕様において互換性のない部分も多い。

値としてfalse (0) またはtrue (1) のみを取りうるbool型を持っており、組み込みの型に対する比較式の結果はbool型となる[7]。if文の条件式はこのbool型に暗黙的に変換可能な式を受け付ける。Cとの互換性のため、bool型は整数型の一種であり、その他の整数型や浮動小数点数型、ポインタ型などの値は、条件式の文脈においてbool型に暗黙変換可能となっている。そのため、このような型Tへの暗黙変換演算子オーバーロードoperator T()を持つユーザー定義型のインスタンスであれば、if文の条件式として直接使うことも可能である。

struct MyStruct {
    std::string name;
    operator size_t() const { return name.size(); }
};

MyStruct obj = {"abc"};
if (obj) {
    // obj.name が空文字列でないとき。
}
size_t size = obj; // 暗黙の型変換があらゆる場面で発動する。

ただしこのような暗黙変換は思わぬ場面で発動することもあり、問題を引き起こすことが多い。安全のため、C++11では、明示的な型変換演算子オーバーロードを定義できるexplicit operator T()の構文がサポートされた[8]Tboolの場合、条件式の文脈においては暗黙変換可能となる。

struct MyStruct {
    std::string name;
    explicit operator bool() const { return !name.empty(); }
};

MyStruct obj = {"abc"};
if (obj) {
    // obj.name が空文字列でないとき。
}
bool b = static_cast<bool>(obj); // 条件式の文脈でない場合、型変換には明示的なキャストが必要。

C++ではif文の条件式で変数を宣言することも可能である。変数の生存期間はそのif-else文を抜けるまでとなる。

if (int x = f()) {
    // x の値が 0 でないとき。
}
else {
    // x の値が 0 のとき。
}

C++17では、if文における初期化と条件式を分離した構文が使えるようになった[9]

if (int x = f(); x == 123) {
    // x の値が 123 のとき。
}
else {
    // x の値が 123 でないとき。
}

Javaのif文は条件式としてboolean型のみを許可する。boolean型の変数への代入またはプリミティブラッパークラスjava.lang.Boolean型の変数への代入を除き、代入式を記述することはできない。

C++のようにif文の条件式の中で変数を宣言することはできないが、Java 16では、instanceof演算子を使ったパターンマッチングの構文をサポートするようになった[10]

Object obj = getSomeObject();
if (obj instanceof String str) {
    // obj の型が String のとき。
    System.out.println("String length = " + str.length());
}
else {
    // obj の型が String でないとき。
}

上記は下記と等価である。

Object obj = getSomeObject();
if (obj instanceof String) {
    // obj の型が String のとき。
    String str = (String) obj;
    System.out.println("String length = " + str.length());
}
else {
    // obj の型が String でないとき。
}

C#はJavaとよく似ており、if文は条件式としてbool型のみを許可する。bool型の変数への代入またはboolへの暗黙変換演算子static implicit operator bool()などをユーザー定義した型の変数への代入を除き、代入式を記述することはできない。

C# 7ではis演算子が拡張され、型パターンなどの構文が使えるようになった[11][12]

object obj = GetSomeObject();
if (obj is string str) {
    // obj の型が string のとき。
    System.Console.WriteLine("String length = " + str.Length);
}
else {
    // obj の型が string でないとき。
}
// 変数 str は if-else 文を抜けた後も使用できるが、未割り当て(未初期化)となる。

Lispでは、ifは関数のような見掛けだが実引数が評価されない特殊形式(マクロ)である。真偽値は、nil という名前や中身の無いカッコ () で表現される空リストが偽として扱われ、他の値は真として扱われる。then節とelse節のどちらも式である。

真の時だけ実行するとき

(if 条件式 then節)

真と偽の両方に振り分けるとき

(if 条件式 then節 else節)

Lispにはcondという、同等の機能を実現できる特殊形式もある。仕様や実装によっては、ifがcondに展開されるマクロのこともあるし、condがifに展開されるマクロのこともある。

Pascal

編集

then節とelse節には、1個の文か、begin - end で囲まれる複文を書く。

真の時だけ実行するとき

if 条件式 then
 then

真と偽の両方に振り分けるとき

if 条件式 then
 then
else
 else

Adaでは条件式の型はBoolean(もしくはBooleanの派生型)でなければならない。これはJava等も同様である。

真の時だけ実行するとき

if 条件式 then
 then節
end if;

真と偽で実行文を変えるとき

if 条件式 then
 then節
else
 else節
end if;

Perlの場合

編集

真の時だけ実行するとき

真文 if 条件文

偽の時だけ実行するとき

偽文 unless 条件文

また、C言語風の記述法も可能である。

真の時だけ実行するとき

if(条件文) {
 真文
}

真と偽で実行文を変えるとき

if(条件文) {
 真文
} else {
 偽文
}

Rubyの場合

編集

Rubyのifは厳密に言えばif式であり、条件が成立した方の節で最後に評価された式の値を返す。

真の時だけ実行するとき

if 条件式 (then)
 真文
end

真と偽で実行文を変えるとき

if 条件文 (then)
 真文
else
 偽文
end

BASICの場合

編集

真の時だけ実行するとき

IF 条件式 THEN 真文

真と偽で実行文を変えるとき

IF 条件式 THEN 真文 ELSE 偽文

真文・偽文が1行で書ききれない場合はgoto文が併用される。

Visual Basicの場合

編集

Visual Basic (VB)、Visual Basic for Applications (VBA)、Visual Basic .NET (VB.NET) は複文にも対応している。

真の時だけ実行するとき

If 条件式 Then
 真文
End If

真と偽で実行文を変えるとき

If 条件式 Then
 真文
Else
 偽文
End If

真文・偽文が1行だけの場合にはBASICと同様の書き方(単一行構文)も可能である[13][14]

表計算ソフトウェア

編集

表計算ソフトウェアMicrosoft ExcelOpenOffice.org Calc、LibreOffice CalcGoogle スプレッドシートなどでは、ワークシート関数のひとつとしてIF関数をサポートしている。

Excelの場合は以下の構文である[15]

IF(テストする条件, 真の場合の値, 偽の場合の値)

関数という性質上、「偽の場合は何も返さない(何も実行しない)」というようなことはできないが、偽の場合は0や空文字列""を返すといった形で記述できる。

LibreOffice Calcの場合は以下の構文である[16]

IF(テストする条件; 真の場合の値; 偽の場合の値)

真の場合の値や偽の場合の値を空にした場合、0とみなされる。

Googleスプレッドシートの場合は以下の構文である[17]

IF(テストする条件, 真の場合の値, 偽の場合の値)

偽の場合の値(FALSE値)を省略することができ、デフォルトは空欄(ブランク)となる。

IFS関数

編集

LibreOffice Calc 5.2以降[18]およびExcel 2019以降(Office 365含む)[19]ではIFS関数をサポートする。

IFS(条件式1, 真の場合1, 条件式2, 真の場合2, ..., 条件式127, 真の場合127)

条件式は先に評価されるべきものから並べる必要がある。IF関数の入れ子構造と処理は同一であるが、簡潔に記述できる。

LibreOffice CalcとExcelのIFS関数では、最大127個の条件をテストすることができる。ただし、IFまたはIFSであまりにも多くの条件をネストすることは推奨されていない。複数の条件は正確な順序で入力する必要があり、かつ、構築、テスト、更新を行うのが大変難しくなる場合があるからである[19]

IFS関数はGoogleスプレッドシートでもサポートされている[20]

FORTRAN

編集

以下は、Fortran77以降の、論理IF文の場合である。1行のみの場合

if(条件式) 真文

複数行にまたがる場合

if(条件式1) then
  条件式1が真の場合ここから
  ここまでのプログラムが実行される(複数行)                                              
else if(条件式2) then                                               
  条件式2が真の場合ただしすでに条件式1が成り立っている場合は除くここから
  ここまでのプログラムが実行される(複数行)
else
  すべてのなかのいずれの条件にも当てはまらない場合ここから  
  ここまでのプログラムが実行される(複数行)
end if

Forthの場合

編集

真の時だけ実行するとき

条件式 IF 真文 THEN

偽の時だけ実行するとき

条件式 NIF 偽文 THEN

真と偽で実行文を変えるとき

条件式 IF 真文 ELSE 偽文 THEN

または

条件式 NIF 偽文 ELSE 真文 THEN

ひまわりの場合

編集

真の時だけ実行するとき

もし、{条件式}ならば、(
{処理}
)

真と偽で実行文を変えるとき

もし、{条件式}ならば、(
{処理}
)
違ったら、(
{処理}
)

HSPの場合

編集

真の時だけ実行するとき

if 条件式 : 真文

真と偽で実行文を変えるとき

if 条件式 : 真文 : else : 偽文

また、Cのようにブレイスを用いることもできる。

if 条件式 {
  真文
} else {
  偽文
}

プログラム例

編集

特に断りがない場合nanbの大きい方をncに代入という意味である。

Cでの例

編集
if (na > nb) {
  nc = na;
} else {
  nc = nb;
}
  • nc = (na > nb) ? na : nb としても同じ事ができる。

Common Lisp での例

編集
(if (> na nb)
    (setq nc na)
    (setq nc nb))

これはcondを使った

(cond ((> na nb) (setq nc na))
      (t (setq nc nb)))

と同様であるが、Common Lispでは文ではなく式であるため返却値を利用し、

(setq nc (if (> na nb) na nb))

と書くこともできる。

Pascalでの例

編集
if na > nb then nc := na else nc := nb

R言語での例

編集
nc <- ifelse(na > nb, na, nb)

FORTRANの例

編集
if(a.eq.b) c=5

上記の記述ではa=bの場合c=5になる簡単なプログラム例である。

if(a.eq.100) then
b=30
else if(a.eq.80) then
b=25
else
b=20
end if

上記の記述ではa=100の場合はb=30となり,a=80の場合はb=25,その他の場合はb=20となるプログラム例である。

論理積・論理和による擬似的なIf文

編集

仮に && を論理積を表す演算子として、

左辺 && 右辺

という論理式で、左辺が真にならなければ右辺を評価しない言語(短絡評価)では、これを

If (左辺) { 右辺 }

と等価とみなすことができる。つまり左辺が条件文で、右辺が真文となるわけである。

同様に || を論理和を表す演算子だとすると、

左辺 || 右辺

If (Not 左辺) { 右辺 }

と等価となり、左辺が偽のときだけ右辺が実行される。

たとえばMS-DOSWindowsバッチファイルでは条件付き処理シンボル&&||がある[21]

CHDIR C:\HOGE || ECHO フォルダがみつかりません

(もしCHDIRコマンドが失敗したら、ECHOコマンドが実行される)

JavaScriptなど言語によっては、このように論理積演算や論理和演算を擬似的なIf文にできることがある。

脚注

編集

関連項目

編集