さあレオ君、いよいよ最後の問題よ!
もう最後か〜。けっこう楽しかったのになぁ……
あら、嬉しいことを言うじゃない。
ユキ先輩のおかげで、僕もちょっとレベルアップできた気がします!
よかったよかった。それじゃあラスト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つ目以降の合計になるんですね!
そういうこと。だんだん答えに近付いてきたんじゃない?
そうなんですか?もうちょっと考えてみます!
この関数から自分自身を呼び出すようにすれば……