プログラミングのネタ帳

30代からプログラミングをはじめた。記憶力が悪いのでメモ代わりに。

C構造体作ったリスト形式にデータを挿入する

以前にエントリーしたものの続き。

 構造体で実装したリスト構造にinsert()のような機能を追加した。

 

myprograming-tips.hatenablog.jp

 

やっていること自体に大きな変わりはなく、ポインタの操作を行っているだけ。

データの受け渡しはポインタで行う。構造体はそのままだとデータのコピーを渡す(はず)なので、このようにポインタで受け渡しするのがベターらしいです。

最初のうちは混乱するので、やはり紙に書いてまとめてみる方が分かりやすいと思います。

 

以下はコード例。追加したのはmyinsert()関数。他にもコメントを中心にちょっと以前のコードから少し修正

 


#include 
#include 
#include 

struct tfield{
    char hantei[8];
    int score;
    struct tfield *pointer;
};

//プロトタイプ宣言
struct tfield *genlist();
void display(struct tfield *p);
struct tfield *myinsert(struct tfield *p,int j,char *hnt,int scr);

int main(){
    struct tfield *p;
    //リストを生成する関数
    p=genlist();

    //リストの内容を表示
    printf("before insert \n");
    display(p);

    //4番目の箇所にデータを挿入
    p=myinsert(p,4,"E",0);

    //リストの表示
    printf("after insert \n");
    display(p);
}

//関数名 genlist()
//機能
//  コード内で記述のある配列を構造体のメンバ変数とし、
//  構造体型の変数型をもつリストを生成する関数
//引数():なし 
//戻り値(struct tfield*):struct tfield型のリスト先頭のアドレス
struct tfield *genlist(){
    int i=0;
    int array_score[]={90,80,70,60};
    char array_hantei[][2]={"A","B","C","D"};
    struct tfield *head,*mydata,*dummy;
    
    dummy=malloc(sizeof(struct tfield));
    head=dummy;
    while(1){
        mydata=malloc(sizeof(struct tfield));
        strcpy(mydata->hantei,array_hantei[i]);
        mydata->score=array_score[i];
        dummy->pointer=mydata;
        dummy=mydata;
        if(strcmp(mydata->hantei,"D")==0){break;}
        i=i+1;
    }
    mydata->pointer=NULL;
    return head;
}

// display(struct tfield *p)関数
//機能
//  リストの先頭のポインタを与えるとNULLになるまで表示する関数 
//引数(struct tfield*):リストの先頭のアドレス 
//戻り値:なし
void display(struct tfield *p){
    while(1){
        p=p->pointer;
        printf("%s %d %p \n",p->hantei,p->score,p->pointer);
        if(p->pointer==NULL){break;}
    }
}

//struct tfield *myinsert()関数
//機能
//  引数int jで指定したj番目の要素となるようにリストの間に構造体を挿入する
//  作成する構造体データも引数で与える
//引数(struct tfield*, int, char*,int):構造体のアドレス,挿入する箇所,struct tfieldの値,struct tfieldの値
//戻り値(struct tfield*):appendした後の構造体の先頭のアドレス
struct tfield *myinsert(struct tfield *p,int j,char *hnt,int scr){
    int i=0;
    struct tfield *newdata,*tmp,*head;
    head=p;
    
    //挿入データの作成
    newdata=malloc(sizeof(struct tfield));
    strcpy(newdata->hantei,hnt);
    newdata->score=scr;

    while(1){
        p=p->pointer;
        if(i==j-1){
    //挿入する箇所のひとつ前のデータのアドレスがp, 挿入する箇所の次のデータを指すアドレスはp->pointerにある
    //tmpに挿入後のデータのアドレスを一時保管
            tmp=p->pointer;
    //挿入か所の次のデータをさせいていたところをnewdataの先頭にする
            p->pointer=newdata;
    //そして挿入データであるnewdataの次のデータを指すアドレスは、保管しておいたtmpである。これを代入する
            newdata->pointer=tmp;
        }
        if(p->pointer==NULL ){break;};
        i=i+1;
    }
    return head;
}

before insert A 90 0x55d8b0eff2e0 B 80 0x55d8b0eff300 C 70 0x55d8b0eff320 D 60 (nil) after insert A 90 0x55d8b0eff2e0 B 80 0x55d8b0eff300 C 70 0x55d8b0eff320 D 60 0x55d8b0eff750 E 0 (nil)


0~3要素のリストに4要素目に代入するようにしたので、末尾にデータを挿入する形になっている。