https://youtu.be/L0S5Ml_0ueY

\textcolor{pink}{四国めたん: }教師役ですわ

\textcolor{lime}{ずんだもん: }生徒役なのだ
\footnotesize \textcolor{pink}{四国めたん:} 皆さん、こんにちは。四国めたんです
\footnotesize \textcolor{lime}{ずんだもん:} ずんだもんなのだ。こんにちはなのだ
\footnotesize \textcolor{pink}{四国めたん:} 今回もC言語のお勉強をしていきましょう
\footnotesize \textcolor{lime}{ずんだもん:} レッツゴーなのだ
\footnotesize \textcolor{pink}{四国めたん:} 今までC言語の文法を中心にお話ししてきましたわ
\footnotesize \textcolor{lime}{ずんだもん:} そうだったのだ
\footnotesize \textcolor{pink}{四国めたん:} 今回は、文法の中でも 無条件ジャンプ についてお話ししますわ
\footnotesize \textcolor{lime}{ずんだもん:} ところで、なぜ おまけ なのだ?
\footnotesize \textcolor{pink}{四国めたん:} なぜ おまけ なのかと云うと、基本的に使ってほしくないからですわ
\footnotesize \textcolor{lime}{ずんだもん:} 使ってほしくないのに解説するのか?
\footnotesize \textcolor{pink}{四国めたん:} はい、キーワードとして決められている以上、 無条件ジャンプ が使われているプログラムも多く存在しますわ
\footnotesize \textcolor{lime}{ずんだもん:} そうなのか?
\footnotesize \textcolor{pink}{四国めたん:} そのようなプログラムを読んだ時に、意味が解らないのでは困ることになりますわ
\footnotesize \textcolor{lime}{ずんだもん:} たしかにその通りなのだ
\footnotesize \textcolor{pink}{四国めたん:} さらに、決められた場所、決められた条件で使う場合にはOKとされることもあるのですわ
\footnotesize \textcolor{lime}{ずんだもん:} なるほどなのだ
\footnotesize \textcolor{pink}{四国めたん:} まぁ、プログラム中に使われていたら、意味が解る程度で充分ですわ
\footnotesize \textcolor{lime}{ずんだもん:} おまけと云うことで軽く流すのだ
continue
\footnotesize \textcolor{pink}{四国めたん:} 最初はcontinue
ですわ
\footnotesize \textcolor{lime}{ずんだもん:} continue
?
\footnotesize \textcolor{pink}{四国めたん:} はい、使う場所は、基本的に forループ および whileループ などのループの中ですわ
\footnotesize \textcolor{lime}{ずんだもん:} 使う場所が決まっているのか...
\footnotesize \textcolor{pink}{四国めたん:} 例えば forループ 中でcontinue
が実行されると、無条件で処理が forループ の先頭に戻りますわ
for (int i = 0; i < 10; i++) { // (1)
:
continue; // (2)
:
:
} // (3)
\footnotesize \textcolor{lime}{ずんだもん:} 説明をお願いするのだ
\footnotesize \textcolor{pink}{四国めたん:} (2)の部分でcontinue
が実行されると、そのまま(1)に戻って forループ が続行しますわ
\footnotesize \textcolor{lime}{ずんだもん:} なるほどなのだ
\footnotesize \textcolor{pink}{四国めたん:} とはいえ、このようにcontinue
が単独で現れるようなプログラムであれば、(2)から(3)のあいだの処理がおこなわれなくなりますわ
\footnotesize \textcolor{lime}{ずんだもん:} たしかにその通りなのだ
\footnotesize \textcolor{pink}{四国めたん:} そのため、通常はif
文と組み合わせて使われますわ
for (int i = 0; i < 10; i++) {
:
if (条件) continue;
:
:
}
\footnotesize \textcolor{lime}{ずんだもん:} 説明をお願いするのだ
\footnotesize \textcolor{pink}{四国めたん:} if
文で条件がtrue
の場合のみ、continue
によりあとに続く処理を飛ばして、 forループ の先頭に戻りますわ
\footnotesize \textcolor{lime}{ずんだもん:} りょうかいなのだ
\footnotesize \textcolor{pink}{四国めたん:} とりあえず、サンプルとしてループが3の倍数の時に「あほ」と出力するプログラムを作ってみますわ
\footnotesize \textcolor{lime}{ずんだもん:} ずいぶんと昔のお笑いなのだ
\footnotesize \textcolor{pink}{四国めたん:} うるさいですわ
#include <stdio.h>
void main() {
for (int i = 0; i < 10; i++) {
if ((i % 3) == 0) {
printf("%d: あほです\n", i);
continue;
}
printf("%d: \n", i);
}
}

