南 晴輝のブログ -5ページ目

南 晴輝のブログ

マイクロプロセッサを応用した、自立動作型ロボットの開発を

目指します。

とくに ロボカップジャパンジュニア の

サッカー

レスキュー

に使用できるロボットを、目標とします。

皆さんこんにちは、南 晴輝( みなみ せいき )です。


ロボカップジュニア2013 に関係する動画を紹介します。



今回は、レスキューです。

レベルが高く、確実に完走しています。

http://www.youtube.com/watch?v=LGc8SncETYE


http://www.youtube.com/watch?v=OU2UOpdBhKE



ブログを読んでくださり、ありがとうございます。


PS:最近、facebook にはまっています。

皆さんこんにちは、 南 晴輝 ( みなみ せいき )です。


今回は、C言語で特に重要な、制御構造 を解説します。



制御文とは、プログラムの流れを制御するものです。

C言語も他のプログラム言語と同じように、上から下に順次プログラムは実行されます。

これを「順次構造」とよびます。


しかし、プログラムによっては、処理を繰り返したり、条件によって違う処理をさせたい時などは、

順次構造以外の制御の流れが必要になります。


以下のような制御構造があります。

順次構造

分岐構造

単一分岐構造
多重分岐構造
ケース構造

反復構造

前判定型反復構造
後判定型反復構造


順次構造

上から下にかけて順に実行されます。

分岐構造

分岐の条件が1つだけの時に単一分岐といいます。


次に例を示します。下の例では、キーボードから数字を入力し、それが1960年以上 1970年未満なら

「1960年代」と表示します。
*/

/*
#include <stdio.h>

void main(){

int yea_r;

printf("西暦で年を入力してください。");

scanf("%d", &yea_r);

if ( 1960 <= yea_r && yea_r < 1970 )

printf("1960年代です。\n");
}
*/

/*
上の例のように、「1960年以上」という条件と「1970年未満」という条件を

「&&」(アンド記号)で区切ることで、その両方を満たす場合に限り、次の文が実行されます。

そして、複数の条件のうちどれか一つでも満たされていれば実行させたい場合は、

「&&」の代わりに、「||」(オア記号)で区切ります。

もし、条件が満たされない場合の処理が必要なければ、「else」文を省略できます。



多重分岐

単一分岐を組み合わせたもので、単一分岐の処理の中にまた条件分岐を含むものです。



if(条件1){

if(条件2){
処理3;
}
else{
処理2;
}
else{
処理3;
}

以下に例を示します。以下の例では、キーボードから数字を入力し、その数字が負数なら「負数」、

0なら「0」、整数なら「整数」と表示します。2例を示すが、どちらも同じ結果になります。
*/

/*
#include <stdio.h>

void main(){
int yea_r;

scanf("%d",&yea_r);

if ( yea_r < 0 ){
printf("負の数です。\n");
}
else{
if ( yea_r == 0 ){
printf("零です。\n");
}
else{
printf("正の数です。\n");
}
}
}

*/


/*


上のように、多重分岐では、「else」は直前の「if」に対応します。
*/


/*
3つ以上の異なった処理の中から、条件にあう処理を行うことを多方向分岐と言い、

次のような書き方をします。


「switch」文の括弧の中は、「int」型、「char」型、「enum」型のみが許されます。


西暦を入力し、その年の干支を表示させます。ただし西暦0年は申年とします。

*/


