C言語

【C言語】第4章第12回:ポインタと構造体の組み合わせ

ポインタと構造体を組み合わせることで、データの操作や管理を効率化できます。この章では、ポインタと構造体の基本から応用例までを丁寧に解説します。

1. 構造体とは?

1.1 構造体の基本

構造体は、異なる型のデータを1つの単位として扱うためのデータ構造です。

例:基本的な構造体の定義と使用

#include <stdio.h>

struct Person {
    char name[50];
    int age;
    float height;
};

int main() {
    struct Person person = {"Alice", 25, 170.5};

    printf("Name: %s\n", person.name);
    printf("Age: %d\n", person.age);
    printf("Height: %.1f cm\n", person.height);

    return 0;
}

2. 構造体とポインタの基本的な使い方

2.1 構造体ポインタの宣言

構造体ポインタを使用することで、構造体を直接操作できます。

例:構造体ポインタを使ったメンバーアクセス

#include <stdio.h>

struct Person {
    char name[50];
    int age;
    float height;
};

int main() {
    struct Person person = {"Bob", 30, 180.2};
    struct Person *ptr = &person; // 構造体ポインタを初期化

    printf("Name: %s\n", ptr->name); // ->を使ってアクセス
    printf("Age: %d\n", ptr->age);
    printf("Height: %.1f cm\n", ptr->height);

    return 0;
}

2.2 構造体ポインタの利点

  • データのコピーを避けられるため効率的。
  • 関数に構造体を渡す際に便利。

3. 構造体ポインタと動的メモリ確保

3.1 動的に構造体を作成する

例:mallocを使用して構造体のメモリを動的に割り当てる

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

struct Person {
    char name[50];
    int age;
    float height;
};

int main() {
    struct Person *person = (struct Person *)malloc(sizeof(struct Person));
    if (person == NULL) {
        printf("Memory allocation failed.\n");
        return 1;
    }

    // メンバーの初期化
    printf("Enter name: ");
    scanf("%s", person->name);
    printf("Enter age: ");
    scanf("%d", &person->age);
    printf("Enter height: ");
    scanf("%f", &person->height);

    printf("Name: %s, Age: %d, Height: %.1f cm\n", person->name, person->age, person->height);

    free(person); // メモリを解放

    return 0;
}

4. 応用例:構造体ポインタを使ったリンクリスト

4.1 リンクリストの基本構造

リンクリストは、ポインタを使って要素同士を接続したデータ構造です。

4.2 単方向リンクリストの実装例

例:構造体ポインタを使ったリンクリスト

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

struct Node {
    int data;
    struct Node *next;
};

void printList(struct Node *head) {
    while (head != NULL) {
        printf("%d -> ", head->data);
        head = head->next;
    }
    printf("NULL\n");
}

int main() {
    struct Node *head = (struct Node *)malloc(sizeof(struct Node));
    struct Node *second = (struct Node *)malloc(sizeof(struct Node));
    struct Node *third = (struct Node *)malloc(sizeof(struct Node));

    if (head == NULL || second == NULL || third == NULL) {
        printf("Memory allocation failed.\n");
        return 1;
    }

    head->data = 1;
    head->next = second;

    second->data = 2;
    second->next = third;

    third->data = 3;
    third->next = NULL;

    printList(head);

    free(head);
    free(second);
    free(third);

    return 0;
}

5. 練習問題

以下の課題に挑戦して、構造体とポインタの組み合わせを深く理解しましょう。

  1. 構造体ポインタを使って、複数の人のデータを動的に作成するプログラムを作成してください。
  2. 構造体ポインタを使った単方向リンクリストのノードを追加する関数を作成してください。
  3. 構造体ポインタを使って、簡単な学生情報管理システムを作成してください。

6. 練習問題の解答と解説

問1の解答

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

struct Person {
    char name[50];
    int age;
};

int main() {
    int n;
    printf("Enter number of people: ");
    scanf("%d", &n);

    struct Person *people = (struct Person *)malloc(n * sizeof(struct Person));
    if (people == NULL) {
        printf("Memory allocation failed.\n");
        return 1;
    }

    for (int i = 0; i < n; i++) {
        printf("Enter name for person %d: ", i + 1);
        scanf("%s", people[i].name);
        printf("Enter age for person %d: ", i + 1);
        scanf("%d", &people[i].age);
    }

    for (int i = 0; i < n; i++) {
        printf("Person %d: Name: %s, Age: %d\n", i + 1, people[i].name, people[i].age);
    }

    free(people);

    return 0;
}

7. まとめ

ポインタと構造体を組み合わせることで、柔軟で効率的なデータ操作が可能になります。応用例を試しながら、さらなるスキルアップを目指しましょう。