C言語関係掲示板

過去ログ

No.983 単方向リストのデータの追加方法

[戻る] [ホームページ]
No.12801

単方向リストのデータの追加方法
投稿者---リスト(2004/02/17 12:00:07)


以前リスト構造についてお世話になった者です。
今回も詰まってしまいました・・・。
プログラムは、
リストの中から指定のデータを探索し、そのデータの次に新しいデータを挿入する関数を追加する、
というものです。

自分なりに作ってみたのですが、追加の部分がうまく行えません。
どなたか教えていただけないでしょうか?
よろしくお願いします。
環境はvisual c++ 6.0です。

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

struct list{
    char name[20];
    char tel[13];
    struct list *next;
};

struct list *genlist(char *name,char *tel,struct list *head);//リストの作成//
void displist(struct list *p);//リストの表示//
void addlist(char *name,char *tel,struct list **ph,char *tan);//データの追加//

main(void){
    struct list *head;
    char name[20],tel[13],tan[20],mode[5];

    head=NULL;

    printf("処理入力:");
    gets(mode);

    while(strcmp(mode,"end")!=0){
        if(strcmp(mode,"gen")==0){
            printf("name入力:");
            gets(name);
            printf("tel入力:");
            gets(tel);
            head=genlist(name,tel,head);
        }
        else if(strcmp(mode,"add")==0){
            printf("探索データ入力");
            gets(tan);
            printf("name入力:");
            gets(name);
            printf("tel入力:");
            gets(tel);
            addlist(name,tel,&head,tan);
        }

    printf("処理入力:");
    gets(mode);
    }

    displist(head);
}

//リストの作成//
struct list *genlist(char *name,char *tel,struct list *head)
{
    struct list *sp;

    sp=(struct list *)malloc(sizeof(struct list));

    strcpy(sp->name,name);
    strcpy(sp->tel,tel);

    sp->next=head;
    head=sp;

    return head;
}

//リストの表示//
void displist(struct list *p)
{
    while(p!=NULL){
        printf("%s\t:%s\n",p->name,p->tel);
        p=p->next;
    }
}

//データの追加//
void addlist(char *name,char *tel,struct list **ph,char *tan)
{
    struct list *pt;
    struct list *p;
    struct list *pb;

    pt=(struct list *)malloc(sizeof(struct list));
    strcpy(pt->name,name);
    strcpy(pt->tel,tel);


    p=*ph;
    (struct list **)pb=ph;

    if(strcmp(p->name,tan)<=0){
        while(p!=NULL){
        pb=p;
        p=p->next;
    }

    if(p==*ph)*ph=pt;
    else
        pb->next=pt;
    pt->next=p;
    }
}


No.12803

Re:単方向リストのデータの追加方法
投稿者---あかま(2004/02/17 13:04:23)


リストを辿ることはできますか?
while(p->next != NULL){//リストの最後までいったら抜ける
    p=p->next;
    if(p->data == 目的) break;//入れるべき場所が見つかったら抜ける
}
//ここに挿入処理

かなり大雑把に書くとこんな感じなんですが。


No.12809

Re:単方向リストのデータの追加方法
投稿者---NykR(2004/02/17 14:43:43)


> (struct list **)pb=ph;

キャスト演算子の結果は右辺値です、つまり、代入式の左辺に書くことは出来ません。
pbに初期値を設定する必要は無い様に思うのですがどうでしょう?


> if(strcmp(p->name,tan)<=0){

strcmp()は、第1引数と第2引数が指す文字列が一致すれば0を、一致しなければ非0を返します。
ですから、この場合は、== 0 または、!= 0 で判定すれば良いと思います。

    if(p==*ph)*ph=pt;
    else
        pb->next=pt;
    pt->next=p;

これは次ではなく前に挿入する処理ですね。

リスト中のノード、previous_item の次に新しいノード、new_item を挿入する処理は、以下のように書けます。

new_item->next = previous_item->next;
previous_item->next = new_item;

図を描いて確かめてみてください。


ところで、探しているノードが見つからなかった ---つまり p == NULL だったときはどうするのかが気になるんですが、、、
問題からは読みとれませんね。

No.12812

単方向リストのデータの削除
投稿者---リスト(2004/02/17 21:32:34)


やりました。
あかまさんとNykRさんのおかげでプログラム完成しました。かなり嬉しいです。1週間以上ずっと悩んでいたので。
でも、分かってみると結構簡単なプログラムでした・・・。
あとすいません説明不足でしたが、探索データが見つからなかった場合は、何もしないでそのままスルーします。

それで今度は、このプログラムに追加で指定のデータを削除するという関数を作ってます。
もう95パーセントほど完成してるのですが、1つだけ分からないことがあります。
データの削除の関数の部分で、探索データが先頭にあった場合の削除に仕方が解からないのです。
例えば、aa-bb-cc-NULL というリストで
aaの部分の削除の仕方です。プログラムでは、

else if(saku==head){
head=head->next;
saku=head;
}

の部分です。自分ではこれで合っていると思うのですが、削除されません。
この場合、どうすればよいのでしょうか?よろしくお願いします。

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

struct list{
    char name[20];
    char tel[13];
    struct list *next;
};

struct list *genlist(char *name,char *tel,struct list *head);/*リストの作成*/
void displist(struct list *p);/*リストの表示*/
struct list *del(struct list *head);/*データの削除*/

main(void){
    struct list *head;
    char name[20],tel[13],mode[5];

    head=NULL;

    printf("処理入力:");
    gets(mode);

    while(strcmp(mode,"end")!=0){
        if(strcmp(mode,"gen")==0){
            printf("name入力:");
            gets(name);
            printf("tel入力:");
            gets(tel);
            head=genlist(name,tel,head);
        }
        else if(strcmp(mode,"del")==0){
            del(head);
        }

    printf("処理入力:");
    gets(mode);
    }

    displist(head);
}

/*リストの作成*/
struct list *genlist(char *name,char *tel,struct list *head)
{
    struct list *sp;

    sp=(struct list *)malloc(sizeof(struct list));

    strcpy(sp->name,name);
    strcpy(sp->tel,tel);

    sp->next=head;
    head=sp;

    return head;
}

/*リストの表示*/
void displist(struct list *p)
{
    while(p!=NULL){
        printf("%s\t:%s\n",p->name,p->tel);
        p=p->next;
    }
}

/*データの削除*/
struct list *del(struct list *head)
{
    struct list *saku;
    char tan[20];
    
    printf("探索データ入力:");
    gets(tan);
    
    saku=head;
    
    while(head!=NULL){
        if(strcmp(head->name,tan)==0){
            printf("探索が成功したよ!\n");
            break;
        }
        saku=head;
        head=head->next;
    }
    
    if(head==NULL){
        saku->next=NULL;
    }
    else if(saku==head){
        head=head->next;
        saku=head;    
    }
    else{
        saku->next=head->next;
    }
    
    return saku;
}


No.12813

Re:単方向リストのデータの削除
投稿者---リスト(2004/02/18 00:39:20)


お恥ずかしい、イージーミスでした。
main関数の方に戻り値を設定していませんでした。
無事解決しました。
あかまさん、NykRさんありがとうございました。