/*
#include <stdio.h>

void main(){
int yea_r;

printf("西暦を入力してください : ");
scanf("%4d", &yea_r); // 西暦入力

if ( yea_r < 0 )
yea_r = -yea_r; // 正に直す 


switch( yea_r % 12 ){ // 12で割ったあまり
case 0 :
printf("%d年は申年です。\n", yea_r);
break;
case 1 :
printf("%d年は酉年です\n", yea_r);
break;
case 2 :
printf("%d年は戌年です\n", yea_r);
break;
case 3 :
printf("%d年は亥年です\n", yea_r);
break;
case 4 :
printf("%d年は子年です\n", yea_r);
break;
case 5 :
printf("%d年は丑年です\n", yea_r);
break;
case 6 :
printf("%d年は寅年です\n", yea_r);
break;
case 7 :
printf("%d年は卯年です\n", yea_r);
break;
case 8 :
printf("%d年は辰年です\n", yea_r);
break;
case 9 :
printf("%d年は巳年です\n", yea_r);
break;
case 10 :
printf("%d年は午年です\n", yea_r);
break;
case 11 :
printf("%d年は未年です\n", yea_r);
break;
}
}

*/

/* 反復構造(while)

ここで紹介するwhile文は、前判定型であり、繰り返し処理に入る前に繰り返し条件をチェックします。

したがって、条件によっては繰り返し処理を1度も実行しない場合もありえます。

1から100までの合計を求めてみます。

*/
/*


#include <stdio.h>

void main(){
int n, t;

n = 1;
t = 0;

while(n <= 100){
t = t + n;
n = n + 1;
}
printf("1から100までの合計は%dです。\n",t);
}
*/

/*

while文ではwhileの後の括弧の中に条件式を記述し、その条件式が真になる間、処理が繰り返されます。

もちろん、複数の条件式を「&&」「||」でつなげることもできます。

*/

/*

ここで紹介するdo~while文は、後判定型であり、繰り返し処理を行った

後に繰り返し条件をチェックします。

したがって、どんな条件でも最低1回は繰り返し処理が実行されます。

前ページ同様、1から100までの合計を求めてみます。

*/
/*
#include <stdio.h>

void main(){
int n, t;

n = 0;
t = 0;

do{

t = t + n;
n = n + 1;

}while(n <= 100);

printf("1から100までの合計は%dです。\n",t);
}

*/

/*
do~while文ではwhileの後の括弧の中に条件式を記述し、その条件式が真になる間処理が繰り返されます。

もちろん、複数の条件式を「&&」「||」でつなげることもできます。

*/

/*


反復構造(for)

ここで紹介するfor文は、前判定型であり、繰り返し処理に入る前に繰り返し条件をチェックします。

したがって、条件によっては繰り返し処理を1度も実行しない場合もあり得ます。

for文は、while文に初期設定と、変化式を組み合わせたものです。

これまでの例と同様に1から100までの合計を求めてみる。while文を使用すると下記のようになります。



void main(){
int n, t;

n = 1; // 初期設定
t = 0; // 初期設定

while(n <= 100){
t = t + n;
n = n + 1; // 変化式
}
printf("1から100までの合計は%dです。\n",t);
}



*/

/*
void main(){
int n, t;

for ( n = 1, t = 0 ; n <= 100 ; n = n + 1 ){
t = t + n;
}
printf("1から100までの合計は%dです\n",t);
}

すなわち、

for ( 初期設定 ; 条件式 ; 変化式 )

繰り返し処理となる。


初期設定、変化式はカンマ「,」で区切って複数の式にすることもできますが、あまり使いません。

また、初期設定、変化式が必要ない場合は、必ずしも記述する必要はなく、省略することもできます。

しかしこの場合もセミコロン「;」は省略できません。その例を下記に示します。



void main(){
int n, t;

n = 1; // 初期設定
t = 0; // 初期設定

for( ; n <= 100 ; n = n + 1){
t = t + n;
}
printf("1から100までの合計は%dです。\n",t);
}

繰り返す処理が1文の時は、中括弧を省略し、下記のように書くこともできます。

void main(){
int n, t;

n = 1;
t = 0;

for( ; n <= 100 ; n = n + 1)
t = t + n;

printf("1から100までの合計は%dです。\n",t);
}

このように処理が1文の時に中括弧を省略できるのは「if」「else」文、「while」文も同様です。
*/

