プロも9割が間違えてる?C言語の繰り返し回数を侮るなかれ!

こんちゃっす、ダイブツです。

今回は、プログラムを書く時には必ず使うといっても過言ではないC言語の「繰り返し処理」というものを勉強していきましょう。

この繰り返し処理が使えるようになることで、プログラムを書くスピードが劇的に早くなります
僕の感覚では最低3倍はプログラムを書くスピードが上がりますね。

この記事では、その繰り返し処理を使って、下のようにLEDを点滅させる方法を説明していきます!

それでは繰り返し処理の入門編始めます!

 

繰り返し処理の使い方

まず、繰り返し処理ってどんなものなんでしょう?

その名の通り、「処理を繰り返すこと」です。

例えば、LED点灯⇒消灯する処理を作ったとします。
「この処理を何度も実行させたい・・・」と思った時に使うのが繰り返し処理です。

そして、この繰り返し処理を書く方法は実は2種類あるんです。

まずはその2種類の書き方を見ていきましょう。

ただ、今回の内容は後から学ぶif文の学習と関わる部分があります。

なので、一旦今回の概要を確認してからif文の学習記事を読むと、より今回の内容について理解が深まるので是非こっちも読んでくださいね。

 ⇒【C言語入門者専用】if文の条件式15個(else、switch含)全て教えます

 

繰り返し処理1:while文の書き方

まず最初にwhile文の書き方を見ていきましょう。

whileを使って6回繰り返す処理を簡単に書くとこうなります。

 

int i = 1;

while(i <= 6){
  繰り返したい処理
  i++;
}

 

これはiが6以下の時は{}内の処理を繰り返すという書き方になります。

つまり、

1、繰り返したい処理
2、i++;

の処理を1→2→1→2→…→1→2と6回繰り返すということです。

 

そして、サラッと書いていますが、「i++」というのは、「i = i + 1」を略した書き方です。

なので、最初に「i++」を実行する時は、iの値が1なので、1 + 1 = 2の値がiに代入されるということです。

この「i++」を6回実行するとiの値が7になりますよね?

そうすると、iが6よりも大きくなったということで、while(i <= 6)の内容と異なったから処理を止めるという動き方をします。

これがwhile文の書き方です。

 

それと、この使っていた「i++」ですが、「i- -」も書くことができます。こっちは引き算の処理ですね。

ちなみに「i++」のように足していくことをインクリメント、「i- -」のように引いていくことをデクリメントと言うので覚えておきましょう。結構使われる言葉です。

 

繰り返し処理2:for文の書き方

次はもう1つの繰り返し処理、for文の書き方について説明していきます。

まずはwhileと同じように6回繰り返す処理を簡単に書いてみますね。

 

for(int i = 1; i <= 6; i++){
  繰り返したい処理
}

 

こっちはwhileと比べて大分スッキリとしてますね。

それもそのはず、for文の方は、一行に変数の宣言と繰り返す条件、定義した変数を計算する式をまとめて書いているんです。

 

だからちょっとややこしいんですが、for文のint i = 1;は最初の1回だけしか実行されません

後の繰り返し処理ではi <= 6;とi++だけが繰り返されます。

 

あと今更ですが、変数名がiになっていることに違和感はありませんでしたか?

そう、前回の変数編で話していた変数名の付け方が実践されていないんです。

 ⇒変数名の付け方の記事はこちら

 

というのも、この繰り返し処理に使う変数は、iかjかkを使うのが暗黙のルールとして教えられるんですよね。

なので、そういうものだと思っておくのが手っ取り早いです。

最初に使うならi、その次ならj、その次にk…といった順番で使っていくのが多いですね。

別に他の変数名でもいいんですが、これが一番無難です。

 

whileとforの使い分け方

ここまで読んで、whileとforの違いは分かりましたね?

while文で()内に記述するのは繰り返し条件のみだけど、for文は変数の宣言と繰り返し条件、計算式の3つが必要になるというのが、whileとforの違いです。

 

じゃあどうやってこの2つを使い分けていくのがいいんでしょうか?

 

まぁ正直言うと、どっちの処理を使ってもいいんですけどね。繰り返すのは同じだし。

もうこの辺りは個人の好みによって変わってくる所です。

つまり、whileとforの好きな方を使えばいーんです

 

個人的には変数の宣言がいらなかったらwhileを使ったりしていますが、使いたい方を使っていきましょ。

使っていくうちに、「こっちの処理は使いにくいな」と感じたらもう片方の繰り返し処理を使っていけばいいだけの話です。
そんな気にするまでの話ではないってことっすね!

 

プログラマーの9割が経験している繰り返しのミスって?

