コンテンツにスキップ

英文维基 | 中文维基 | 日文维基 | 草榴社区

「Do-while文」の版間の差分

出典: フリー百科事典『ウィキペディア(Wikipedia)』
削除された内容 追加された内容
編集の要約なし
Cewbot (会話 | 投稿記録)
m Bot作業依頼: sourceタグをsyntaxhighlightタグに置換 (Category:非推奨のsourceタグを使用しているページ) - log
7行目: 7行目:
== 構文 ==
== 構文 ==
[[C言語]]および類似の言語では以下のような構文である。
[[C言語]]および類似の言語では以下のような構文である。
<source lang="c">
<syntaxhighlight lang="c">
do
do
文 /* ここの部分を「ループ本体」と呼ぶ */
文 /* ここの部分を「ループ本体」と呼ぶ */
while (条件);
while (条件);
</syntaxhighlight>
</source>
このループの実行は、次のような手順となる。
このループの実行は、次のような手順となる。
# 「文」を実行する。
# 「文」を実行する。
19行目: 19行目:


ループ本体が複数の文からなる場合、[[ブロック (プログラミング)|ブロック]](複文)を使う。
ループ本体が複数の文からなる場合、[[ブロック (プログラミング)|ブロック]](複文)を使う。
<source lang="c">
<syntaxhighlight lang="c">
do {
do {
...
...
} while (条件);
} while (条件);
</syntaxhighlight>
</source>


C言語のプログラム例:
C言語のプログラム例:
<source lang="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文]]と同等であり、制御式を前置する。以下の例では、ループ本体は一度も実行されない。
<source lang="fortran">
<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]] ===
<source lang="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]] ===
<source lang="vbnet">
<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++]] ===
<source lang="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#]] ===
<source lang="csharp">
<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言語]] ===
<source lang="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]] ===
<source lang="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]] ===
<source lang="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文の特殊な用法に、最後にセミコロンが付く構文であることを利用し、展開結果にブロックを含むマクロの呼出しを関数のように見えるものにする、というイディオムがある。
<source lang="c">
<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 (条件);

このループの実行は、次のような手順となる。

  1. 「文」を実行する。
  2. 「条件」を評価する。
  3. 「条件」がならば、手順の最初に戻る。「条件」がならば、ループを終了する。

「条件」がはじめから偽の場合も、「文」は一度実行される。

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

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]

注釈

  1. ^ C言語では論理演算の結果の型はintである。C99規格よりも前のC言語にはブーリアン型は無かったからである。一方、C++では論理演算の結果の型はboolである。しかしC言語との互換性維持のため、制御式にはbool以外の型の式も使えるようになっている。

脚注

  1. ^ JIS X 3010:2003「プログラム言語C」§6.8.5.2「do文」
  2. ^ JIS X 3010:2003「プログラム言語C」§6.8.5「繰返し文」
  3. ^ JIS X 3010:2003「プログラム言語C」§6.8.6.2「continue文」
  4. ^ PRE10-C. 複数の文からなるマクロは do-while ループで包む

関連項目