/*

補助制御文


反復構造では同じ処理を繰り返しましたが、場合によっては条件式が真でも反復構造から

抜け出したい場合が生じたりする場合もあります。、

実際のプログラムでは、このように反復処理中にその処理から抜け出した方が、

プログラムがすっきり書ける場合も少なくありません。

そのような時には補助制御文を使用します。補助制御文には以下のような物が用意されています。

break

「switch~case文」のところでも紹介しましたが、「while」「for」などの反復処理中に使用すると

強制的に反復処理を抜けます。

反復処理が入れ子になっている場合(多重反復処理)は、内側の反復構造を1つだけ抜けるだけです。


continue

反復構造中に使用すると、反復処理が終了したことになります。すなわち条件評価を行い、

条件が真ならばもう一度反復処理を実行します。なお、「for」文であれば、

変化式も実行した後に条件式を評価します。


goto

ラベルへの無条件分岐です。C言語では、まず使いません。

組み込み系では、ハードウェアのトラブルなどの緊急に処理が必要な時のみ使います。


return

その関数から抜けます。

以下に例を示します。この例では、数字を2つ入力しa,bに代入します。

そしてaからbまでの偶数の和を求めますが、bが100以上の場合はaから100までの偶数の合計を求めます。

なおaの方が大きい場合のチェックはしていません。

*/

/*
#include <stdio.h>

void main(){
int a, b, t;

scanf("%d %d", &a, &b);

for ( t = 0 ; a <= b ; a++ ){
if ( a > 100 ) // 100以上になったら終了
break;

if ( a % 2 ) // 偶数じゃなかったら、変化式を実行
continue;
t = t + a;
}
printf("%d\n", t);
}

*/

/*
上の例の「continue」文の前の「if」文の条件ですが、本題からはずれますが、ここで解説します。

条件式は「真」か「偽」で判断します。C言語では「0」と「偽」は等価です。

また「0以外」と「真」は等価です。

したがって、「a % 2」すなわち「a÷2」の余りが真(0以外)ならば「continue」を実行します。

したがって「if ( a % 2 )」は「aが奇数なら」という意味になります。


「a % 2」すなわち「a÷2」の余りが真(0以外)ならば「continue」を実行します。

「aが偶数なら」「a % 2」の値は、ゼロ(0)になります。


*/


今回は、少し難しかったと思いますが、とくに良く使う制御構造ですので、


繰り返し読んで、理解してください。


ありがとうございました。


南 晴輝



追伸 : 私は、劇団四季のファンです。 大阪ライオンキングを、7月15日に観劇しました。


     観客全員が スタンデングオベーション でした。


     皆さんも、是非観劇してください。









入力と出力

出力 printf() 関数

画面に文字を表示させるには標準ライブラリ関数、printf()を使います。

C言語では非常に簡単です。

#include <stdio.h>

void main(){
printf("Hello C world.\n");
}

標準出力は、次のようになります。

Hello C world.

上の例のように、ダブルクォーテショーンで囲んだ文字列を表示します。

最後の「\n」はエスケープシーケンスと言います。「\n」は改行を示します。

詳しくは、後で説明します。


変数の値を表示したいこともあるので、その時は「%」記号を使います。

#include <stdio.h>

void main(){
int i = 10;
char cha = 'A';
printf("変数iの値は%dです。\n",i);
printf("chaの文字は%cです。\n",cha);
}

標準出力は、次のようになります。

変数iの値は10です。
chaの文字はAです。

表現指示文字

上で述べた「%d」の「d」のような文字を「表現指示文字」と言います。

表現指示文字は次のような物があります。

表現指示文字 機能

d 整数を10進数で表示
x 整数を16進数で表示
o 整数を8進数で表示
u 符号なし整数を10進数で表示
s 文字列を表示
c 変数を1文字として表示
e 小数を指数形式で表示
f 小数を実数形式で表示
g 小数を指数形式、実数形式の短い方で表示