実は今回説明している繰り返し処理、不具合が発生しやすい箇所TOP10ぐらいに入る箇所があります。

それは処理を繰り返す回数の間違いです。

あなたは下の4つのパターンで、それぞれ処理が何回繰り返されるか分かりますか?

 

例1

for(int i = 0; i <= 6; i++){
 処理
}

例2

for(int i = 1; i <= 6; i++){
 処理
}

例3

for(int i = 0; i < 6; i++){
 処理
}

例4

for(int i = 1; i < 6; i++){
 処理
}

 

分かりましたか?

答えはこの通りです。

 

例1:7回

例2:6回

例3:6回

例4:5回

 

思っていた回数と合っていましたかね?

これよく混乱しやすくなるんですよね~。

 

ここで注意するべきなのが、この2つのポイントです。

 

・変数が0から始まっているのか1から始まっているのか。

・<を使っているのか<=を使っているのか。

 

このポイントさえ注意しておけば、繰り返し回数を間違う可能性はグッと減ります。

ただ本当に間違いやすい箇所なので、毎回注意深く確認するようにしてくださいね。

 

それじゃあこの繰り返し処理を実際に使ってLEDを点滅させてみます。

 

繰り返し処理を1つ使った例

もしかしたら、「まずC言語で一定時間待つ処理はどう作ればいーんじゃ?!」とあなたは思っているかもしれません。

実はC言語で一定時間待つ処理を作るには、それだけで1記事分の説明が必要になってしまいます。
ただ今回は繰り返し処理の説明がメインなので、僕があらかじめ待ち処理を作っておきました!

開発環境準備の記事でダウンロードしてもらったmain.cで下記内容を追加してもらえば、1ms間待つ処理を使うことができます。

#include “./library/time.h
wait_1ms();

この処理を使って、緑色LEDを点灯してから消灯するプログラムを作るとこんな動きをします。

プログラムはこんな内容になります。
0.5秒ぐらいの待ち時間を作る為に繰り返し処理を使っています。

main.c
#include "r_cg_userdefine.h"
#include "./library/time.h"	//wait_1ms()を使えるようにインクルード

void main_study(void)
{
	int i;	//繰り返し処理のカウント用変数
	
	P_GREEN_LED = 1;	// 緑色LEDを点灯
	
	//一定時間待つ
	for(i = 0; i < 500; i++){
		wait_1ms();		//1ms待つ
	}
	
	P_GREEN_LED = 0;	// 緑色LEDを消灯
	
	//一定時間待つ
	for(i = 0; i < 500; i++){
		wait_1ms();		//1ms待つ
	}
}

ただ、このままだと待ち時間を変えたくなった時に2ヶ所修正しなきゃいけなくなるので面倒ですよね。
なので、定数を追加して、待ち時間を一気に変えれるようにしておきましょう。

プログラムの動きを簡単に変更できるようにしておくのはめちゃんこ大事ですからね!

定数を使うとこんなプログラムになります。
LED_ON_CYCLE_TIMEを追加して、待ち時間を簡単に変更できるように変えています。

main.c
#include "r_cg_userdefine.h"
#include "./library/time.h"	//wait_1ms()を使えるようにインクルード

#define LED_ON_CYCLE_TIME 500	//LEDの点滅間隔

void main_study(void)
{
	int i;	//繰り返し処理のカウント用変数
	
	P_GREEN_LED = 1;	// 緑色LEDを点灯
	
	//一定時間待つ
	for(i = 0; i < LED_ON_CYCLE_TIME; i++){
		wait_1ms();		//1ms待つ
	}
	
	P_GREEN_LED = 0;	// 緑色LEDを消灯
	
	//一定時間待つ
	for(i = 0; i < LED_ON_CYCLE_TIME; i++){
		wait_1ms();		//1ms待つ
	}
}

 

繰り返し処理を2つ使った例

それじゃあ今度は一歩進んで、繰り返し処理にさらに繰り返し処理をくっつけちゃいましょう。

そうすることで、LEDを希望する回数点滅させられるようになるんです。

実行結果とプログラムを見るとこうなりますね。
ここではLEDを3回点滅させています。

 

main.c
#include "r_cg_userdefine.h"
#include "./library/time.h"	//wait_1ms()を使えるようにインクルード

#define LED_ON_CYCLE_TIME 500	//LEDの点滅間隔

void main_study(void)
{
	int i, j;	//繰り返し処理のカウント用変数

	// 緑色LEDを3回点滅
	for(j = 0; j < 3; j++){

		P_GREEN_LED = 1;	// 緑色LEDを点灯
		
		//一定時間待つ
		for(i = 0; i < LED_ON_CYCLE_TIME; i++){
			wait_1ms();		//1ms待つ
		}
		
		P_GREEN_LED = 0;	// 緑色LEDを消灯
		
		//一定時間待つ
		for(i = 0; i < LED_ON_CYCLE_TIME; i++){
			wait_1ms();		//1ms待つ
		}
	}
}

 