\footnotesize \textcolor{lime}{ずんだもん:} 3の倍数の時には、printf("%d: あほです\n", i);
のあとにcontinue;
があるのだ
\footnotesize \textcolor{pink}{四国めたん:} まあ、結果として forループ の先頭にもどるため、printf("%d: \n", i);
は実行されていませんわ
\footnotesize \textcolor{lime}{ずんだもん:} 3の倍数以外の時にはprintf("%d: \n", i);
が実行されているのだ
\footnotesize \textcolor{pink}{四国めたん:} とはいえ、if
~else
文を使えば、continue
を使わなくても、同じことが可能ですわ
#include <stdio.h>
void main() {
for (int i = 0; i < 10; i++) {
if ((i % 3) == 0) {
printf("%d: あほです\n", i);
} else {
printf("%d: \n", i);
}
}
}

\footnotesize \textcolor{lime}{ずんだもん:} とりあえず同じ出力となっているのだ
\footnotesize \textcolor{pink}{四国めたん:} ちなみにループが多重構造になっている場合には、continue
が記述されている内側のループの先頭に戻りますわ
\footnotesize \textcolor{lime}{ずんだもん:} そうなのか?
for (int i = 0; i < 10; i++) { // (1)
for (int j = 0; j < 10; j++) { // (2)
:
if (条件) continue; // (3)
:
}
:
if (条件) continue; // (4)
:
:
}
\footnotesize \textcolor{pink}{四国めたん:} (3)でcontinue
が実行される場合には、(2)に戻りますわ
\footnotesize \textcolor{lime}{ずんだもん:} うむ
\footnotesize \textcolor{pink}{四国めたん:} (4)でcontinue
が実行される場合には、(1)に戻りますわね
\footnotesize \textcolor{lime}{ずんだもん:} なるほどなのだ
\footnotesize \textcolor{pink}{四国めたん:} 2重程度のループなら簡単ですが、3重、4重とループの数が多くなり、continue
が頻繁に使われると、バグの温床となるので注意が必要ですわ
\footnotesize \textcolor{lime}{ずんだもん:} りょうかいなのだ
\footnotesize \textcolor{pink}{四国めたん:} まぁ、continue
を使った方が見やすいと云うプログラマーも、それなりにるので、一概に悪いとは言い切れないのですが...
\footnotesize \textcolor{lime}{ずんだもん:} 難しいのだ
\footnotesize \textcolor{pink}{四国めたん:} できるなら使わないことをお勧めしますわ
break
\footnotesize \textcolor{pink}{四国めたん:} 次はbreak
ですわ
\footnotesize \textcolor{lime}{ずんだもん:} break
?
\footnotesize \textcolor{pink}{四国めたん:} はい、使う場所は、基本的に forループ および whileループ などのループの中とswitch
文の中ですわ
\footnotesize \textcolor{lime}{ずんだもん:} switch
文とはなんなのだ?
\footnotesize \textcolor{pink}{四国めたん:} switch
文については別途、お話ししますわ
\footnotesize \textcolor{lime}{ずんだもん:} 待っているのだ
\footnotesize \textcolor{pink}{四国めたん:} break
ですが、例えば forループ 中でbreak
が実行されると、無条件で forループ を脱出しますわ
\footnotesize \textcolor{lime}{ずんだもん:} そうなのか?
for (int i = 0; i < 10; i++) { // (1)
:
break; // (2)
:
:
} // (3)
: // (4)
\footnotesize \textcolor{pink}{四国めたん:} (2)の部分に処理が移ると、そのまま forループ を抜けて(4)に処理が移りますわ
\footnotesize \textcolor{lime}{ずんだもん:} りょうかいなのだ
\footnotesize \textcolor{pink}{四国めたん:} とはいえ、このようにbreak
が単独で現れるようなプログラムであれば、(2)から(3)のあいだの処理がおこなわれなくなりますわ
\footnotesize \textcolor{lime}{ずんだもん:} たしかに...
\footnotesize \textcolor{pink}{四国めたん:} また、 forループ の最初でループが終了してしまいますわ
\footnotesize \textcolor{lime}{ずんだもん:} なるほどなのだ
\footnotesize \textcolor{pink}{四国めたん:} そのため、通常はif
文と組み合わせて使われますわ
for (int i = 0; i < 10; i++) {
:
if (条件) break;
:
:
}
\footnotesize \textcolor{pink}{四国めたん:} 条件にあった時のみ、あとに続く処理を飛ばして forループ を終了しますわ
\footnotesize \textcolor{lime}{ずんだもん:} ふむふむ
\footnotesize \textcolor{pink}{四国めたん:} とりあえず、サンプルとしてキーボードから\fcolorbox{blue}{lightgray}{z}を入力した場合に終了するプログラムを作ってみますわ
#include <stdio.h>
#include <conio.h>
void main() {
for (int i = 0; i < 10; i++) {
printf("キーボードから文字を入力して下さい。\n");
int c = _getch();
if (c == 'z') {
printf("ループを抜けます。\n");
break;
}
printf("キーボードからの入力は%cです。\n", c);
}
}

