過去に渡した値を返す関数

関数int delay6(int var)は1つのint型の引数varを持ち,関数の返す値は,6回前にこの関数が呼ばれた時のvarである。
ただし,最初の6回の呼び出し時の返す値は0とする。

方法1 現在値,前回値を保存しておく静的変数を使う方法

#include <stdio.h>
#include <stdlib.h>

int delay6(int var)
{
    static int previous0=0; /*受け取った値*/
    static int previous1=0; /*前回受け取った値*/
    static int previous2=0; /*その前回受け取った値*/
    static int previous3=0; /*その前回受け取った値*/
    static int previous4=0; /*その前回受け取った値*/
    static int previous5=0; /*その前回受け取った値*/
    static int previous6=0; /*その前回受け取った値=返す値*/
    previous6=previous5;
    previous5=previous4;
    previous4=previous3;
    previous3=previous2;
    previous2=previous1;
    previous1=previous0;
    previous0=var;
    return previous6;
}

int main()
{
    int i;
    int x,y;
    for(i=0;i<15;i++) {
        x=rand();
        y=delay6(x);
        printf("%2d x=%6d y=%6d\n",i,x,y);
    }
    return 0;
}

/* 実行結果
 0 x=    41 y=     0
 1 x= 18467 y=     0
 2 x=  6334 y=     0
 3 x= 26500 y=     0
 4 x= 19169 y=     0
 5 x= 15724 y=     0
 6 x= 11478 y=    41
 7 x= 29358 y= 18467
 8 x= 26962 y=  6334
 9 x= 24464 y= 26500
10 x=  5705 y= 19169
11 x= 28145 y= 15724
12 x= 23281 y= 11478
13 x= 16827 y= 29358
14 x=  9961 y= 26962
*/

この方法だと,10個前の値を返す関数を作るには変数を10個作らなければならないし,
100個前の値を返す関数を作るには変数を100個作らなければならない。

方法2 現在値,前回値を保存しておく静的配列変数を使う方法

#include <stdio.h>
#include <stdlib.h>

int delay6(int var)
{
    static int buffer[8]={0,0,0,0,0,0,0,0};
    buffer[6]=buffer[5];
    buffer[5]=buffer[4];
    buffer[4]=buffer[3];
    buffer[3]=buffer[2];
    buffer[2]=buffer[1];
    buffer[1]=buffer[0];
    buffer[0]=var;
    return buffer[6];
}

int main()
{
    int i;
    int x,y;
    for(i=0;i<15;i++) {
        x=rand();
        y=delay6(x);
        printf("%2d x=%6d y=%6d\n",i,x,y);
    }
    return 0;
}

/* 実行結果
 0 x=    41 y=     0
 1 x= 18467 y=     0
 2 x=  6334 y=     0
 3 x= 26500 y=     0
 4 x= 19169 y=     0
 5 x= 15724 y=     0
 6 x= 11478 y=    41
 7 x= 29358 y= 18467
 8 x= 26962 y=  6334
 9 x= 24464 y= 26500
10 x=  5705 y= 19169
11 x= 28145 y= 15724
12 x= 23281 y= 11478
13 x= 16827 y= 29358
14 x=  9961 y= 26962
*/

この方法だと,10個前の値を返す関数を作るには変数の移動を10回行わなければならないし,
100個前の値を返す関数を作るには変数の移動を100回行わなければならない。

方法3 静的配列変数をリングバッファとして使う方法

静的配列のお尻と先頭をつないでリング状のデータ保存領域のように考え,新しいデータを保存する場所を 示す変数putposと,取り出すデータを示す変数getposを用いて,データを順送りにせず,2つの変数を変化させる。この方法はリングバッファと呼 ばれ,用途が広い。
プログラム中,7号室の次に0号室がつながっているリング状の配列があり,この8要素の中で,putposとgetposが追いかけっこをするように移動しているのがわかる。

#include <stdio.h>
#include <stdlib.h>

int delay6(int var)
{
    static int buffer[8]={0,0,0,0,0,0,0,0};
    static int putpos=7;
    static int getpos=0;
    buffer[putpos]=var;
    putpos++;
    if (putpos==8) putpos=0;
    getpos++;
    if (getpos==8) getpos=0;
    return buffer[getpos];
}

int main()
{
    int i;
    int x,y;
    for(i=0;i<15;i++) {
        x=rand();
        y=delay6(x);
        printf("%2d x=%6d y=%6d\n",i,x,y);
    }
    return 0;
}

/* 実行結果
 0 x=    41 y=     0
 1 x= 18467 y=     0
 2 x=  6334 y=     0
 3 x= 26500 y=     0
 4 x= 19169 y=     0
 5 x= 15724 y=     0
 6 x= 11478 y=    41
 7 x= 29358 y= 18467
 8 x= 26962 y=  6334
 9 x= 24464 y= 26500
10 x=  5705 y= 19169
11 x= 28145 y= 15724
12 x= 23281 y= 11478
13 x= 16827 y= 29358
14 x=  9961 y= 26962
*/


テクニック staticの配列変数の初期化について

staticの配列変数の初期化で全てに0を埋める場合,配列の大きさが10個程度なら,これまでの方 法で良いが,100個とか1000個あると,直接0を並べるのは大変である。static変数であることの特性を考えて,initializedのような int型変数を導入すると,プログラムの動作として初期化出来る。

#include <stdio.h>
#include <stdlib.h>

int delay6(int var)
{
    static int buffer[8];
    static int initialized=0;
    static int putpos=7;
    static int getpos=0;
    int i;
    if (initialized==0) {
        for (i=0; i<8; i++) buffer[i]=0;
        initialized=1;
    }
    buffer[putpos]=var;
    putpos++;
    if (putpos==8) putpos=0;
    getpos++;
    if (getpos==8) getpos=0;
    return buffer[getpos];
}

int main()
{
    int i;
    int x,y;
    for(i=0;i<15;i++) {
        x=rand();
        y=delay6(x);
        printf("%2d x=%6d y=%6d\n",i,x,y);
    }
    return 0;
}

/* 実行結果
 0 x=    41 y=     0
 1 x= 18467 y=     0
 2 x=  6334 y=     0
 3 x= 26500 y=     0
 4 x= 19169 y=     0
 5 x= 15724 y=     0
 6 x= 11478 y=    41
 7 x= 29358 y= 18467
 8 x= 26962 y=  6334
 9 x= 24464 y= 26500
10 x=  5705 y= 19169
11 x= 28145 y= 15724
12 x= 23281 y= 11478
13 x= 16827 y= 29358
14 x=  9961 y= 26962
*/