「Do-while文」の版間の差分
編集の要約なし |
|||
7行目: | 7行目: | ||
== 構文 == |
== 構文 == |
||
[[C言語]]および類似の言語では以下のような構文である。 |
[[C言語]]および類似の言語では以下のような構文である。 |
||
< |
<syntaxhighlight lang="c"> |
||
do |
do |
||
文 /* ここの部分を「ループ本体」と呼ぶ */ |
文 /* ここの部分を「ループ本体」と呼ぶ */ |
||
while (条件); |
while (条件); |
||
</syntaxhighlight> |
|||
</source> |
|||
このループの実行は、次のような手順となる。 |
このループの実行は、次のような手順となる。 |
||
# 「文」を実行する。 |
# 「文」を実行する。 |
||
19行目: | 19行目: | ||
ループ本体が複数の文からなる場合、[[ブロック (プログラミング)|ブロック]](複文)を使う。 |
ループ本体が複数の文からなる場合、[[ブロック (プログラミング)|ブロック]](複文)を使う。 |
||
< |
<syntaxhighlight lang="c"> |
||
do { |
do { |
||
... |
... |
||
} while (条件); |
} while (条件); |
||
</syntaxhighlight> |
|||
</source> |
|||
C言語のプログラム例: |
C言語のプログラム例: |
||
< |
<syntaxhighlight lang="c"> |
||
int x = 0; |
int x = 0; |
||
do { |
do { |
||
x += 1; |
x += 1; |
||
} while (x < 3); |
} while (x < 3); |
||
</syntaxhighlight> |
|||
</source> |
|||
この例では、最初に <code>x += 1</code> を実行し <code>x == 1</code> となる。次に条件の <code>x < 3</code> をチェックする。条件は真であり、コードブロックを再度実行する。[[変数 (プログラミング)|変数]] <code>x</code> がループ脱出条件に合致する(<code>x >= 3</code> になる)まで、コードの実行と条件のチェックを繰り返す。 |
この例では、最初に <code>x += 1</code> を実行し <code>x == 1</code> となる。次に条件の <code>x < 3</code> をチェックする。条件は真であり、コードブロックを再度実行する。[[変数 (プログラミング)|変数]] <code>x</code> がループ脱出条件に合致する(<code>x >= 3</code> になる)まで、コードの実行と条件のチェックを繰り返す。 |
||
38行目: | 38行目: | ||
なお、[[Fortran]] (Fortran 90以降) にもdo-while文はあるが、これはC言語の[[while文]]と同等であり、制御式を前置する。以下の例では、ループ本体は一度も実行されない。 |
なお、[[Fortran]] (Fortran 90以降) にもdo-while文はあるが、これはC言語の[[while文]]と同等であり、制御式を前置する。以下の例では、ループ本体は一度も実行されない。 |
||
< |
<syntaxhighlight lang="fortran"> |
||
program TEST |
program TEST |
||
integer x |
integer x |
||
48行目: | 48行目: | ||
print "('Finished. x = ', i0)", x |
print "('Finished. x = ', i0)", x |
||
end |
end |
||
</syntaxhighlight> |
|||
</source> |
|||
=== 分岐文 === |
=== 分岐文 === |
||
57行目: | 57行目: | ||
=== [[Ada]] === |
=== [[Ada]] === |
||
< |
<syntaxhighlight lang="ada"> |
||
with Ada.Integer_Text_IO; |
with Ada.Integer_Text_IO; |
||
72行目: | 72行目: | ||
Ada.Integer_Text_IO.Put(Factorial); |
Ada.Integer_Text_IO.Put(Factorial); |
||
end Main; |
end Main; |
||
</syntaxhighlight> |
|||
</source> |
|||
<!-- |
<!-- |
||
87行目: | 87行目: | ||
--><!-- 特筆性に欠けるのでコメントアウト。 --> |
--><!-- 特筆性に欠けるのでコメントアウト。 --> |
||
=== [[Visual Basic .NET]] === |
=== [[Visual Basic .NET]] === |
||
< |
<syntaxhighlight lang="vbnet"> |
||
Dim counter As UInteger = 5 |
Dim counter As UInteger = 5 |
||
Dim factorial as ULong = 1 |
Dim factorial as ULong = 1 |
||
95行目: | 95行目: | ||
Loop While counter > 0 |
Loop While counter > 0 |
||
System.Console.WriteLine(factorial) |
System.Console.WriteLine(factorial) |
||
</syntaxhighlight> |
|||
</source> |
|||
=== [[C言語]]と[[C++]] === |
=== [[C言語]]と[[C++]] === |
||
< |
<syntaxhighlight lang="c"> |
||
unsigned int counter = 5; |
unsigned int counter = 5; |
||
unsigned long factorial = 1; |
unsigned long factorial = 1; |
||
105行目: | 105行目: | ||
} while (counter > 0); |
} while (counter > 0); |
||
printf("%lu\n", factorial); |
printf("%lu\n", factorial); |
||
</syntaxhighlight> |
|||
</source> |
|||
=== [[C Sharp|C#]] === |
=== [[C Sharp|C#]] === |
||
< |
<syntaxhighlight lang="csharp"> |
||
uint counter = 5; |
uint counter = 5; |
||
ulong factorial = 1; |
ulong factorial = 1; |
||
117行目: | 117行目: | ||
while (counter > 0); |
while (counter > 0); |
||
System.Console.WriteLine(factorial); |
System.Console.WriteLine(factorial); |
||
</syntaxhighlight> |
|||
</source> |
|||
=== [[D言語]] === |
=== [[D言語]] === |
||
< |
<syntaxhighlight lang="d"> |
||
uint counter = 5; |
uint counter = 5; |
||
ulong factorial = 1; |
ulong factorial = 1; |
||
127行目: | 127行目: | ||
} while (counter > 0); |
} while (counter > 0); |
||
writeln(factorial); |
writeln(factorial); |
||
</syntaxhighlight> |
|||
</source> |
|||
=== [[Java]] === |
=== [[Java]] === |
||
< |
<syntaxhighlight lang="java"> |
||
int counter = 5; |
int counter = 5; |
||
long factorial = 1; |
long factorial = 1; |
||
137行目: | 137行目: | ||
} while (counter > 0); |
} while (counter > 0); |
||
System.out.println(factorial); |
System.out.println(factorial); |
||
</syntaxhighlight> |
|||
</source> |
|||
=== [[Pascal]] === |
=== [[Pascal]] === |
||
< |
<syntaxhighlight lang="pascal"> |
||
program FactorialProgram; |
program FactorialProgram; |
||
var |
var |
||
155行目: | 155行目: | ||
Write(factorial); |
Write(factorial); |
||
end. |
end. |
||
</syntaxhighlight> |
|||
</source> |
|||
== C/C++のマクロにおける利用 == |
== C/C++のマクロにおける利用 == |
||
C/C++におけるdo-while文の特殊な用法に、最後にセミコロンが付く構文であることを利用し、展開結果にブロックを含むマクロの呼出しを関数のように見えるものにする、というイディオムがある。 |
C/C++におけるdo-while文の特殊な用法に、最後にセミコロンが付く構文であることを利用し、展開結果にブロックを含むマクロの呼出しを関数のように見えるものにする、というイディオムがある。 |
||
< |
<syntaxhighlight lang="c"> |
||
#if NDEBUG |
#if NDEBUG |
||
#define DEBUG_LOG(msg) |
#define DEBUG_LOG(msg) |
||
172行目: | 172行目: | ||
DEBUG_LOG("debug message"); |
DEBUG_LOG("debug message"); |
||
} |
} |
||
</syntaxhighlight> |
|||
</source> |
|||
<!-- printf("%s\n", msg) だと、可変個引数の脆弱性によりマクロ引数にconst char*以外を渡すこともできてしまうので、strlen()呼び出しで型チェックできるように改良。ただ、size_tからintへのキャストは好ましくない。そもそも論として、型安全な関数 void debug_print(const char* msg) { printf("%s\n", msg); } を用意して、DEBUG_LOGマクロシンボルをdebug_printへのエイリアスにするべきなので、do-whileのマクロ活用としてはあまり良い例ではない。要改良/改変。 --> |
<!-- printf("%s\n", msg) だと、可変個引数の脆弱性によりマクロ引数にconst char*以外を渡すこともできてしまうので、strlen()呼び出しで型チェックできるように改良。ただ、size_tからintへのキャストは好ましくない。そもそも論として、型安全な関数 void debug_print(const char* msg) { printf("%s\n", msg); } を用意して、DEBUG_LOGマクロシンボルをdebug_printへのエイリアスにするべきなので、do-whileのマクロ活用としてはあまり良い例ではない。要改良/改変。 --> |
||
これを利用することで、「セミコロンを付けてはいけないマクロ」という、扱いが面倒なものを作らずにすむ<ref>[https://www.jpcert.or.jp/sc-rules/c-pre10-c.html PRE10-C. 複数の文からなるマクロは do-while ループで包む]</ref>。 |
これを利用することで、「セミコロンを付けてはいけないマクロ」という、扱いが面倒なものを作らずにすむ<ref>[https://www.jpcert.or.jp/sc-rules/c-pre10-c.html PRE10-C. 複数の文からなるマクロは do-while ループで包む]</ref>。 |
2020年7月5日 (日) 22:59時点における版
do-while文 (英: do-while statement) は、C言語および類似のプログラミング言語において繰り返し(ループ)の制御構造を記述するための文 (statement) のひとつである。C言語の規格では「do文」と呼ばれる[1]。ループ本体 (loop body) [2]の処理を一度実行した後、さらに継続条件として指定された式(制御式)を評価した値が真である間、ループ本体を繰り返し実行する。while文との違いは、ループに入る前の条件の評価が無いこと、また最初に必ず1回はループ本体が実行されることである。
なお、C言語およびC++ではゼロに等しい値を偽、ゼロ以外を真とみなす。したがって、整数型だけでなく、任意のポインタ型や浮動小数点数型の式も制御式として記述可能である[注釈 1]。C/C++以外のブーリアン型をサポートするほとんどの言語では通例、制御式にはブーリアン型の式のみを記述できる。
構文
C言語および類似の言語では以下のような構文である。
do
文 /* ここの部分を「ループ本体」と呼ぶ */
while (条件);
このループの実行は、次のような手順となる。
「条件」がはじめから偽の場合も、「文」は一度実行される。
ループ本体が複数の文からなる場合、ブロック(複文)を使う。
do {
...
} while (条件);
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文と同等であり、制御式を前置する。以下の例では、ループ本体は一度も実行されない。
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文はループの途中から、ループ本体の最後に飛び[3]、do-while文の場合には条件の評価となる。
例
以下の、各言語によるdo-while文あるいは同様の制御を利用したプログラムは、与えられた数の階乗を計算する。
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;
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)
unsigned int counter = 5;
unsigned long factorial = 1;
do {
factorial *= counter--; /* Multiply, then decrement. */
} while (counter > 0);
printf("%lu\n", factorial);
uint counter = 5;
ulong factorial = 1;
do
{
factorial *= counter--;
}
while (counter > 0);
System.Console.WriteLine(factorial);
uint counter = 5;
ulong factorial = 1;
do {
factorial *= counter--;
} while (counter > 0);
writeln(factorial);
int counter = 5;
long factorial = 1;
do {
factorial *= counter--; // Multiply, then decrement.
} while (counter > 0);
System.out.println(factorial);
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文の特殊な用法に、最後にセミコロンが付く構文であることを利用し、展開結果にブロックを含むマクロの呼出しを関数のように見えるものにする、というイディオムがある。
#if NDEBUG
#define DEBUG_LOG(msg)
#else
#define DEBUG_LOG(msg) do { \
if (msg) { printf("%.*s\n", (int)strlen(msg), msg); } \
} while (0)
#endif
void some_function()
{
DEBUG_LOG("debug message");
}
これを利用することで、「セミコロンを付けてはいけないマクロ」という、扱いが面倒なものを作らずにすむ[4]。
注釈
脚注
- ^ JIS X 3010:2003「プログラム言語C」§6.8.5.2「do文」
- ^ JIS X 3010:2003「プログラム言語C」§6.8.5「繰返し文」
- ^ JIS X 3010:2003「プログラム言語C」§6.8.6.2「continue文」
- ^ PRE10-C. 複数の文からなるマクロは do-while ループで包む