表現指示文字、桁あわせ

桁をあわせたい時には、次の表現指示文字を追加します。

符号 + データを右詰めで表示(符号付き)

- データを左詰めで表示(負数のみ符号付き)

省略 データを右詰めで表示(負数のみ符号付き)

0 0 数値が入らない桁を「0」で埋める

省略 数値が入らない桁をスペースで埋める

桁数 n 符号を含めて「n」桁で表示する」

省略 必要な桁分表示する

小数部 n 小数「n」桁まで表示する

文字列の場合は表示する文字数

省略 必要な桁分表示する

// 例を示します。

#include <stdio.h>

void main(){

int m = 10;

double pai = 3.1415926;

printf("変数mの値は%+010dです。\n\n",m);

printf("円周率は%+010.5fです。\n",pai);

}

// 標準出力は、次のようになります。

// 変数nの値は+000000010です。

// 円周率は+003.14159です。


エスケープシーケンス(制御文字)

エスケープシーケンスは、改行やタブなど特殊な操作をしたい場合に用いられます。

以下のようなエスケープシーケンスがあります。

エスケープシーケンス 機能

\n 改行

\t 水平タブ ( Tab )

\\ 円記号「\」(バックスラッシュ)

\' シングルクォーテーション「'」

\" ダブルクォーテーション「"」

\0nn nnは0~7までの2桁の8進数
8進数でnnが表す文字

\xnn nnは0~Fまでの2桁の16進数
16進数でnnが表す文字

\b 1文字戻る

\r その行の先頭に戻る

\f 画面をクリアする

\a ベルを鳴らす

\v 垂直タブ


*/

今回は、基本的な 演算子 について、解説します。





代入演算子

「=」を使います。

変数に定数を代入したり、変数に変数を代入する時に使用します。

算術演算子

算術演算子とは、「+」「-」「*」「/」「%」です。それぞれ、加算、減算、乗算、除算、

余りを求めます。

計算の順序は、数学の場合と同じです。

整数同士の割り算の場合は、結果も整数になります。

この時には、小数点以下は切り捨てになります。

負数を含む「余り(%)」を計算する場合は、コンパイラによって異なります。

*/

/*

#include <stdio.h>

void main() {

int a, b, c;

printf( "\n\n");
printf("a の値を入力してください。");

scanf("%d", &a);

printf("b の値を入力してください。");

scanf("%d", &b);


printf( "\n\n");
printf( " a =%d b =%d \n\n", a, b );

c = a + b; printf( "c = a + b c = %d\n", c);
c = a - b; printf( "c = a - b c = %d\n", c);
c = a * b; printf( "c = a * b c = %d\n", c);
c = a / b; printf( "c = a / b c = %d\n", c);
c = a % b; printf( "c = a % b c = %d\n", c);

printf( "\n\n");
}

*/


/*

比較演算子

値が等しいか「==」、値が等しくないか「!=」、値が大きいか「>」「>=」

値が小さいか「<=」「<」を調べます


比較演算子 例 意 味

< a < b aはbより小さい
<= a <= b aはb以下
> a > b aはbより大きい
>= a >= b aはb以上
== a == b aはbと同じ
!= a != b aとbは異なる

比較が成り立つ場合は「真」(1)が、成り立たない場合は「偽」(0)となります。

比較の「==」と代入の「=」を間違えないでください。

以前に私もこれを、間違えて長い間プログラムが正常に働きませんでした。

よく注意してください。

*/


/*

#include <stdio.h>

void main() {

int a, b, c;

printf( "\n\n");
printf("a の値を入力してください。");

scanf("%d", &a);

printf("b の値を入力してください。");

scanf("%d", &b);


printf( "\n\n");
printf( " a =%d b =%d \n\n", a, b );

c = a > b; printf( "c = a > b c = %x\n", c);
c = a >= b; printf( "c = a >= b c = %x\n", c);
c = a < b; printf( "c = a < b c = %x\n", c);
c = a <= b; printf( "c = a <= b c = %x\n", c);
c = a == b; printf( "c = a == b c = %x\n", c);
c = a != b; printf( "c = a != b c = %x\n", c);

printf( "\n\n");
}

*/


