0
1

More than 1 year has passed since last update.

双方向リストを使った関数管理方法と構造体管理方法

Last updated at Posted at 2023-09-03

前回

再帰的関数呼び出しを使った配列代入方法と関数管理方法

参考ページ

モノづくりC言語塾 C言語 関数ポインタ【ポインタを使って関数を呼ぶ仕組み解説】

超初心者向けプログラミング入門【構造体】

SAMEBASE サメベース 【[C言語]双方向リストとその基本操作(追加、削除、挿入)関数の実装[コード付]】

日々量産 【C言語でvectorさせろ】

Programming Place Plus 【連結リスト②(双方向・循環) | Programming Place Plus アルゴリズムとデータ構造編【データ構造】 第4章】

参考文献

問題解決力を鍛える!アルゴリズムとデータ構造 (KS情報科学専門書)
大槻兼資・著 秋葉拓哉・監修

[改訂新版]C言語による標準アルゴリズム事典
奥村晴彦 著

準備

今回はオンラインコンパイラを使用します。
オンラインコンパイラ

ソースコード

sample.c
#include <stdio.h>
#include <stdlib.h>

//Hello_Variable型を定義する
typedef struct Hello_Variable {
    long i;
    double d[11];
}Hello_Variable;

//関数fを代入することを想定して、関数ポインタfupo型を定義する
typedef void (*fupo)(Hello_Variable*);

//関数fを代入することを想定して、fupo型の変数uを構造体Hello型の内に定義する
typedef struct Hello {
	Hello_Variable j;
	fupo u;
}Hello;

// ノードの構造体
typedef struct Node {
    Hello data;
    struct Node* next;
    struct Node* prev;
}Node;

// 新しいノードを作成する関数
struct Node* createNode(Hello data) {
    struct Node* newNode = (struct Node*)malloc(sizeof(struct Node));
    if (newNode == NULL) {
        printf("メモリの割り当てに失敗しました\n");
        exit(1);
    }
    newNode->data = data;
    newNode->next = NULL;
    newNode->prev = NULL;
    return newNode;
}

// リストの先頭にノードを挿入する関数
void insertAtBeginning(struct Node** head, Hello data) {
    struct Node* newNode = createNode(data);
    newNode->next = *head;
    if (*head != NULL) {
        (*head)->prev = newNode;
    }
    *head = newNode;
}

// リストの末尾にノードを挿入する関数
void insertAtEnd(struct Node** head, Hello data) {
    struct Node* newNode = createNode(data);
    struct Node* current = *head;
    if (current == NULL) {
        *head = newNode;
    } else {
        while (current->next != NULL) {
            current = current->next;
        }
        current->next = newNode;
        newNode->prev = current;
    }
}

// リストを表示する関数
void printList(struct Node* head) {
    struct Node* current = head;
    while (current != NULL) {
        //Hello型関数ポインタuを実行
        current->data.u(&current->data.j);
        //Hello_Variable型変数j.iを表示
        printf("%ld -> ", current->data.j.i);
        current = current->next;
    }
    printf("NULL\n");
}

void f(Hello_Variable* v){
	//引数v->dに値を代入
	v->d[v->i]=1+(v->i*0.1);
	//引数v->dを表示
	printf("_%1.2lf_",v->d[v->i]);
	//引数v->iに1を加算
	v->i++;
	if(v->i<=10){
		//引数iが10以下のとき関数fを再帰呼び出し
		f(v);
	}
	else{
	    printf("\n");
		//引数iが10より上になったらHELLO_VARIABLEポインタ型vを返す
		return;
	}
	return;
}


int main() {
    struct Node* myList = NULL;
    Hello data[4];
    int i=0;
    for(;i<4;i++){
        //Hello_Variable型変数j.iに0を代入
        data[i].j.i=0;
        //関数fを代入
        data[i].u=f;
    }
    
    
    // リストに要素を追加
    insertAtBeginning(&myList, data[0]);
    insertAtBeginning(&myList, data[1]);
    insertAtBeginning(&myList, data[2]);
    insertAtEnd(&myList, data[3]);

    // リストを表示
    printf("双方向リスト: ");
    printList(myList);

    return 0;
}

実行結果

console
双方向リスト: _1.00__1.10__1.20__1.30__1.40__1.50__1.60__1.70__1.80__1.90__2.00_
11 -> _1.00__1.10__1.20__1.30__1.40__1.50__1.60__1.70__1.80__1.90__2.00_
11 -> _1.00__1.10__1.20__1.30__1.40__1.50__1.60__1.70__1.80__1.90__2.00_
11 -> _1.00__1.10__1.20__1.30__1.40__1.50__1.60__1.70__1.80__1.90__2.00_
11 -> NULL

0
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
1