\footnotesize \textcolor{pink}{四国めたん:} キーボードから\fcolorbox{blue}{lightgray}{z}を入力すれば、break
によりループを抜けますわ
\footnotesize \textcolor{lime}{ずんだもん:} ループの回数は関係あるのか?
\footnotesize \textcolor{pink}{四国めたん:} 関係ありませんわね
\footnotesize \textcolor{pink}{四国めたん:} ただ、キーボードからの入力が10回に達すれば、break
に関係なく forループ を抜けますわ
\footnotesize \textcolor{lime}{ずんだもん:} forループ の条件式がそのようになっているのだ
\footnotesize \textcolor{pink}{四国めたん:} なお、少し複雑ですが、if
~else
文とフラグを使えば、break
を使わなくても、同じことが可能ですわ
#include <stdio.h>
#include <conio.h>
#include <stdbool.h>
void main() {
bool flag = true;
for (int i = 0; (i < 10) && flag ; i++) {
printf("キーボードから文字を入力して下さい。\n");
char c = _getch();
if (c == 'z') {
printf("ループを抜けます。\n");
flag = false;
} else {
printf("キーボードからの入力は%cです。\n", c);
}
}
}

\footnotesize \textcolor{lime}{ずんだもん:} とりあえず同じ出力となっているのだ
\footnotesize \textcolor{pink}{四国めたん:} はい、 forループ の条件式に"flag"を使ってループの中断の判断を追加していますわ
\footnotesize \textcolor{lime}{ずんだもん:} ふむ
\footnotesize \textcolor{pink}{四国めたん:} そしてbreak
の代わりにflag = false
でループの中断を指定していますわ
\footnotesize \textcolor{lime}{ずんだもん:} なるほどなのだ
\footnotesize \textcolor{pink}{四国めたん:} ちなみにループが多重構造になっている場合には、break
が記述されている内側のループを抜けますわ
\footnotesize \textcolor{lime}{ずんだもん:} そうなのか?
for (int i = 0; i < 10; i++) { // (1)
for (int j = 0; j < 10; j++) { // (2)
:
if (条件) break; // (3)
}
: // (4)
if (条件) break; // (5)
:
:
}
: // (6)
\footnotesize \textcolor{pink}{四国めたん:} (3)でbreak
が実行される場合には、(2)のループを抜けて(4)に処理が移りますわ
\footnotesize \textcolor{lime}{ずんだもん:} ふむ
\footnotesize \textcolor{pink}{四国めたん:} (5)でbreak
が実行される場合には、(1)のループを抜けて(6)に処理が移りますわね
\footnotesize \textcolor{lime}{ずんだもん:} なるほどなのだ
\footnotesize \textcolor{pink}{四国めたん:} 2重程度のループなら簡単ですが、3重、4重とループの数が多くなり、break
が頻繁に使われると、バグの温床となるので注意が必要ですわ
\footnotesize \textcolor{lime}{ずんだもん:} りょうかいなのだ
\footnotesize \textcolor{pink}{四国めたん:} まぁ、break
を使った方が見やすいと云うプログラマーも多いので、一概に悪いとは言い切れないのですが...
\footnotesize \textcolor{lime}{ずんだもん:} そうなのか?
\footnotesize \textcolor{pink}{四国めたん:} とにかくbreak
を使う場合には、充分な注意が必要ですわ
goto
\footnotesize \textcolor{pink}{四国めたん:} 最後はgoto
ですわ
\footnotesize \textcolor{lime}{ずんだもん:} goto
?
\footnotesize \textcolor{pink}{四国めたん:} 文字通りの無条件ジャンプですわね
\footnotesize \textcolor{lime}{ずんだもん:} ふむふむ
\footnotesize \textcolor{pink}{四国めたん:} 基本的な書き方はこのようになりますわ
\footnotesize \textcolor{pink}{四国めたん:} ちなみに ラベル については、同じ関数内に配置しますわ
\footnotesize \textcolor{lime}{ずんだもん:} ラベル のあとにコロン":"が付加されているのだ
\footnotesize \textcolor{pink}{四国めたん:} はい、そして基本的に ラベル は見やすくするために、 ラベル のみで1行を使うことをお勧めしますわ
\footnotesize \textcolor{lime}{ずんだもん:} りょうかいなのだ
\footnotesize \textcolor{pink}{四国めたん:} また、アンインデント、もしくは行頭から記述するほうがいいですわね
\footnotesize \textcolor{lime}{ずんだもん:} アンインデント?
\footnotesize \textcolor{pink}{四国めたん:} インデントの逆で、書き始めを数文字、左にずらすのですわ
\footnotesize \textcolor{lime}{ずんだもん:} なるほどなのだ
\footnotesize \textcolor{pink}{四国めたん:} また、 ラベル はキーワード以外であれば、概ね、どのような名前としてもOKですわ
\footnotesize \textcolor{lime}{ずんだもん:} そうなのか?
\footnotesize \textcolor{pink}{四国めたん:} そして、一般的にはスネークケースが、よく使われるようですわね
\footnotesize \textcolor{lime}{ずんだもん:} りょうかいなのだ
\footnotesize \textcolor{pink}{四国めたん:} なお、ループやif
文の外からループ内やif
文の内側に、goto
でジャンプすることはできませんわ
\footnotesize \textcolor{lime}{ずんだもん:} そうなのか?
\footnotesize \textcolor{pink}{四国めたん:} 反対に、ループやif
文の内からループ外やif
文の外側に、goto
でジャンプすることは一般的な使い方ですわね
\footnotesize \textcolor{lime}{ずんだもん:} なるほどなのだ
\footnotesize \textcolor{pink}{四国めたん:} とりあえず使ってみましょう
#include <stdio.h>
#include <stdlib.h>
#include <conio.h>
#define SIZE (50)
void main() {
char* ptext = (char*)malloc(SIZE);
for (int i = 0; i < 10 ; i++) {
printf("キーボードから文字を入力して下さい。\n");
int c = _getch();
if (c == 'z') {
printf("緊急脱出します。\n");
goto clean_up;
} else {
printf("キーボードからの入力は%cです。\n", c);
}
}
printf("ループを抜けました。\n");
clean_up:
free(ptext);
ptext = NULL;
}

