後輩たちのためのEV3rt講座⑥(関数を使う)

今回はソースコードをきれいに書くコツでもある『関数化』について紹介します。
教育版ソフトウェアでいうところの**`マイブロック`**ですね
![スクリーンショット 2018-10-01 22.00.06.png](https://qiita-image-store.s3.amazonaws.com/0/183170/4ffdca47-d895-f3a6-34c8-0eaf929df98e.png)
基本的にはC言語と同じですが、一応紹介しておきます。

**(注)今回の例ではコンフィグを省いています**

#関数でできること#
まずは関数とはどういうものかを理解しておきましょう。
例えば、『ライントレースをタッチセンサーが押されるまで行う』という制御があるとします。

```app.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`など、型を書きますよね。
関数も宣言するときに型を書きます。そもそも発想が逆なんですが、関数というのは別に簡略化の道具というわけではないんです。「ある作業をした結果を返す」というのが本来の役割で、そこを忘れてはいけません。
例えば、以下のような足し算をする関数があるとします。

```c
int add(){
    return 1+2;  //3を返す
}

void main(){
    int answer=add();  //answer=3
}
```

これは1+2をする関数ですが、`return`によって計算結果を返しています。
すなわち、`answer`に3が代入されることとなります。
今回、関数addは型が`int`ですが、これは`bool`などの他の型であっても問題ありません。(その型に沿った値を返す必要がありますが。)
又、返す値がない場合は、`void`と書きます。この関数はreturnしても値を返しません。

#引数(ひきすう)#
**いんすう**ではないですよ!!  (数学的にいんすうは因数)
**ひきすう**です!!

さて、では引数とはなんなのか？
先程から提示している関数ですが、名前の横に()がありますね。
この()の中に任意の値を代入することができるのです。

```math
y=f(a,b)\\
f(a,b)=a+b
```

この数式でいうところの`a`と`b`が引数です。
この引数も型を指定した上で値を代入させます。
では例として、先程の足し算関数をすこしいじってみましょう。

```c
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での関数#
上のライントレースの例をもとに関数化してみましょう。

```app.c
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で使用##
ソース上のあらゆる好きな場所で使うことができます。もちろん、何回でも使えます。

#まとめ#

- 関数を使って効率よく書く
- 関数にも型がある
- **いんすう**ではなく**ひきすう**!!
- 引数を使って関数を拡張

これでまた、プログラミングが上手くなったのではないでしょうか？
これを機に今までのプログラムも見直してみてみるのもいいでしょう。

次回:[第7回](https://qiita.com/koushiro/items/3d7911b4d6a9477904e1)
前回:[第5回](https://qiita.com/koushiro/items/1845f60c26573db3a9a8)