アプリ版:「スタンプのみでお礼する」機能のリリースについて

線形リストのコードでどーしても理解できない個所があります。

(以下、コード部分)
typedef struct __node {
char name[20];
char tel[16];
struct __node *next;
} Node;

typedef struct {
Node *head;
Node *tail;
} List;

Node *AllocNode(void)
{
return ((Node *)calloc(1, sizeof(Node)));
}

/*--- 新たに生成したノードを先頭へ挿入 ---*/
void InsertNode(List *list, const char *name, const char *tel)
{
Node *ptr = list->head;
list->head = AllocNode();

strcpy(list->head->name, name);
strcpy(list->haed->tel, tel);

list->head->next = ptr;
}

/*--- pが指すノードの直前にノードを挿入 ---*/
void PutNodeP(List *list, Node *p, const char *name, const char *tel)
{
if (p == list->head)
InsertNode(list, name, tel);
else {
Node *temp = AllocNode();

if (p == list->tail)
list->tail = temp;
else
*temp = *p;
strcpy(p->name, name);
strcpy(p->tel, tel);

temp->next = p;
}
}

上の29行目以降の≪pが指すノードの直前にノードを挿入≫についてです。
if文部分については理解できますが、else文部分について、何をやっているのかわからないです。Cの基本的な部分(ポインタも含めて)については充分に理解しているつもりです。
どなたか御教授頂けないでしょうか。
長々と書いてしまいましたがよろしくお願いします。

A 回答 (4件)

list->tail が指しているのはダミーのノードで実はデータが入っていないと見た>#3... あれ? でもそうするとダミーのノードが 2つもいるから無駄だ.


最初に空のリストをどのように作っていますか?
    • good
    • 0

なるほど。

Tacosanさんの説明でどのように挿入しているかがわかりました。後に挿入して中身を入れ替えているのですね。
ただ、そうなると以下の部分、elseはいらないんじゃないでしょうか?

if (p == list->tail)
list->tail = temp;
else
*temp = *p;

*temp = *pの部分、p == list->tailであるかどうかに関わらず実行されるべきだと思うのですが。

この回答への補足

else文以下です。
字下げがうまく表示されないみたいなので
こちら側で付け加えました
(かえって見づらくなりましたがお許しください)。

else{
(タブ)Node *temp = AllocNode();
(タブ)if(p == list->tail)
(タブ)(タブ)list->tail = temp;
(タブ)else
(タブ)(タブ)*temp = *p;
(タブ)strcpy(p->name, name);
(タブ)strcpy(p->tel, tel);
(タブ)p->next = temp;
}

補足日時:2010/04/26 18:37
    • good
    • 0

や, 「pが指すノードの直前にノードを挿入」というコメントが紛らわしいですが, 得られるリストだけを見れば「p が指すノードの直前に挿入した『よう』」には見えます>#1.


で本題ですが, 図を描いて動作を調べてみましたか?
・p の指すノードの後に新しいノードを挿入する
・今挿入したノードに p の指すノードの内容をコピーする
・もともと p が指していたノードには新しい内容を入れる
という一連の処理をしているだけです.
    • good
    • 0

このコード、本当に正しいのでしょうか?


pが指すノードの「直後」ではなく「直前」に挿入するんですよね?
そうするとheadからlistを辿っていかないといけないと思うのですが、そうしているようには見えないですね。
詳しいコードは書きませんが、こんな流れになると思います。

if (p == list->head)
InsertNode(list, name, tel);
else {
// p の直前のノードを見つける(仮にp0とします)。
// 新しいノードを生成する(temp)。name、telも設定します。
// tempをp0とpの間に挿入する。 
} 

直前に挿入するので、pがtailであるかどうかは気にしなくていいはずです。

この回答への補足

すいません、一部誤りがありました。

44行目について
(誤)temp->next = p;
(正)p->next = temp;

以上です。
本当に申し訳ありませんでした。
以上です、よろしくお願い致します。

補足日時:2010/04/26 16:12
    • good
    • 0

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