\footnotesize \textcolor{pink}{四国めたん:} まず、最初にmalloc
でメモリ領域を確保していますわ
\footnotesize \textcolor{lime}{ずんだもん:} プログラム内では使っていないのだ
\footnotesize \textcolor{pink}{四国めたん:} とりあえずサンプルと云うことで...
\footnotesize \textcolor{lime}{ずんだもん:} むぅ、仕方がないのだ
\footnotesize \textcolor{pink}{四国めたん:} そして、最後にfree
で開放していますわ
\footnotesize \textcolor{lime}{ずんだもん:} free
で開放するのは大事なのだ
\footnotesize \textcolor{pink}{四国めたん:} なお、free
の前にclean_up:
と云うラベルがありますが、ラベルはgoto
のジャンプ先の目印の意味しかありませんわ
\footnotesize \textcolor{lime}{ずんだもん:} プログラムに影響を与えることはないと云うことか...
\footnotesize \textcolor{pink}{四国めたん:} その通りですわね
\footnotesize \textcolor{pink}{四国めたん:} そして、 forループ 内では、キーボードから1文字の入力を受け付けますわ
\footnotesize \textcolor{lime}{ずんだもん:} ふむ
\footnotesize \textcolor{pink}{四国めたん:} \fcolorbox{blue}{lightgray}{z}以外が入力された場合には、入力された文字をコンソールに表示しますわ
\footnotesize \textcolor{lime}{ずんだもん:} ふむふむ
\footnotesize \textcolor{pink}{四国めたん:} そして、ループが10回になると、ループを抜けて、 ループを抜けました。 と表示されてfree
によるメモリ開放へと処理が移りますわ
\footnotesize \textcolor{lime}{ずんだもん:} なるほどなのだ
\footnotesize \textcolor{pink}{四国めたん:} もしループ中で\fcolorbox{blue}{lightgray}{z}が入力されると、goto
によってclean_up
ラベルの位置に強制的にジャンプしますわ
\footnotesize \textcolor{lime}{ずんだもん:} ループの状態は無視されるのか?
\footnotesize \textcolor{pink}{四国めたん:} そうですわね
\footnotesize \textcolor{pink}{四国めたん:} また、break
と異なり、ループ直後のprintf("ループを抜けました。\n");
の行も無視されますわ
\footnotesize \textcolor{lime}{ずんだもん:} りょうかいなのだ
\footnotesize \textcolor{pink}{四国めたん:} なお、その性質上、break
と異なって、多重ループの深い場所から、一気にループを抜け出すこともできますわ
\footnotesize \textcolor{lime}{ずんだもん:} お~、便利なのだ
\footnotesize \textcolor{pink}{四国めたん:} 便利であっても、goto
は使わないでくださいね
\footnotesize \textcolor{lime}{ずんだもん:} わかったのだ
return
\footnotesize \textcolor{pink}{四国めたん:} おまけでreturn
ですわ
\footnotesize \textcolor{lime}{ずんだもん:} 今までも関数でreturn
を使っていたのだ
\footnotesize \textcolor{pink}{四国めたん:} はい、基本的には、関数の戻り値を指定するとともに、関数を脱出するために使われますわ
\footnotesize \textcolor{lime}{ずんだもん:} その通りなのだ
\footnotesize \textcolor{pink}{四国めたん:} return
が実行されると無条件で関数から脱出することから、いわゆる無条件ジャンプと考えてもいいかと思いますわ
\footnotesize \textcolor{lime}{ずんだもん:} 少し無理があるのでは?
\footnotesize \textcolor{pink}{四国めたん:} そうなのですが、return
によって関数を脱出する部分が多い場合、関数内のプログラムの流れが解りにくくなってしまうのですわ
\footnotesize \textcolor{lime}{ずんだもん:} なるほどなのだ
\footnotesize \textcolor{pink}{四国めたん:} そして、それを嫌うプログラマーもいるようですわ
\footnotesize \textcolor{lime}{ずんだもん:} そうなのか?
\footnotesize \textcolor{pink}{四国めたん:} はい、中には関数の最後にのみreturn
を記述するプログラマーもいるようですわ
\footnotesize \textcolor{lime}{ずんだもん:} かなりストイックなのだ
\footnotesize \textcolor{pink}{四国めたん:} いずれにしても、関数中でreturn
を多用するのは避けた方が良さそうですわ
\footnotesize \textcolor{lime}{ずんだもん:} りょうかいなのだ
まとめ
\footnotesize \textcolor{pink}{四国めたん:} お疲れさまでした
\footnotesize \textcolor{lime}{ずんだもん:} おつかれさまなのだ
\footnotesize \textcolor{pink}{四国めたん:} 以上で ジャンプ を終わりますわ
\footnotesize \textcolor{pink}{四国めたん:} ところで、continue
やbreak
は、できるだけ使用は避けるべきだと思いますわ
\footnotesize \textcolor{lime}{ずんだもん:} りょうかいなのだ
\footnotesize \textcolor{pink}{四国めたん:} また、goto
については、余程の事情がない限り、使用しないことをお勧めしますわ
\footnotesize \textcolor{lime}{ずんだもん:} わかったのだ
Discussion