制御文法を使う(反復)条件により処理を繰り返す(Arduino)
分岐にも書きましが、記述されたプログラムは、
何も制御しない場合は、
上から下へ左から右へと順に実行されます。
今回は、反復(繰り返し)処理です。
繰り返しといえば、
loop( )関数も繰り返し処理の関数でした。
loop( )関数{ }ブロック内に記述された内容は、
電源を切るまで、永久的に繰り返されます。
マイコンを使い、何かを制御する事を考えてみると、
void loop( ) {
センサーからの情報取得
この情報を使って機器を制御
}
これで、あとは、loop( )関数が勝手に繰り返し
処理を続けてくれることになります。
ここで、センサーの情報精度を上げるため、
センサーからの情報取得を5回繰り返して、
その平均で機器の制御を行うことを一組とすると、
センサーからの情報取得に必要となる
プログラム記述を5回書かなければならなりません。
しかも同じ内容を書くことになるますね。
こんな時、
このセンサーからの情報取得を5回繰り返す
などと記述できたら便利です。
これが、反復(繰り返し)文の必要な理由の一つです。
全体の大きな反復(繰り返し)処理は、loop( )関数に
任せるとして、その中の反復が必要となる処理は、
自分で書くことになります。
反復(繰り返し)処理のイメージは、
こんな、感じでしょうか。
反復(繰り返し)処理は、
while( )、for( )、do while( )文を使います。
各書式は、
while( )文
while( 継続条件式 ) { }
for( )文
for( 初期化式; 継続条件式; 繰り返し毎の式) { }
do while( )文
do { } while( 継続条件式 )
となります。
各文の継続条件式ですが、
継続条件式は、if ( )文と同じく、比較演算子を使用して記述します。
( )内の条件式が成り立っている(真、true)間、
{ } ブロック内の処理が繰り返し行われます。
while( i < 5 ) { }
と書けば、iが5より小さい間、繰り返しが行われます。
このiが更新されず、5以上にならなければ、
この{ }のブロックから抜け出ることが出来ず、
永久(無限)ループとなってしまいます。
for( )文の( )内の式は、3つで、各式は、セミコロン(;)で区切って
記述します。
初期化式は、この繰り返しに入る前に行いたいことを記述します。
継続条件式は、他の繰り返し文と同じく、継続条件を記述します。
繰り返し毎の式は、{ }ブロック内を1回繰り返し、戻ってきたときに
行いたい事を記述します。
int i;
for ( i = 0; i < 5; i = i + 1 ){繰り返したい処理}
のような記述の場合、
このfor( )文の繰り返しに入る前に、変数iが0で初期化されます。
続いて、1回繰り返すごとに、i = i + 1が実行され、
繰り返すごとに、変数iは1ずつ加算されます。
1回繰り返すごとに、継続条件が判定されるため、
i → 0、1、2、3、4、5
となり、継続条件が崩れ(偽、falseとなり)、繰り返しが
終了することになります。
do while( ) 文は、while( ) 文と同様ですが、
継続条件式の判定位置が違います。
そのため、
while( )文では、
int i = 5;
while( i < 1 ) { 繰り返したい処理 }
繰り返しより前に継続条件式の判定を行うため、
この繰り返したい処理は実行されません。
・・・前判定型繰り返しとよびます。
do while( )文では、
int i = 1;
do { 繰り返したい処理 } while( i < 1 )
判定が、繰り返し後に行われるため、
繰り返したい処理内容が、必ず一度は実行されてしまいます。
・・・後判定型繰り返しとよびます。
最低1度は繰り返す処理であれば、
どちらの記述を使っても同じ結果になります。
また、3文のどれを使うかも、
自分が分かりやすいものを使うべきです。
for( )文については、数をカウントしながら繰り返すような
使い方には分かりやすく向いていると思います。
さて、整数1から10までの加算結果を求めるには、
(1+2+3+4+5+6+7+8+9+10 を行うには)
for ( )文で記述してみます。
void setup() {
// put your setup code here, to run once:
Serial.begin(9600); // シリアルポートを初期化(9600 bpsで通信)
// 変数宣言
int i;
int total = 0;
// 1から10の加算
for ( i = 1; i <= 10; i++ ) {
total += i;
}
Serial.println( total );
}
void loop() {
// put your main code here, to run repeatedly:
}
while ( )文で記述してみます。
void setup() {
// put your setup code here, to run once:
Serial.begin(9600); // シリアルポートを初期化(9600 bpsで通信)
// 変数宣言
int i = 1;
int total = 0;
// 1から10の加算
while ( i<= 10 ) {
total = total + i;
i = i + 1;
}
Serial.println( total );
}
void loop() {
// put your main code here, to run repeatedly:
}
do while ( )文で記述してみます。
void setup() {
// put your setup code here, to run once:
Serial.begin(9600); // シリアルポートを初期化(9600 bpsで通信)
// 変数宣言
int i = 1;
int total = 0;
// 1から10の加算
do {
total = total + i;
i = i + 1;
} while ( i<= 10 );
Serial.println( total );
}
void loop() {
// put your main code here, to run repeatedly:
}
継続条件式とは別に、他の条件で繰り返しを中断したい
場合もあります。
この場合は、break文を使います。
このbreak文を発行すると、
その時点で、繰り返しから抜け出し、
繰り返し{ }ブロックの、次の処理へ移行します。
ここで、中断と書いていますが、
これは、継続条件式ではまだ繰り返す予定なのに、
途中で中止するという意味で中断と書いていますが、
再開するなどということは出来ません。
整数1から10までの加算結果を求めるプログラムを、
while( )文で記述し、その継続条件を、trueとして無限ループにします。
while( true ) { }
このままでは、継続条件は崩れません(falseにならない)から、
ループが終了することはありません。
そこで、 break文を発行して、ループから抜け出す方法で、
if ( i > 10 ){
break;
}
のような記述になりますね。
記述してみます。
void setup() {
// put your setup code here, to run once:
Serial.begin(9600); // シリアルポートを初期化(9600 bpsで通信)
// 変数宣言
int i = 1;
int total = 0;
// 1から10の加算
while ( true ) { // 繰り返しの継続条件を無限に
total += i;
i++;
if( i > 10 ){
break; // 10まで加算したので繰り返し中断
}
}
Serial.println( total );
}
void loop() {
// put your main code here, to run repeatedly:
}
ネスト(入れ子)処理とよばれる記述もあります。
これは、文法ブロック内に同文法ブロックを記述することで、
繰り返し処理の中に繰り返し処理を書くことをいい、
二重ループ(多重ループ)などと呼ばれる処理です。
while( ){
while( ){
}
}
こんな記述のことになりますね。
のような感じでしょうか。
※ここでは、ループ記号(台形記号)を使わずに記載しています。
・・・・私はこの記述の方が分かりやすいので。
また、
loop( )関数の中に、
while( )、for( )、do while( )文を使って記述すれば、
これもある意味入れ子処理ってことになりますね?
ネスト処理を利用して、
*を数値分だけ表示するスケッチを記述してみます。
void setup() {
// put your setup code here, to run once:
Serial.begin(9600); // シリアルポートを初期化(9600 bpsで通信)
// 変数宣言
int i, j;
int total = 0;
// 5×5マスに*の数を変えながら表示する
for ( i = 0; i < 5; i++ ) { // *を増やしながら表示(5×5)
for ( j = 0; j <= i; j++ ) {
Serial.print( "*" );
}
Serial.println( );
}
for ( i = 0; i < 5; i++ ) { // *を減らしながら表示(5×5)
for ( j = 0; j < 5 - i; j++ ) {
Serial.print( "*" );
}
Serial.println( );
}
}
void loop() {
// put your main code here, to run repeatedly:
}
ネスト処理を利用して、
九九の表を表示するスケッチを記述してみます。
void setup() {
// put your setup code here, to run once:
Serial.begin(9600); // シリアルポートを初期化(9600 bpsで通信)
// 変数宣言
int i, j;
// 九九の表示
for ( i = 1; i <= 9; i++ ) {
for ( j = 1; j <= 9; j++ ) {
Serial.print( j );
Serial.print( "×" );
Serial.print( i );
Serial.print( "=" );
Serial.print( i * j );
Serial.print( "\t" );
}
Serial.println( );
}
}
void loop() {
// put your main code here, to run repeatedly:
}