43222


Cの初心者です。  
再帰を使用して、ユーザーが入力した自然数（入力される自然数の数は分からない）をscanfで読み取り、その中から最大値を返す関数int
max()を書くという課題です。ユーザーが入力する最後の自然数は0でなくてはならず、0が入力されたら関数は必ず終了し、その時点での最大値を返す。

配列やリスト、ループを使わずに再帰だけで書かなければならず、以下のコードではどうも毎回入力した一つ目の数字だけを返すのですが、何時間格闘しても原因がわかりません。

しょうもない質問かもしれませんが、ご指摘、ご教授いただけると幸いです。

[code]

    #include <stdio.h>
    #include <stdlib.h>
    
    int max() {
        int i;
        int result = 0;
        scanf("%d", &i);
        if (i > result) {
            result = i;
            return result;
        }
        if (i < result)
            return result;
        if (i == 0)
            exit(0);
    
        return max();
    }
    
    int main() {
        printf("Enter your numbers (the last one should be zero):\n");
        printf("The maximum value is %d.\n", max());
        return 0;
    }
    
[/code]


CC BY-SA 3.0
2018-04-13T19:16:50.793
43221
2018-05-02T07:45:43.070
2018-04-13T20:35:37.800
24254
24254
question
c アルゴリズム
プログラミングCの再帰に関しての質問です。


max() がどういう動作をするか、頭から追いかけていけば、原因が分かります。

max() が最初に呼び出されると、

  1. 変数 i が作成される
  2. 変数 result が作成され、0 に初期化される。
  3. scanf で自然数が i に読み込まれる。 ここでユーザは 5 を入力したと仮定します。つまり i は 5 になります。
  4. i と result, つまり 5 と 0 を比べるので、最初の if 文の中身が実行される。
  5. result に i を代入し、5 になる。
  6. `return result;` で 5 を返して max() 関数から抜け出す。

でおしまいです。6. のところでは、再帰的に max() を呼ぶ必要があります。

その他、気づいた点をいくつか。

  1. 変数の result は、max()を呼び出すたびに新しく作成されます。つまり、最初の max()と、そこから呼び出したmax()は、それぞれ別の result なので、結果を取っておくのには使えません。結果を比較するには戻り値を利用しましょう。
  2. exit()はプログラム自体をいきなり終了します。`i==0`は、再帰の終了条件なので、普通に関数から抜けてください。

* * *

**考え方**  
ユーザーが1,3,0と入力した場合の考え方を説明します。

  1. 最初の max() 呼び出し: 1を受け取って、再帰呼び出し
  2. 二番目の max() 呼び出し: 3を受け取って、再帰呼び出し
  3. 三番目の max() 呼び出し: 0を受け取ったので、0を返して関数を抜ける。
  4. 二番目の max() に戻る: 自分の持っている3と、返ってきた0を比べて、大きいほうの3を返して関数を抜ける。
  5. 最初の max() に戻る: 自分の持っている1と、返ってきた3を比べて、大きいほうの3を返して関数を抜ける。

これで最大値の3が返ってきます。


CC BY-SA 3.0
2018-04-13T21:07:09.373
43222
2018-04-14T22:31:06.537
2018-04-14T22:31:06.537
3605
3605
43221
answer


Hideki さんの回答でほぼ良いと思うのですが、疑似コードで書いてみました。  
(再帰で書くより、ループが簡単なのですが、、、)

[code]

    int max(int lastMax) {
       // lastMax : 今までの最大値
       読み込んだ数値: i
       if (i == 0)  return lastMax;
       return max(i と lastMax の大きい方);
    }
    
    int main() {
        ...
        printf("The maximum value is %d.\n", max(0));  // 自然数の最小値: 0
        ...
    }
    
[/code]


CC BY-SA 3.0
2018-04-15T14:29:03.327
43273
2018-04-15T14:29:03.327
43221
answer


試しに作成してみました。

[code]

    #include <stdio.h>
    #include <stdlib.h>
    
    int max(int i) {
        int j;
        scanf("%d", &i);
        if (i == 0) return i;
        return (i > (j=max(i)) ? i : j);
    }
    
    int main() {
        int i;
        printf("Enter your numbers (the last one should be zero):\n");
        printf("The maximum value is %d.\n", max(0));
        return 0;
    }
    
[/code]


CC BY-SA 4.0
2018-05-02T07:45:43.070
43727
2018-05-02T07:45:43.070
20674
43221
answer