dポイントプレゼントキャンペーン実施中!

参考書の次のプログラムで、どうしても分からないことがあります。

-------------------------
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

typedef struct person {
char name[30];
int age;
struct person *next;
} Person;

void getsn(char *ss, int n); // gets()の代替関数

int main(void)
{
Person dmy = {"", 0, NULL}; // NULLを終端マークにする
Person *start = &dmy; // 先頭管理用の構造体を指す
Person *wkdtp; // 作業用の構造体を指す
Person *ip; // forループ制御用
char name[30], age_ss[10]; // データ入力用

while (1) {

/* キーボードからデータを入力する */
printf("名前 = ");
getsn(name, 80);
if (strcmp(name, "") == 0) break; // 改行だけなら入力の終了
printf("年齢 = ");
getsn(age_ss, 80);

/* 構造体1個分のメモリを確保する */
wkdtp = (Person *)malloc(sizeof(Person));
if (wkdtp == NULL) {
printf("メモリ確保できません。\n");
exit(EXIT_FAILURE);
}

/* 確保した構造体に名前と年齢を設定する */
strcpy(wkdtp->name, name);
wkdtp->age = atoi(age_ss);

/* 作成した構造体wkdtpを既存のチェーンにはめ込んでいく */
for (ip = start; ip->next != NULL; ip = ip->next) {
if (wkdtp->age < ip->next->age) {
wkdtp->next = ip->next;
ip->next = wkdtp;
break;
}
}

/* 最高齢だったらチェーンの最後につなぐ */
if (ip->next == NULL) {
ip->next = wkdtp;
wkdtp->next = NULL;
}
}

/* チェーンをたどって構造体の内容を表示する */
for (ip = start->next; ip != NULL; ip = ip->next)
printf("%s %d\n", ip->name, ip->age);

free(wkdtp);
return EXIT_SUCCESS;
}

void getsn(char *ss, int n)
{
fgets(ss, n, stdin);
if (ss[strlen(ss)-1] == '\n')
ss[strlen(ss)-1] = '\0';
}
-------------------------

【実行結果】
-------------------------
名前 = 田中一郎(キーボードから入力)
年齢 = 20(キーボードから入力)
名前 = 伊藤二郎(キーボードから入力)
年齢 = 40(キーボードから入力)
名前 = 鈴木三郎(キーボードから入力)
年齢 = 10(キーボードから入力)
名前 = 内田四郎(キーボードから入力)
年齢 = 30(キーボードから入力)
名前 = [Enter]のみ入力
鈴木三郎 10
田中一郎 20
内田四郎 30
伊藤二郎 40
-------------------------

これをトレースしていて、ポインタstartの中身がどうしても分からないので、プログラムの所々にprintf()を入れて、start->nextとip->nextを文字列として出力させたら、次のようになりました。

【改変したプログラムの実行結果】
-------------------------
whileループ1回目
名前 = 田中一郎
年齢 = 20
start->next = (null), ip->next = (null)
start->next = 田中一郎, ip->next = 田中一郎
whileループ2回目
名前 = 伊藤二郎
年齢 = 40
whileループ2回目中のforループ1回目:
start->next = 田中一郎, ip->next = 田中一郎
if文は偽
start->next = 田中一郎, ip->next = (null)
start->next = 田中一郎, ip->next = 伊藤二郎
whileループ3回目
名前 = 鈴木三郎
年齢 = 10
whileループ3回目中のforループ1回目:
start->next = 田中一郎, ip->next = 田中一郎
if文は真
start->next = 鈴木三郎, ip->next = 鈴木三郎
start->next = 鈴木三郎, ip->next = 鈴木三郎
start->next = 鈴木三郎, ip->next = 鈴木三郎
whileループ4回目
名前 = 内田四郎
年齢 = 30
whileループ4回目中のforループ1回目:
start->next = 鈴木三郎, ip->next = 鈴木三郎
if文は偽
whileループ4回目中のforループ2回目:
start->next = 鈴木三郎, ip->next = 田中一郎
if文は偽
whileループ4回目中のforループ3回目:
start->next = 鈴木三郎, ip->next = 伊藤二郎
if文は真
start->next = 鈴木三郎, ip->next = 内田四郎
start->next = 鈴木三郎, ip->next = 内田四郎
start->next = 鈴木三郎, ip->next = 内田四郎
whileループ5回目
名前 =
鈴木三郎 10
田中一郎 20
内田四郎 30
伊藤二郎 40
-------------------------

これでも、どうしても分からない疑問が残りました。
forループの第1項で、ip=start;が実行されるので、
ip->next = wkdtp;
が実行されるとstart->nextも変化することは理解できるのですが、それなのにそれ以降でstart->nextとip->nextが違う変化をするのはなぜでしょうか。プログラムを慎重にトレースしていっても、どうしても分かりません。
forループの第1項でip=start;とされたipとstartが、どうして同じ変化をしたり異なったりするのでしょうか。

どなたか解説をお願い致します。

A 回答 (2件)

うん, そこ.



そこで ip と start が違う値になれば, 「start->nextとip->nextが違う変化をする」としてもおかしくないでしょ?
    • good
    • 0
この回答へのお礼

ありがとうございます。なんだか、あまりにも悩んだ割にあっさりと解決して拍子抜けしました。せっかくforループ1回ごとの中身を表示させているのに、そのループごとにip=start;で初期化されるように勘違いしていました。ありがとうございました。

お礼日時:2021/01/16 20:31

ip を変えてるでしょ?

    • good
    • 0
この回答へのお礼

ご回答ありがとうございます。「ipを変えている」のは、for文の第3項のip=ip->nextのことですか?

お礼日時:2021/01/16 20:11

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!