Do-while文

**do-while文** () は、C言語および類似のプログラミング言語において繰り返し（ループ）の制御構造を記述するための文 (statement) のひとつである。C言語の規格では「do文」と呼ばれる。ループ本体 (loop body) の処理を一度実行した後、さらに継続条件として指定された式（制御式）を評価した値が真である間、ループ本体を繰り返し実行する。while文との違いは、ループに入る前の条件の評価が無く最初に必ず1回はループ本体が実行されることである。

なお、C言語およびC++ではゼロに等しい値を偽、ゼロ以外を真とみなす。したがって、整数型だけでなく、任意のポインタ型や浮動小数点数型の式も制御式として記述可能である。C/C++以外のブーリアン型をサポートするほとんどの言語では通例、制御式にはブーリアン型の式のみを記述できる。

## 構文
C言語および類似の言語では以下のような構文である。

```c
do
    文 /* ここの部分を「ループ本体」と呼ぶ */
while (条件);
```

このループの実行は、次のような手順となる。
# 「文」を実行する。
# 「条件」を評価する。
# 「条件」が真ならば、手順の最初に戻る。「条件」が偽ならば、ループを終了する。
「条件」がはじめから偽の場合も、「文」は一度実行される。

ループ本体が複数の文からなる場合、ブロック（複文）を使う。

```c
do {
    ...
} while (条件);
```


C言語のプログラム例:

```c
int x = 0;
do {
    x += 1;
} while (x < 3);
```


この例では、最初に `x += 1` を実行し `x == 1` となる。次に条件の `x < 3` をチェックする。条件は真であり、コードブロックを再度実行する。変数 `x` がループ脱出条件に合致する（`x >= 3` になる）まで、コードの実行と条件のチェックを繰り返す。

C言語に似ていない言語では、異なった構文で同様の機能を持つものもある（while文の記事も参照）。例えばPascalでは、"repeat-until" 文である。ただし、制御式として継続条件ではなく終了条件（真のときループを終了）を記述する。

なお、Fortran (Fortran 90以降) にもdo-while文はあるが、これはC言語のwhile文と同等であり、制御式を前置する。以下の例では、ループ本体は一度も実行されない。

```fortran
program TEST
    integer x
    data x /0/
    do while (x > 0)
        print *, x
        x = x - 1
    end do
    print "('Finished. x = ', i0)", x
end
```


### 分岐文
while文と同様、do-while文においてもbreak文などの分岐文を使用できる。なお、continue文はループの途中から、**ループ本体の最後**に飛び、do-while文の場合には条件の評価となる。

## 例
以下の、各言語によるdo-while文あるいは同様の制御を利用したプログラムは、与えられた数の階乗を計算する。

### Ada
Adaの例。

```ada
with Ada.Integer_Text_IO;

procedure Factorial is
   Counter   : Integer := 5;
   Factorial : Integer := 1;
begin
   loop
      Factorial := Factorial * Counter;
      Counter   := Counter - 1;
      exit when Counter = 0;
   end loop;

   Ada.Integer_Text_IO.Put(Factorial);
end Main;
```


### Visual Basic .NET
Visual Basic .NETの例。

```vbnet
Dim counter As UInteger = 5
Dim factorial as ULong = 1
Do
  factorial *= counter ' multiply
  counter -= 1 ' decrement
Loop While counter > 0
System.Console.WriteLine(factorial)
```


### C言語とC++
C言語とC++の例。

```c
unsigned int counter = 5;
unsigned long factorial = 1;
do {
  factorial *= counter--; /* Multiply, then decrement. */
} while (counter > 0);
printf("%lu\n", factorial);
```


### C#
C#の例。

```csharp
uint counter = 5;
ulong factorial = 1;
do
{
    factorial *= counter--;
}
while (counter > 0);
System.Console.WriteLine(factorial);
```


### D言語
D言語の例。

```d
uint counter = 5;
ulong factorial = 1;
do {
    factorial *= counter--;
} while (counter > 0);
writeln(factorial);
```


### Java
Javaの例。

```java
int counter = 5;
long factorial = 1;
do {
  factorial *= counter--; // Multiply, then decrement.
} while (counter > 0);
System.out.println(factorial);
```


### Pascal
Pascalの例。

```pascal
program FactorialProgram;
var
  counter, factorial: Integer;
begin
  counter := 5;
  factorial := 1;

  repeat
    factorial := factorial * counter;
    counter := counter - 1;
  until counter = 0;

  Write(factorial);
end.
```


## C/C++のマクロにおける利用
C/C++におけるdo-while文の特殊な用法に、最後にセミコロンが付く構文であることを利用し、展開結果にブロックを含むマクロの呼び出しを関数のように見えるものにする、というイディオムがある。

```c
/* 2つの値 x, y を入れ替えるマクロ。 */
#define SWAP(x, y, tmp) do { (tmp) = (x); (x) = (y); (y) = (tmp); } while (0)

/* 以下のように書いてしまうと、セミコロンを付けた場合にコンパイルが通らなくなるケースがある。 */
/*
#define SWAP(x, y, tmp) { (tmp) = (x); (x) = (y); (y) = (tmp); }
*/

void some_function()
{
    int x, y, tmp;
...
    if (x > y)
        SWAP(x, y, tmp);
    else
        puts("Not swapped.");
...
}
```


これを利用することで、「セミコロンを付けてはいけないマクロ」という、扱いが面倒なものを作らずにすむ。

## 脚注

### 注釈

### 出典

## 関連項目
* while文
* for文

## 外部リンク
*