配列 練習問題4 解答解説

練習問題4: 終端記号 END をもつ整数型配列内のデータを,他の整数型配列へ複写する関数を作れ。今回は,関数名を含めて関数仕様も考えることが問題である。

 関数名は, data を copy するということで, dataCopy とした。

void dataCopy(int src[], int dest[]) の仕様
終端記号 END をもつように約束された整数型配列 src と整数型配列 dest とを引数にとり,src のデータ内容を dest へ複写しその最後に終端記号 END をつける.戻り値はない.

引数の変数名 src は source(送り元)の略であり, dest は destination(行き先)の略である.

void dataCopy(int src[], int dest[])
{
    int i;
   
    for (i = 0; src[i] != END; i++) {
        dest[i] = src[i];
    }
    dest[i] = END;
}

この関数内での for 文では, src[i] の値が終端記号 END になる直前まで dest[i] に src[i] を複写している.このままでは,dest には終端記号がついていないので,for 文が終わってから付加している.

 仮引数においては,何々型配列は何々型ポインタと同じである. したがって,引数に渡された配列をポインタとして扱って次のようにコーディングすることもできる.このようにすると,配列の添字として用いた変数 i が不要となる.

void dataCopy(int *src, int *dest)
{
    while (*src != END) {
        *dest = *src;
        src ++;
        dest ++;
    }
    *dest = END;
}

src ++ や dest ++ は,ポインタが指す配列中の要素位置を,一つ後ろにずらす効果がある.

この while 文でも終端記号は複写されないので,while の終了後,dest に END を付加する必要がある。

 「ループの後で END を付加するのは面倒だ.ループの中で src の終端記号もまとめて dest に複写すれば良いのに」と思った人は,次のように書けば良い.

void dataCopy(int *src, int *dest)
{
    while ((*dest = *src) != END) {
        src ++;
        dest ++;
    }
}

while の継続条件部分にある *dest = *src という代入式は,代入した値を,値としてもつことに注意しよう.すなわち, *src の値を *dest に代入して,その値で while 文を続けるかどうかを判断している.したがって,END が複写された時点で while 文が終了する.

 for 文を用いても,同様のコーディングができる.

void dataCopy(int *src, int *dest)
{
    for (; (*dest = *src) != END; src ++, dest ++);
}

この for 文は,初期設定部分がなく,継続条件部分で判断の前にデータの複写を行い,再設定部分には src と dest とを次の要素にずらすという二つの実行式があり,繰り返し本体部分がない.

このソースコードは短いが,ここまで短縮すると,見たときに意味を読み取るのが難しくなるので,あまりお勧めはしない。

 この関数の使用例を挙げておく。

main()
{
    int a[] = {4, 2, 3, 6, 3, 2, 1, 3, 5, 7, -1};
    int b[20];
    int i;

    dataCopy(a, b);
    for (i = 0; b[i] != END; i++) printf("%3d", b[i]);
    printf("\n");
}
 4  2  3  6  3  2  1  3  5  7

 ここで作った関数 dataCopy(src, dest) の引数は, src, dest の順に並んでいる.これは,「src から dest にコピーする」という言葉の順序に従うように決めたからである.英語で表現しても, "Copy data from src to dest." という順序になる.
一方,標準ライブラリにある,文字列を複写する関数 strcpy(dest, src) の引数は, dest, src の順に並んでいる.このようになった理由は, a = b という代入文では,左側に代入先が,右側に代入元がある,というである.
どちらの順序が良いのかというのは,意見が分かれるが,自分で書いたプログラムはどちらかに統一しておくべきである.