「C言語/制御文」の版間の差分

削除された内容 追加された内容
Ef3 (トーク | 投稿記録)
{{コラム|Visual Studio で、デバッグ セッションの終了時にコンソールが閉じてしまう場合| Visual Studio で、デバッグ セッションの終了時にコンソールが閉じてしまう場合は、 : [ツール] -> [オプション] -> [デバッグ] -> [デバッグの停止時に自動的にコンソールを閉じる] を無効にします。 }}
タグ: 2017年版ソースエディター
Ef3 (トーク | 投稿記録)
→‎分岐文: cleanup
タグ: 2017年版ソースエディター
725 行
 
== 分岐文 ==
分岐文( jump statements )は、無条件に別の場所にジャンプします<ref name="jtc1-sc22-wg14-n2596-6.8.6">{{cite book
=== break文 ===
| url=http://www.open-std.org/jtc1/sc22/wg14/www/docs/n2596.pdf
<ref>『JISX3010:2003』p.105「6.8.6.3 break文」</ref>
| title= N2596 working draft — December 11, 2020 ISO/IEC 9899:202x (E)
break文(ブレイクぶん)は、スイッチ本体またはループ本体の中で使われ、
| page=126, §6.8.6 ''The jump statements''
スイッチ本体またはループ本体の直後へ制御を移す。
| publisher = [http://www.open-std.org/jtc1/sc22/wg14/www/projects ISO/IEC JTC1/SC22/WG14]}}</ref>。
 
構文
英語における「break」(ブレイク)とは、よく「壊す」(こわす)の意味でbreakが使われますが、「中断(ちゅうだん)する」という意味もbreakにはあります。
jump-statement:
[[#goto文|goto]] identifier ;
[[#continue文|continue]] ;
[[#break文|break]] ;
[[#return文|return]] expression<sub>opt</sub> ;
 
=== goto文 ===
プログラミングにおけるbreak文は、ソレを使うことでスイッチ本体またはループ本体から抜け出す動作をします。
goto文( goto statement )は、包含する関数内の、名前の付いたラベルを先頭に持つ文に無条件にジャンプします<ref name="jtc1-sc22-wg14-n2596-6.8.6.1">{{cite book
| url=http://www.open-std.org/jtc1/sc22/wg14/www/docs/n2596.pdf
| title= N2596 working draft — December 11, 2020 ISO/IEC 9899:202x (E)
| page=126, §6.8.6.1 ''The goto statement''
| publisher = [http://www.open-std.org/jtc1/sc22/wg14/www/projects ISO/IEC JTC1/SC22/WG14]}}</ref><ref>『JISX3010:2003』p.103「6.8.6.1 goto文」</ref>。
goto文の識別子は、包含する関数のどこかにあるラベルを指し示さなければなりません<ref name="jtc1-sc22-wg14-n2596-6.8.6.1"/>。
goto文は、可変的に変更された型を持つ識別子のスコープ外から、その識別子のスコープ内にジャンプしてはなりません<ref name="jtc1-sc22-wg14-n2596-6.8.6.1"/>
 
;goto文の形式:<syntaxhighlight lang="C">
 
goto 識別子 ;
 
break文の記述は次のようになっている。
* break文
<syntaxhighlight lang="C">
break;
</syntaxhighlight>
;ラベル文の形式:<syntaxhighlight lang="C">
 
識別子 :
<syntaxhighlight lang="C">
</syntaxhighlight>
//例 break文の使用例
;[https://paiza.io/projects/KhbOJ-86RYOk0V_up6nyjQ?language=c 例]:<syntaxhighlight lang="C">
#include <stdio.h>
#include <math.h>
 
int main(void) {
int x, y;
{
while for (y = 1; y <= 9; ++y) {
for (x = 1; x <= 9; ++x) {
double d;
if (y * x >= 50)
printf("正の数を入力してください。(0以下で終了):");
goto exit_loop;
scanf("%lf", &d);
}
if (d<=0) break;
}
printf("%fの平方根は%f。\n", d, sqrt(d));
exit_loop:
}
printf("九九の表で、最初に50以上になるのは%d×%d。\n", y, x);
}
</syntaxhighlight>
 
{{コラム|goto文の使用は一般的に推奨されせん。|
また、break文は、break文を含む最も内側のスイッチ本体またはループ本体に対応する。
goto文の使用は一般的に推奨されません。
その理由は、コードの構造が把握しにくくなるからです(スパゲッティコード)。
また、入れ子になった複数のスイッチやループから逃れるために(大域脱出)、goto文が使われることがありますが、大域脱出は、ループを関数にしてreturn文で脱出したり、setjmpとlongjmpを使うなど、他の方法でも実現できます。
}}
 
=== forcontinueの中のif文のbreak ===
continue文( ''continue statement'' )は、それを囲む最小の反復文のループ継続部分、すなわち、ループ本体の終わりにジャンプする<ref name="jtc1-sc22-wg14-n2596-6.8.6.2">{{cite book
[[File:Destination Break Programming in If sentence in For sentence.svg|thumb|600px|break文の移動先の説明図]]
| url=http://www.open-std.org/jtc1/sc22/wg14/www/docs/n2596.pdf
| title= N2596 working draft — December 11, 2020 ISO/IEC 9899:202x (E)
| page=126, §6.8.6.2 ''The continue statement''
| publisher = [http://www.open-std.org/jtc1/sc22/wg14/www/projects ISO/IEC JTC1/SC22/WG14]}}</ref><ref>『JISX3010:2003』p.104「6.8.6.2 continue文」</ref>。
; 制約事項
: continue文は、ループ本体の中にのみ現れることが許されます。
 
;コード例
右図のようにfor文の中にif文があり、そのif文のブロック内に break; がある場合、
:{|
 
|<syntaxhighlight lang="C">
breakによって抜け出す先は、if文のひとつ上にあるfor文の終了直後の地点です。
while (/* ... */) {
 
/* ... */
for文が2つ以上ある場合、break文で一気に複数のfor文を抜け出すことは '''できない''' です。
continue;
 
/* ... */
{{-}}
contin:
 
}
=== return文 ===
<ref>『JISX3010:2003』p.103「6.8.6.4 return文」</ref>
return文(リターンぶん)とは、分岐文の内の1つであり、実行中の関数を終了し、その呼び出し元へ制御を返す。
式があるかどうかは関数の返却値のデータ型により異なり、
void型の場合は式がなく、それ以外のデータ型の場合は式がある。
 
 
return文の記述は次のようになっている。
* return文
<syntaxhighlight lang="C">
return 式;
</syntaxhighlight>
|<syntaxhighlight lang="C">
 
do {
<syntaxhighlight lang="C">
/* ... */
//例 return文の使用例
continue;
#include <stdio.h>
/* ... */
 
contin:;
//整数1234を返す関数function
} while (/* ... */);
int function()
</syntaxhighlight>
{
|<syntaxhighlight lang="C">
return 1234;
for (/* ... */) {
}
/* ... */
 
continue;
int main(void)
/* ... */
{
contin:
int i=function();//関数functionを呼び、返却値をiに代入する。
printf("iの値は%d。", i);
}
</syntaxhighlight>
|}
:上のコード例での continue は、goto continと同等です<ref>2番目の例のcontin:ラベルに続くのは、NULL文です。1つ目と3つ目の例のnull文は、ラベルによって暗示されてます。</ref>。
 
;形式:<syntaxhighlight lang="C">
 
returnの英語の日常での意味と、プログラミングにおけるreturnの意味は、大きく違うので、初心者は、あまり気にしないほうがイイです。
 
returnの意味は、英語では、よく「戻ってくる」「帰ってくる」の意味で使われたり、借りたものが返って来る、借りたものを返すなどの意味で使われこともありますが、他にも質問や意見などに「言い返す」などの意味があったり、投資などで利益を返すという意味もあります。(※ ジーニアス英和辞典にちゃんとそう書いてもある。)
 
 
=== continue文 ===
[[File:Destination Continue Programming in If sentence in For sentence.svg|thumb|500px|continue文の移動先の説明図]]
 
<!--
<ref>『JISX3010:2003』p.104「6.8.6.2 continue文」</ref>
continue文(コニュティニューぶん)とは、分岐文の内の1つであり、ループ本体の中で使われ、ループ本体の終わりへ制御を移す。
つまり、ただちに制御式が実行され、それからループが繰り返される。
ループ本体の終わりとはcontinue文を含む最も内側のループ本体の最後の文の直後である。
 
※ 出典があるようですが、初学者に誤解を与える記述なので、非表示にします。
-->
 
continue文(コニュティニューぶん)とは、ブロック内のその後の処理をスキップし、カウンタを一回分だけ進めて、ループ先頭の判定からの処理に戻らせて再走させる処理です。
 
 
continue文の記述は次のようになっている。
* continue文
<syntaxhighlight lang="C">
continue;
</syntaxhighlight>
;[https://paiza.io/projects/IM89XiUvAXhyRY6_KHv7hA?language=c continue文の使用例]:
 
<syntaxhighlight lang="C">
//例 continue文の使用例
#include <stdio.h>
 
int main(void) {
// 1から14までの整数の中で、3の倍数以外を表示する。
for (int i = 1; i <= 14; i++) {
for (i = 1; i <= 14; ++i) {
 
if (i % 3 == 0) {
continue;
845 ⟶ 830行目:
}
</syntaxhighlight>
;実行結果:<syntaxhighlight lang="text">
 
実行結果
<pre>
1
2
858 ⟶ 841行目:
13
14
</syntaxhighlight>
</pre>
 
上の実行結果では、3の倍数の「3」と「6」と「9」と「12」が抜けています。
864 ⟶ 847行目:
このように、continue 文は、そのループ内の以降の処理をスキップしつつも、カウントを1回ぶん、進めます。
 
=== break文 ===
{{-}}
break文( break statement)は、最小のswitch文または反復文を囲むものの実行を終了させます<ref name="jtc1-sc22-wg14-n2596-6.8.6.3">{{cite book
| url=http://www.open-std.org/jtc1/sc22/wg14/www/docs/n2596.pdf
| title= N2596 working draft — December 11, 2020 ISO/IEC 9899:202x (E)
| page=127, §6.8.6.3 ''The break statement''
| publisher = [http://www.open-std.org/jtc1/sc22/wg14/www/projects ISO/IEC JTC1/SC22/WG14]}}</ref><ref>『JISX3010:2003』p.105「6.8.6.3 break文」</ref>。
break文は、switch本体またはloop本体の中以外に現れてはいけません。
 
break文の記述は次のようになっている。
=== goto文 ===
;形式:<syntaxhighlight lang="C">
<ref>『JISX3010:2003』p.103「6.8.6.1 goto文」</ref>
break;
goto文とは、分岐文の内の1つであり、指定するラベルへ制御を移す。
</syntaxhighlight>
goto文は、識別子が指すラベルへ制御を移す。
;例:<syntaxhighlight lang="C">
そのラベルはgoto文を含む関数内になければならない(関数有効範囲)。<ref>『JISX3010:2003』p.21「6.2.1 識別子の有効範囲」</ref>
#include <stdio.h>
#include <math.h>
 
int main(void) {
<pre>
while (1) {
goto文の使用は一般には推奨されません。
double d;
理由は構造を把握しづらいコード(スパゲティコード)となるからです。
printf("正の数を入力してください。(0以下で終了):");
また、goto文は多重にネストされたスイッチやループから抜け出すために使われることがありますが、
scanf("%lf", &d);
それも関数化してreturn文で抜け出すように書き換えることができます。
if (d <= 0)
</pre>
break;
printf("%fの平方根は%f。\n", d, sqrt(d));
}
}
</syntaxhighlight>
 
=== for文の中のif文のbreak ===
goto文及びラベルの記述は次のようになっている。
<!--[[File:Destination Break Programming in If sentence in For sentence.svg|thumb|600px|break文の移動先の説明図]]-->
* goto文
<syntaxhighlight lang="C" highlight="5,9" line>
for (・・・) {
goto 識別子;
for (・・・) {
</syntaxhighlight>
for (・・・) {
* ラベル
if (・・・) {
<syntaxhighlight lang="C">
break;
識別子:
}
/* ・・・ */
}
break_point:
}
}
</syntaxhighlight>
kこのように、for文の中にif文があり、if文のブロックの中にbreak;がある場合、一番内側のfor文の終わりに処理が移ります(ここでは、ラベル break_point の位置)。
for文が2つ以上ある場合、break文で複数のfor文を一度に抜け出すことは'''不可能'''です。
 
=== return文 ===
return文( ''return statement'' )は、現在の関数の実行を終了し、呼び出し元に制御を返します<ref name="jtc1-sc22-wg14-n2596-6.8.6.4">{{cite book
| url=http://www.open-std.org/jtc1/sc22/wg14/www/docs/n2596.pdf
| title= N2596 working draft — December 11, 2020 ISO/IEC 9899:202x (E)
| page=127, §6.8.6.4 ''The return statement''
| publisher = [http://www.open-std.org/jtc1/sc22/wg14/www/projects ISO/IEC JTC1/SC22/WG14]}}</ref>
<ref>『JISX3010:2003』p.103「6.8.6.4 return文」</ref>。
関数はいくつでもreturn文を持つことができます<ref name="jtc1-sc22-wg14-n2596-6.8.6.4"/>。
式を持つreturn文が実行されると、その式の値が関数呼び出し式の値として呼び出し元に返されます。式の型がその関数の戻り値の型と異なる場合、その値は関数の戻り値の型を持つオブジェクトに代入されたように変換されます<ref name="jtc1-sc22-wg14-n2596-6.8.6.4"/>。
式を持つreturn文は、戻り値の型がvoidである関数の中に現れてはなりません。式を伴わないreturn文は、戻り値の型がvoidである関数の中でのみ現れます<ref name="jtc1-sc22-wg14-n2596-6.8.6.4"/>。
 
;形式:<syntaxhighlight lang="C">
return 式;
// 例 goto文の使用例
</syntaxhighlight>
;[https://paiza.io/projects/-WEWEhXg14BxtL3A9tMsiA?language=c 例]:<syntaxhighlight lang="C">
#include <stdio.h>
 
//整数1234を返す関数function
int main(void)
int function() { return 1234; }
{
 
int x,y;
int main(void) {
for(y=1;y<=9;++y){
int i = function(); //関数functionを呼び、返却値をiに代入する。
for(x=1;x<=9;++x){
printf("iの値は%d。", i);
if(y*x>=50)goto exit_loop;
}
}
exit_loop:
printf("九九の表で、最初に50以上になるのは%d×%d。\n", y, x);
}
</syntaxhighlight>