「C言語/制御文」の版間の差分
削除された内容 追加された内容
M →発展的な話題: Fix タグ: 2017年版ソースエディター |
→無限ループ: scanf/scanf_sの戻り値は EOF の可能性があり、無視すると無限ループに陥る。 タグ: 2017年版ソースエディター |
||
493 行
==== 無限ループ ====
無限ループとは、文の実行が無限に繰り返されることで
{| class="wikitable"
|+ 無限ループのコード
!while文!!do文!!for文
|-
|style="vertical-align:top"|<syntaxhighlight lang="C">
while (1)
文
</syntaxhighlight>
|style="vertical-align:top"|<syntaxhighlight lang="C">
do
文
while (1);
</syntaxhighlight>
|style="vertical-align:top"|<syntaxhighlight lang="C">
for (;;)
文
</syntaxhighlight>
|}
いずれのコードも、継続条件は常に真であるので文の実行を無限に繰り返します。
無限ループを用いる場合、後述するbreak文を用いるなどして適切にループから脱出できるようにする必要があります。
;無限ループを使った例:<syntaxhighlight lang="C">
#include <stdio.h>
int main(void) {
for (;;) {
printf("ループの中。\n");
printf("End of File に達しました。\n");
return 1;
}
if (ans == 'y') {
printf("ループを脱出します。\n");
break;
}
}
printf("ループの外です。\n");
}
</syntaxhighlight>
:※註 過去の版では、scanf の戻り値をチェックしていませんでしたが EOF を返す可能性があり、これを無視すると、それこそ'''無限ループ'''になってしまうので、戻り値も必ずチェックしましょう。また、この部分は return 文による脱出の例にもなっています。
Visual C/C++ では、scanf が「非推奨とマークされている関数」にあたり、設定によってはビルドに失敗します。⇒ [https://docs.microsoft.com/ja-jp/cpp/error-messages/compiler-warnings/compiler-warning-level-3-c4996?view=msvc-160 コンパイラの警告 (レベル 3) C4996]
ソースコードに <syntaxhighlight lang="C" inline>#pragma warning(disable:4996)</syntaxhighlight> を補って迂回する方法もありますが、
ここでは scanfの境界検査インターフェース版のscanf_sを使った実装を紹介します(scanf_sの3つめの引数 1は、記憶するデータの個数で、第1引数がスカラオブジェクトを指している場合、それは1要素の配列であるとみなされます。<ref name="jtc1-sc22-wg14-n1570-k.3.5.3.2">{{cite book
| url = http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1570.pdf
| title = N1570 Committee Draft — April 12, 2011 ISO/IEC 9899:201x
| page=592, §K.3.5.3.2 ''The fscanf_s function''
| quote = If the first argument points to a scalar object, it is considered to be an array of one element
| publisher = ISO/IEC}}</ref>なので第3引数の値は 1 です。<ref>過去の版で 10 とされていましたが、正しくは 1 です。</ref>)
;境界検査インターフェース版 無限ループ:<syntaxhighlight lang="c">
#include <stdio.h>
int main(void) {
for (;;) {
printf("ループの中。\n");
char ans;
printf("ループを脱出しますか? 「はい」y /「いいえ」N\n ");
if (scanf_s("%c", &ans, 1) == EOF) {
printf("End of File に達しました。\n");
return 1;
}
if (ans == 'y') {
printf("ループを脱出します。\n");
break;
}
}
}
</syntaxhighlight>
:※註 過去の版では、scanf_s の戻り値をチェックしていませんでしたが EOF を返す可能性があり、これを無視すると、それこそ'''無限ループ'''になってしまうので、戻り値も必ずチェックしましょう。また、この部分は return 文による脱出の例にもなっています。
このプログラムを終了するには、y(Yの小文字)を入力してエンターキーを押します。入力する「y」は直接入力モード(Windowsの場合は半角英数)にしてください。
なお、文字変数の中身を示す「'y'」のように、文字リテラルは ' (シングルクォーテーションマーク)で囲みます。文字列リテラルを囲む " (ダブルクォーテーションマーク)と間違えないうようにしましょう<ref>生徒に教えていると、" であるべきところを '' と書いているパターンのほうが多く、また発見が遅れます。</ref>。
=== do-while文 ===
|