/*

論理演算子

例 意 味

&&    a && b AND(かつ)
||    a || b OR(または)
!    !b NOT(否定)

*/

/*

#include <stdio.h>

void main() {

int a, b, c;

printf( "\n\n");
printf("a の値を入力してください。");

scanf("%d", &a);

printf("b の値を入力してください。");

scanf("%d", &b);


printf( "\n\n");

printf( " a =%d b =%d \n\n", a, b );

c = a && b; printf( "c = a && b c = %x\n", c);

c = a || b; printf( "c = a || b c = %x\n", c);

c = !b; printf( "c = !b c = %x\n", c);

c = ( b==30 ) && ( a<b ); printf( "c = (b==30) && (a<b) c = %x\n", c );


// これら論理演算子、比較演算子は、分かりにくい組み合わせになることがあるので、

// 括弧をつけて見やすくします。

// 括弧を外すと c = b==30 && a<b となって、なんだかよくわかりませんね。


printf( "\n\n");

}

*/


/*
2012.07.03 ( 平成24年7月3日 )Seiki Minami

定数は、どのように表すのだろうか。


整数定数

整数定数には

10進数 100 255 -50

16進数 0x43 0xFF

8進数 0105 0373

文字 'C'


8進数を表すには、最初に「0」を、16進数を表すには「0x」をつけます。文字はASCII文字1バイトです。

整数定数と言うよりは、1文字の定数として扱うことがほとんどですが、整数として扱うこともできます。

C言語では、文字という概念はなく、その文字に対応するASCIIコードという数字で扱います。

小数定数

小数は、「1.234」、「-0.123」のように書きます。

このような書き方では200万や1000万分の一などを書きたい場合は、よくありません。

そこで「1.0e8」や「1.453E-6」のように、10の何乗かで書きます。

「e」と「E」はどちらでも構いません。

円周率は、「3.1415」ですが、「0.31415E1」、「3.1415E0」などとなります。


代入

宣言した変数に対して、定数を代入することができます。

int a, b; // 変数名「a, b」をint型で宣言

char ch_1, ch_2; // 変数名「ch_1」と「ch_2」をchar型で宣言

unsigned long lon_g; // 変数名「lon_g」をunsigned long型で宣言

float flo; // 変数名「flo」をfloat型で宣言

ch_1 = 'C';

ch_2 = 0x43; // 16進数で43を代入

lon_g = 'C'; // long型 lon_gに'C'のASCIIコード43Hを代入

flo = 3.1415;

a = b = 10000; // aとbに10000を代入

初期化

変数を宣言しても、その変数の内容(値)は不定です。

変数の宣言と同時にある値で初期化することもできます。


int a = 10000;

char ch = 'C';

int b = a = 10000; // aもbも10000になる

いままで説明したことを、C言語のプログラムを実行し、確かめてみましょう。

*/

/*
#include <stdio.h>

void main() {

int a, b; // 変数名「a, b」をint型で宣言

char ch_1, ch_2; // 変数名「ch_1」と「ch_2」をchar型で宣言

unsigned long lon_g; // 変数名「lon_g」をunsigned long型で宣言

float flo; // 変数名「flo」をfloat型で宣言

ch_1 = 'C';

ch_2 = 0x43; // 16進数で43を代入、10進数で67です。

lon_g = 'C'; // long型 lon_gに'C'のASCIIコード43Hを代入

flo = 3.1415; // float型 flo に 3.1415を代入

a = b = 10000; // aとbに10000を代入

printf( "\n\n");

printf("ch_1 = %d ch_2 = %d lon_g = %d flo = %f a = %d b = %d \n\n", ch_1, ch_2, lon_g,

flo, a, b);

printf("ch_1 = 0x%x ch_2 = %c lon_g = 0x%x flo = %f a = %d b = %d \n\n", ch_1, ch_2, lon_g,

flo, a, b);

// なにをやっているか、わかりますか。

printf( "\n\n");

}
*/

