🖥️

【C言語超入門】 おまけ1 ジャンプ

に公開

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}{四国めたん:} とはいえ、ifelse文を使えば、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);
    }
  }
}

あほの出力2

\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);
  }
}

zで終わる

\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}{四国めたん:} なお、少し複雑ですが、ifelse文とフラグを使えば、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);
    }
  }
}

zで終わる2

\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}{四国めたん:} 基本的な書き方はこのようになりますわ

goto ラベル;

\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}{四国めたん:} ところで、continuebreakは、できるだけ使用は避けるべきだと思いますわ

\footnotesize \textcolor{lime}{ずんだもん:} りょうかいなのだ

\footnotesize \textcolor{pink}{四国めたん:} また、gotoについては、余程の事情がない限り、使用しないことをお勧めしますわ

\footnotesize \textcolor{lime}{ずんだもん:} わかったのだ

Discussion