独学で勉強してる者ですが、又分からない事が出てきており、困っております。 下記の状態なんですが,ご助言お願いします一方向チェーンなんですが。 #include<stdio.h> //一方向チェーン #include<stdlib.h> #include<string.h> typedef struct person{ char name[20]; int age; struct person *next; }Person; int main(void){ Person dmy={"",0,NULL}; Person *start=&dmy; Person *wkdtp; Person *ip; char name[20],age_ss[6]; while(1){ printf("名前=");gets(name); if(strcmp(name,"")==0)break; printf("年齢=");gets(age_ss); wkdtp=(Person *)malloc(sizeof(Person)); if(wkdtp==NULL){ printf("メモリ確保できません\n"); exit(EXIT_FAILURE); } strcpy(wkdtp->name,name); wkdtp->age=atoi(age_ss); 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("%10s %3d\n",ip->name,ip->age); } return(EXIT_SUCCESS); } ip->next=wkdtp;だと前と次の間に新たにチェーンを埋め込もうとしてるのは分かるんですが、 でもこれだと、ip->nextだけじゃなく、ip->nextが表しているポインタも変わってしまうのではないかと思うのですが、 つまりwkdtpという先頭アドレスをもつ構造体(入ってきたのと次の二つ)が2個できてしまう。うまく説明できなくてすいません。
チェーンの解釈について
チェーンの解釈について
Re:チェーンの解釈について
こんな絵でご理解いただけるでしょうか。 【リンクの付け替え前】 ip ip->next +--------+ +--------+ | | -----------------------> | | +--------+ +--------+ wkdtp +--------+ | | +--------+ 【リンクの付け替え操作(その1)】 wkdtp->next=ip->next; の実行 ip ip->next +--------+ +--------+ | | -----------------------> | | +--------+ +--> +--------+ | wkdtp | +--------+ | | | --+ +--------+ 【リンクの付け替え操作(その2)】 ip->next=wkdtp; の実行 ip +--------+ +--------+ | | --+ +--> | | +--------+ | | +--------+ | | | wkdtp | | +--------+ | +--> | | --+ +--------+
Re:チェーンの解釈について
返信ありがとうございます。 (その1)で一番右の奴がip->nextじゃないですか、 それもwkdtpには変わらないんでしょうか? つまり下の図のように。それともアドレスはmallocにより固定的に 決まるから、変更不可能で変更しようとしても、何も起きないということでしょうか? 凄いお馬鹿な質問だったらごめんなさい。 【リンクの付け替え操作(その2)】 ip->next=wkdtp; の実行 ip wkdtp +--------+ +--------+ | | --+ +--> | | +--------+ | | +--------+ | | | wkdtp | | +--------+ | +--> | | --+ +--------+
Re:チェーンの解釈について
> (その1)で一番右の奴がip->nextじゃないですか、
> それもwkdtpには変わらないんでしょうか?
変わらないです。
wkdtpという、今回リスト構造に加えたい領域に対しては、
1)wkdtpから出て行くリンク
2)wkdtpに入ってくるリンク
の2本を適切につなぐ必要があります。
1)今回は、もともとの ip と ip->next との間に wkdtp をつなぎたいので、
wkdtp の次(つまり wkdtp->next)は、(もともとの)ip->next となります。
これが、
wkdtp->next = ip->next;
という文と対応します。
2)今回は、もともとの ip と ip->next との間に wkdtp をつなぎたいので、
ip の次(つまり、新しい ip->next)は、wkdtp となります。
これが、
ip->next = wkdtp;
という文と対応します。
なお、今回の図のような内容を貼り付ける際は、
図の前後を<pre>と</pre>タグ(カッコは半角)ではさんで、
レイアウトが崩れないようにしてください。
これらのタグではさまなかった場合、ブラウザは複数の空白を1つの空白と
みなしてしまい、レイアウトが崩れます。
> それもwkdtpには変わらないんでしょうか?
変わらないです。
wkdtpという、今回リスト構造に加えたい領域に対しては、
1)wkdtpから出て行くリンク
2)wkdtpに入ってくるリンク
の2本を適切につなぐ必要があります。
1)今回は、もともとの ip と ip->next との間に wkdtp をつなぎたいので、
wkdtp の次(つまり wkdtp->next)は、(もともとの)ip->next となります。
これが、
wkdtp->next = ip->next;
という文と対応します。
2)今回は、もともとの ip と ip->next との間に wkdtp をつなぎたいので、
ip の次(つまり、新しい ip->next)は、wkdtp となります。
これが、
ip->next = wkdtp;
という文と対応します。
なお、今回の図のような内容を貼り付ける際は、
図の前後を<pre>と</pre>タグ(カッコは半角)ではさんで、
レイアウトが崩れないようにしてください。
これらのタグではさまなかった場合、ブラウザは複数の空白を1つの空白と
みなしてしまい、レイアウトが崩れます。
Re:チェーンの解釈について
> 変わらない理由が知りたいんですが、駄目でしょうか?
リンクの付け替え操作は2段階に分かれています。
1段階目:今回リスト構造に挿入したい wkdtp から出て行くリンクを設定する
2段階目:wkdtp に入ってくるリンクを設定する
ここまではいいですか?
リンクの付け替え操作は2段階に分かれています。
1段階目:今回リスト構造に挿入したい wkdtp から出て行くリンクを設定する
2段階目:wkdtp に入ってくるリンクを設定する
ここまではいいですか?
Re:チェーンの解釈について
はい、それは分かるんですが、余分な動作ip->nextで 示される構造体のポインタが変わらない理由がしりたいんですが。 訂正したんですが、念のためもう一度書きます。しつこくてすいません。 Re:チェーンの解釈について 返信ありがとうございます。 (その1)で一番右の奴がip->nextじゃないですか、 それもwkdtpには変わらないんでしょうか? つまり下の図のように。それともアドレスはmallocにより固定的に 決まるから、変更不可能で変更しようとしても、何も起きないということでしょうか? 【リンクの付け替え操作(その2)】 ip->next=wkdtp; の実行 ip wkdtp +--------+ +--------+ | | --+ +--> | | +--------+ | | +--------+ | | | wkdtp | | +--------+ | +--> | | --+ +--------+
Re:チェーンの解釈について
box さんの図を、ちょっと変更させてもらって、書いてみる。
【リンクの付け替え前】
ip ipNext
+-----------------+ +---------+
|ip->next = ipNext| --------------------------> | |
+-----------------+ +---------+
wkdtp
+--------------------+
|wkdtp->next = 未設定|
+--------------------+
【リンクの付け替え操作(その1)】
wkdtp->next=ipNext; の実行
ip ipNext
+-----------------+ +---------+
|ip->next = ipNext| --------------------------> | |
+-----------------+ +--> +---------+
|
wkdtp |
+--------------------+ |
|wkdtp->next = ipNext|---+
+--------------------+
【リンクの付け替え操作(その2)】
ip->next=wkdtp; の実行
ip ipNext
+----------------+ +--------+
|ip->next = wkdtp|--+ +--> | |
+----------------+ | | +--------+
| |
| wkdtp |
| +--------------------+ |
+-->|wkdtp->next = ipNext|--+
+--------------------+
【リンクの付け替え前】
ip ipNext
+-----------------+ +---------+
|ip->next = ipNext| --------------------------> | |
+-----------------+ +---------+
wkdtp
+--------------------+
|wkdtp->next = 未設定|
+--------------------+
【リンクの付け替え操作(その1)】
wkdtp->next=ipNext; の実行
ip ipNext
+-----------------+ +---------+
|ip->next = ipNext| --------------------------> | |
+-----------------+ +--> +---------+
|
wkdtp |
+--------------------+ |
|wkdtp->next = ipNext|---+
+--------------------+
【リンクの付け替え操作(その2)】
ip->next=wkdtp; の実行
ip ipNext
+----------------+ +--------+
|ip->next = wkdtp|--+ +--> | |
+----------------+ | | +--------+
| |
| wkdtp |
| +--------------------+ |
+-->|wkdtp->next = ipNext|--+
+--------------------+
Re:チェーンの解釈について
> はい、それは分かるんですが、余分な動作ip->nextで > 示される構造体のポインタが変わらない理由がしりたいんですが。 余分な動作は、何もありません。リンクを張り替えるために必要かつ不可欠な動作です。 先ほど書いた1段階目から、もう一度説明します。 1段階目:今回リスト構造に挿入したい wkdtp から出て行くリンクを設定する ip ip->next +--------+ +--------+ | | -----------------------> | | +--------+ +--> +--------+ | wkdtp | +--------+ | | | --+ +--------+ 1段階目が終わった時点では、上図のようになります。 つまり、「そのときの」ip->nextが、wkdtpの「次」に来るようにしなければなりません。 そこで、ip->nextの値を、wkdtp->nextに代入します。 式で書くと、 wkdtp->next = ip->next; です。 1段階目は、これで終わりです。ここまでは、いいでしょうか?
Re:チェーンの解釈について
はい、ここまでは大丈夫です。ここの時点で一番右の奴がip->nextなのに、
次の操作でwkdtpに変わらないのが疑問なんです。
すいません、迷惑をおかけして。
次の操作でwkdtpに変わらないのが疑問なんです。
すいません、迷惑をおかけして。
Re:チェーンの解釈について
> はい、ここまでは大丈夫です。ここの時点で一番右の奴がip->nextなのに、 > 次の操作でwkdtpに変わらないのが疑問なんです。 リンクの張り替えの2段階目です。 2段階目:今回リスト構造に挿入したい wkdtp に入ってくるリンクを設定する 1段階目が終わった時点では、そのときの ip->next に向かっているリンクが2本あります。 ip から出ているリンクと wkdtp から出ているリンクです。 リンク張り替えの2段階目では、2本のリンクのうち、ip から出ているリンクだけを 張り替える必要があります。もう1本の、wkdtp から出ているリンクは、 1段階目で処理済のため2段階目で意識してはいけません。 張り替えた結果、1段階目終了時点の ip->next に成り代わって、wkdtp が 「新しく」「ipの次」になります。 「新しく」ということは、代入することを意味します。 「ipの次」は、文字通り ip->next のことです。 よって、2段階目の操作は、 ip->next = wkdtp; となります。
Re:チェーンの解釈について
少し補足します。 A B +-----+ +-----+ | | | | +-----+ +-----+ 上図のように、リンクを張っていない状態から A B +-----+ +-----+ | | -----> | | +-----+ +-----+ このようにリンクを張るということは、 Aの次をBにする、ということです。 ここで、いったんリンクのことを離れてみます。 「nを10にする」をC言語で表現すると、 n = 10; となります。これはご理解いただけるでしょう。 リンクの話に戻ります。 「Aの次をBにする」をC言語で表現するということは、 「Aの次」にBを代入することです。 つまり、 A->next = B; です。
Re:チェーンの解釈について
工夫を凝らした解答(その時点でのリンクの詳細)のお陰で、
なんとか分かりました。私の素朴な疑問にお付き合いさせてしまって、
ご迷惑をおかけして、すみませんでした。
またの機会がありましたら、よろしくお願いします。
長い時間ありがとうございました。
なんとか分かりました。私の素朴な疑問にお付き合いさせてしまって、
ご迷惑をおかけして、すみませんでした。
またの機会がありましたら、よろしくお願いします。
長い時間ありがとうございました。