これは、緑色LEDを点灯⇒消灯という処理を3回繰り返しているんです。
こうすることでLEDの点滅処理が作れるんですね。

 

こういう同じ作業を何回でもやれちゃうのがプログラミングの強みです。

数ある強みの中でも1番のものですね。
人間なら同じ作業を繰り返すと疲れてきたりしますが、プログラムは疲れないですもん。

こういうことができるから、どんどん色んなものが機械化されていってるんですね。
そして僕たちがその機械を作る立場になるってことですよ。

 

繰り返し処理を無限に行う方法(無限ループ)

繰り返す回数を指定せずに、ずっと繰り返して処理をするという書き方も、実はあります。
それが無限ループというものです。

この無限ループを使うと、例えばLEDを永遠に点滅させることも可能です。
実際にLED点滅を無限ループさせたものを見てみましょう。

この無限無限ループも、whileとforを使った2種類の書き方があります。
どちらかというとwhileを使った無限ループの方が使われていることが多いですね。

書き方は凄く単純です。

while(1){
 処理
}
for(;;){
 処理
}

↓は無限ループを使ったLED点滅のプログラムです。

main.c
#include "r_cg_userdefine.h"
#include "./library/time.h"	//wait_1ms()を使えるようにインクルード

#define LED_ON_CYCLE_TIME 500	//LEDの点滅間隔

void main_study(void)
{
	int i;	//繰り返し処理のカウント用変数

	// 緑色LEDをずっと点滅
	while(1){

		P_GREEN_LED = 1;	// 緑色LEDを点灯
		
		//一定時間待つ
		for(i = 0; i < LED_ON_CYCLE_TIME; i++){
			wait_1ms();		//1ms待つ
		}
		
		P_GREEN_LED = 0;	// 緑色LEDを消灯
		
		//一定時間待つ
		for(i = 0; i < LED_ON_CYCLE_TIME; i++){
			wait_1ms();		//1ms待つ
		}
	}
}

 

繰り返し処理を強制的に中断する方法

さて、こんな便利な繰り返し処理ですが、場合によっては繰り返しを中断したい!ということも起きてきます。

そんな時に繰り返し処理を中断させる書き方、あります。

それがこのbreakというものです。

 

このbreakは、繰り返している処理「1つだけ」を中断して抜けることができます。

この繰り返している処理「1つだけ」というのが少しややこしいんですよね。

 

分かりやすくする為に例を出しましょう。

下のようにfor文を2つ重ねているプログラムがあったとします。

breakは2番目に出てきたforの中に書きますね。

 

for(int j = 1; j <= 3; j++){
  for(int i = 1; i <= LED_ON_CYCLE_TIME; i++){
    処理
    break;
  }
  
}

 

そうすると、一見、両方のfor文を中断するように思うかもしれませんが、違います。

さっきも書いたように、breakでは1つの繰り返し処理しか中断できません。

なので、今回は2番目のfor文を中断することになります。
1番目のfor文は繰り返したままです。

 

for(int j = 1; j <= 3; j++){
  for(int i = 1; i <= LED_ON_CYCLE_TIME; i++){
    処理
    break;
  }
  ここに抜けてくる
}

 

逆に1番目に出てきたforの中にbreakを書くと、こう抜けてきます。

 

for(int j = 1; j <= 3; j++){
  break;
  for(int i = 1; i <= LED_ON_CYCLE_TIME; i++){
    処理
  }
}
ここに抜けてくる

 

この場合だと、処理は何も実行されません。

ふとした時に混乱しやすい内容なので、ここでしっかり理解しておきましょう。

問題:以下のようにLEDを点滅させるプログラムで書け

 

 

これで繰り返し処理の内容は完了です。

お疲れ様でした!

 

この繰り返し処理はプログラミングをする上で何度も何度も使っていく内容なので、絶対にマスターしてくださいね!

混乱してきたら、振り返ってもう一度この記事を確認してもらえばと思います。

質問も大歓迎なので、「ココが分からなかった」、「この部分は分かりやすくて助かった!」等コメント貰えると嬉しいです!

 

次のC言語入門編では、プログラムのデバッグ方法について説明していきます。

このデバッグ方法を知っておけば、プログラムの修正スピードはグンッと上がりますよ。
それじゃあ、また次回の記事で会いましょう!

 

気軽にコメントどうぞ!100%返信します。

内容を確認してから、下記の「コメントを送信する」ボタンを押してください。