今回はソースコードをきれいに書くコツでもある『関数化』について紹介します。
教育版ソフトウェアでいうところの**マイブロック
**ですね
基本的にはC言語と同じですが、一応紹介しておきます。
(注)今回の例ではコンフィグを省いています
#関数でできること#
まずは関数とはどういうものかを理解しておきましょう。
例えば、『ライントレースをタッチセンサーが押されるまで行う』という制御があるとします。
void main_task(intptr_t unused)
{
float lasterror = 0, integral = 0;
float midpoint = 30;
while (ev3_touch_sensor_is_pressed(0) != true) {
float error = midpoint - ev3_color_sensor_get_reflect(0); //error 差分
integral = error + integral * 0.5; //integral 微分
float steer = 0.07 * error + 0.3 * integral + 1 * (error - lasterror); //steer モーター設定
ev3_motor_steer(EV3_MOTOR_A, EV3_MOTOR_D, 10, steer);
lasterror = error; //lasterror 積分
tslp_tsk(1); //1mm秒休止
}
}
これを何回もやりたいなと思ったとき、いちいち全部書いているとソースコードが見にくくなり、非効率です。
しかしこのプログラムを『関数化』してやると、11行が1行に短縮されるのです。
できるだけ見やすく、扱いやすいプログラムを書くのが重要です。
#関数にも型がある#
変数を宣言するときに、int
やchar
bool
など、型を書きますよね。
関数も宣言するときに型を書きます。そもそも発想が逆なんですが、関数というのは別に簡略化の道具というわけではないんです。「ある作業をした結果を返す」というのが本来の役割で、そこを忘れてはいけません。
例えば、以下のような足し算をする関数があるとします。
int add(){
return 1+2; //3を返す
}
void main(){
int answer=add(); //answer=3
}
これは1+2をする関数ですが、return
によって計算結果を返しています。
すなわち、answer
に3が代入されることとなります。
今回、関数addは型がint
ですが、これはbool
などの他の型であっても問題ありません。(その型に沿った値を返す必要がありますが。)
又、返す値がない場合は、void
と書きます。この関数はreturnしても値を返しません。
#引数(ひきすう)#
いんすうではないですよ!! (数学的にいんすうは因数)
ひきすうです!!
さて、では引数とはなんなのか?
先程から提示している関数ですが、名前の横に()がありますね。
この()の中に任意の値を代入することができるのです。
y=f(a,b)\\
f(a,b)=a+b
この数式でいうところのa
とb
が引数です。
この引数も型を指定した上で値を代入させます。
では例として、先程の足し算関数をすこしいじってみましょう。
int add(int a , int b){
return a + b; //a+bを返す
}
void main(){
int answer=add(3,5); //answer=8
int answer2=add(100,200); //answer2=300
int answer3=add(100,-200); //answer3=-100
}
これでだいたいわかったと思います。(もう説明はいらないかな??)
引数の型も基本的に自由です。
では、実際にEV3rtで実装していきましょう。
#EV3rtでの関数#
上のライントレースの例をもとに関数化してみましょう。
void main_task(intptr_t unused)
{
linetrace(0,0,30); //(ⅲ)main_taskで使用
}
void linetrace(float LAST , float INTEG , float MID); //(ⅰ)まずはこの一文を書く
void linetrace(float LAST , float INTEG , float MID){ //(ⅱ)そして本文
while (ev3_touch_sensor_is_pressed(0) != true) {
float lasterror = LAST, integral = INTEG;
float midpoint = MID;
float error = midpoint - ev3_color_sensor_get_reflect(0); //error 差分
integral = error + integral * 0.5; //integral 微分
float steer = 0.07 * error + 0.3 * integral + 1 * (error - lasterror); //steer モーター設定
ev3_motor_steer(EV3_MOTOR_A, EV3_MOTOR_D, 10, steer);
lasterror = error; //lasterror 積分
tslp_tsk(1); //1mm秒休止
}
}
##(ⅰ)まずはこの一文を書く##
関数の本文を書く前にここで一文書きます。書かなくてもコンパイルは通りますが、書くことが推奨されているので、書いておきましょう。
##(ⅱ)本文##
実際の処理内容です。ここではfloat型の引数を3つ(LAST,INTEG,MID)を使用しています。
中身の処理はライントレースです。
##(ⅲ)main_taskで使用##
ソース上のあらゆる好きな場所で使うことができます。もちろん、何回でも使えます。
#まとめ#
- 関数を使って効率よく書く
- 関数にも型がある
- いんすうではなくひきすう!!
- 引数を使って関数を拡張
これでまた、プログラミングが上手くなったのではないでしょうか?
これを機に今までのプログラムも見直してみてみるのもいいでしょう。