9章 関数その2

http://www.geocities.jp/ky_webid/c/009.html

どうやら関数の宣言順はとても重要らしい。

まだ定義されてない関数を使ってしまうとエラーになる。

なので宣言に依存しないように、関数のプロトタイプ宣言というものを初めにやっておくことが重要という話。

でもこれなんか二度手間だよね。同じ定義文を書くわけでしょ?少し面倒臭い気がする。

問題1

次のプログラムを実行すると、画面に何と表示されるか答えて下さい。

#include <stdio.h>

/* 関数プロトタイプ */
int pow_num(int num);    /* 引数の値を2乗した値を返す */

int main(void) {
    int num = 2;
    printf( "%d, %d, %d\n", num, pow_num(num), pow_num( pow_num(num) ) );
    return 0;
}

/* 引数の値を2乗した値を返す */
int pow_num(int num) {
    return num * num;
}

何と表示されるか。なんだか関数の呼び出しが複雑だけど一つずつ展開していけば迷うことは無いはず。

printf( "%d, %d, %d\n", num, pow_num(num), pow_num( pow_num(2) ) );

printf( "%d, %d, %d\n", num, pow_num(num), pow_num( 4 ) );

printf( "%d, %d, %d\n", num, pow_num(num), 16 );

printf( "%d, %d, %d\n", num, pow_num(2), 16 );

printf( "%d, %d, %d\n", num, 4, 16 );

printf( "%d, %d, %d\n", 2, 4, 16 );

ということで2,4,16が答え。

問題2

キーボードから秒数を正数(正の整数)で入力し、それを「○時間○分○秒」の形に変換して表示するプログラムを作って下さい。ただし、最低1つは自作関数を使い、関数プロトタイプも書いて下さい。

うおっと。いきなり難易度が上がった気がする。。。

できるかな・・・。

秒を60で割れば分になる。そして分を60で割れば時間になる。

割り切れなかった場合に出る余りはそれがそれぞれ秒と分になる。

void maketime (int second);

void maketime (int second) {
    int minute;
    int hour;
    
    minute = second / 60;
    hour   = minute / 60;
    second = second % 60;
    minute = minute % 60;
    printf("%d%d%d秒",hour,minute,second);
}

int main () {
    int second;
    
    scanf("%d", &second );
    maketime(second);
    return 0;
}

できた。実行結果色々

$ main
80
0時1分20秒
$ main
5000
1時23分20秒
$ main
86400
24時0分0秒

あってるはず。

答え合わせ
void print_time(int second) {
    int time;
    int minute;

    time = second / 3600;                  /* 時間を計算 */
    minute = (second - time * 3600) / 60;  /* 分を計算 */
    second = second % 60;                  /* 秒を計算 */

    printf( "%d時間%d%d\n", time, minute, second );
}

あれ・・・。全然違う・・・。

読み解いてみよう。まず初めに秒を3600で割る。3600というのは3600秒=60分=1時間のこと。

つまりこの処理で時間が割り出せるという話だね。

で次。さっき割り出した時間にまた3600をかけて秒に戻し、それを全体の秒から引く。

こうすれば時間以下(3599以下)の残りの秒が取れるのでそれを60で割ると分になる。

最後は俺が考えたやり方と同じで秒を60で割った余りを求めて終了。

なるほどね。

こちらの書き方がセオリーなんだろうか。

でも一応計算結果はあってるのでとりあえず今はいいか。

問題3

ソースの先頭に関数プロトタイプさえあれば、関数定義がどのような順番であっても、コンパイルが正常に行えることを確認して下さい。

適当に順番変えてみたけどうまくいった。

プロトタイプって少し面倒な気もするけど必要ということなので忘れずに書くようにしないとダメだよ、俺。