さあレオ君、いよいよ最後の問題よ!
もう最後か〜。けっこう楽しかったのになぁ……
あら、嬉しいことを言うじゃない。
ユキ先輩のおかげで、僕もちょっとレベルアップできた気がします!
よかったよかった。それじゃあラスト1問、はりきっていきましょうか!
はーい!
以下は、第29問の答えのプログラムです。数値の並びを連結リスト(linked list)構造で表現し、その合計を関数SumListValues()で求めています。この関数ではループが使われていますが、ループを使わない方法に置き換えたいと考えています。
どう書き直せばいいか、分かりますか?
main.c
#include <stdio.h>
#include <stdlib.h>
typedef struct ListNode {
int value;
struct ListNode *pNext;
} ListNode;
int SumListValues(const ListNode *pNode) {
int sum = 0;
for (const ListNode *p = pNode; p; p = p->pNext) {
sum += p->value;
}
return sum;
}
int main(void) {
ListNode node4 = { 40, 0 };
ListNode node3 = { 30, &node4 };
ListNode node2 = { 20, &node3 };
ListNode node1 = { 10, &node2 };
printf("Sum: %d\n", SumListValues(&node1));
return EXIT_SUCCESS;
}
実行結果
Sum: 100
第29問は正しいプログラムを、別の正しいプログラムに書き換える問題だったわよね。
はい、そうでした。
そこで、さらに別の方法で正しいプログラムを書いてみよう!っていうのが今回の問題よ。
なるほど。でも、ループを使わない方法なんて、本当にあります?
あるのよ。数値の並びは
10、20、30、40でしょう?
はい。つまり、求めたいのは「
10、20、30、40の合計」ってことですよね。
そうね。それを最初の1つと残りの3つを分けて考えたら、「
10」と「20、30、40の合計」の2つになるわよね。
え……はい、なります。
その2つを足したら、求めたい合計になるのよ。
ええっ?それって解決になってます?
あら、何かおかしなことを言ったかしら?
だって、「
20、30、40の合計」のほうは、結局ループしないと求められないですよ。
そこはもう1回、最初の1つと残りを分けるのよ。
ん?「
20」と「30、40の合計」ってことですか?
そう!そうやって2つに分ければ、足し算できるでしょ?
あのー、何をどうすればいいのか、さっぱり分からないです……
うん。ちょっと手応えがあったほうが最終問題っぽいでしょ。
そ、そうですね……
じゃあ、ヒントね。合計を求める関数には何を渡しているかしら?
えっと、呼び出し元は
main()関数にあって……ここだな。
printf("Sum: %d\n", SumListValues(&node1));
引数として
node1、つまり1つ目のノードのアドレスを渡してます。
すると、1つ目以降の合計が分かるのよね。そこに2つ目のノードのアドレスを渡したらどうなるかしら?
それって、こういうこと?
printf("Sum: %d\n", SumListValues(&node2));
そっか。この場合は2つ目以降の合計になるんですね!
そういうこと。だんだん答えに近付いてきたんじゃない?
そうなんですか?もうちょっと考えてみます!
この関数から自分自身を呼び出すようにすれば……