/*

構成

C言語の文法的な構成について、次に説明します。


語句の種類

C言語を構成する語句は「識別子」、「予約語」、「定数」、「文字列」、「演算子」、「区切子」、

「コメント」、「ブランク」があります。

識別子は、関数名、変数名のことです。変数には、単純変数、配列、ポインタの3種類があり、

さらにint型、char型などの型が存在します。

予約語は、プログラムの実行順序の制御や、変数の型など、決まっている語です。

定数はその名の通り、決まった値をもちます。文字列も定数(文字)の集まりで、

定数の1種と考えられます。

演算子は足し算、引き算などの「+」や「-」のことです。

区切子とは、文と文を区切ったりするものです。

コメントとは、プログラムとは関係ないが、プログラマーが自分あるいは、一緒に作っている仲間の

プログラマーに対してのメッセージです。

*/

// コメントの書き方は2種類あります。1つは 「//」の以降改行まで、2つ目は「/*」と「*/」の間です。

/* 後者は入れ子ができません。

ブランクとは、プログラムを見やすくするための改行や、タブ、スペースを言います。




上で説明した語句を組み合わせて式を構成します。

式には一次式と演算式(演算子を用いて一次式を組み合わせたもの)に分けることができます。

関数も式になります。何かを処理するための引数(パラメータ)を必要とし、その結果を返します。

その結果を戻り値と言います。




式1つもしくは複数の式から文を構成します。文の後には必ず1文の終わりを示す記号「;」がつきます。

1行の中に文が2つ以上あっても構いません。エディターで見た場合に1行の中に複数の文があっても、

コンパイラは各々を文として認識するからです。

*/


/*
文には「式の文」(上で言う「int c_language = 10;」など)、空文(「;」のみからなる文)、

制御文(「break;」、「return;」など)があります。


ブロック

文が0文、1文、あるいは複数の文からブロックが構成されます。

文をブロックを表す「{」と「}」で囲みます。ブロックは「1文と見なす単位」のことです。

条件分岐(「if」、「else」)や反復(「for」や「while」など)などは、基本的に1文しか実行できません。

しかし1文だけしか繰り返せないのでは不便です。そこでこのブロックで1文と見なすことで、

複数の文を反復することができるのです。

また、ブロックは入れ子にできるので、複数のブロックを1つのブロックとすることもできます。

*/


コンピュータとのコミュニケーションを、考えてみましょう。



/*

簡単な入力と出力のプログラムを考えてみましょう。

プログラム中の scanf("%d",&joutei); がデータを入力するための文です。

scanf() は、書式付入力関数と呼ばれる標準のライブラリ関数で、

&joutei のようにアドレスを渡すように、決まっています。

「 LSIC-86 マニュアルビューア }で、確認してみましょう。

ありましたか。


******* LSI C-86 Reference Manual SCANF(3)*******


台形の面積を計算してみましょう。

プログラムの指示によって、パラメータを入力してください。

*/


/*


#include <stdio.h>

void main(){
int joutei,katei,takasa,t;

printf("台形の面積を計算してみましょう。プログラムの指示によって、
パラメータを入力してください。\n");

printf("上底を入力してください。\n");
scanf("%d",&joutei);

printf("下底を入力してください。\n");
scanf("%d",&katei);

printf("高さを入力してください。\n");
scanf("%d",&takasa);

t=(joutei+katei)*takasa/2;
if(t != 0){
printf("面積は%dです。\n",t);
}

}


*/


簡単な、プログラムですが、実用になっています。