[C言語] 構造体配列の初期化方法と活用例

C言語における構造体配列の初期化は、構造体のメンバーを指定して行います。

例えば、構造体Personを定義し、その配列を初期化する場合、Person people[2] = {{"Alice", 30}, {"Bob", 25}};のように記述します。

構造体配列は、同じ型のデータをまとめて管理するのに便利で、例えば学生の成績管理や社員情報の管理に活用されます。

これにより、データの一括処理や検索が容易になり、コードの可読性と保守性が向上します。

この記事でわかること
  • 構造体配列の静的初期化、動的初期化、メンバー指定による初期化の方法
  • 学生の成績管理や社員情報の管理、商品カタログの管理における構造体配列の活用例
  • 構造体配列の要素の追加、削除、検索、更新の方法
  • ソートアルゴリズムの実装やファイル入出力との連携、データベースの簡易実装における構造体配列の応用例

目次から探す

構造体配列の初期化方法

構造体配列は、複数の構造体を一つの配列として扱うことができる便利なデータ構造です。

ここでは、構造体配列の初期化方法について詳しく解説します。

静的初期化

静的初期化は、プログラムのコンパイル時に構造体配列の要素を初期化する方法です。

以下に例を示します。

#include <stdio.h>
// 学生の情報を表す構造体
typedef struct {
    char name[50]; // 名前
    int age;       // 年齢
    float gpa;     // GPA
} Student;
int main() {
    // 構造体配列の静的初期化
    Student students[3] = {
        {"田中太郎", 20, 3.5},
        {"鈴木花子", 22, 3.8},
        {"佐藤次郎", 19, 3.2}
    };
    // 初期化された構造体配列の内容を表示
    for (int i = 0; i < 3; i++) {
        printf("名前: %s, 年齢: %d, GPA: %.1f\n", students[i].name, students[i].age, students[i].gpa);
    }
    return 0;
}
名前: 田中太郎, 年齢: 20, GPA: 3.5
名前: 鈴木花子, 年齢: 22, GPA: 3.8
名前: 佐藤次郎, 年齢: 19, GPA: 3.2

この例では、3人の学生の情報を持つ構造体配列を静的に初期化しています。

各要素の値は、配列の宣言時に指定されています。

動的初期化

動的初期化は、プログラムの実行時に構造体配列の要素を初期化する方法です。

以下に例を示します。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
// 学生の情報を表す構造体
typedef struct {
    char name[50]; // 名前
    int age;       // 年齢
    float gpa;     // GPA
} Student;
int main() {
    // 構造体配列の動的初期化
    int num_students = 3;
    Student *students = (Student *)malloc(num_students * sizeof(Student));
    // 各要素を動的に初期化
    strcpy(students[0].name, "田中太郎");
    students[0].age = 20;
    students[0].gpa = 3.5;
    strcpy(students[1].name, "鈴木花子");
    students[1].age = 22;
    students[1].gpa = 3.8;
    strcpy(students[2].name, "佐藤次郎");
    students[2].age = 19;
    students[2].gpa = 3.2;
    // 初期化された構造体配列の内容を表示
    for (int i = 0; i < num_students; i++) {
        printf("名前: %s, 年齢: %d, GPA: %.1f\n", students[i].name, students[i].age, students[i].gpa);
    }
    // メモリの解放
    free(students);
    return 0;
}
名前: 田中太郎, 年齢: 20, GPA: 3.5
名前: 鈴木花子, 年齢: 22, GPA: 3.8
名前: 佐藤次郎, 年齢: 19, GPA: 3.2

この例では、malloc関数を使用して動的にメモリを確保し、実行時に構造体配列を初期化しています。

使用後はfree関数でメモリを解放する必要があります。

メンバー指定による初期化

メンバー指定による初期化は、構造体のメンバーを指定して初期化する方法です。

以下に例を示します。

#include <stdio.h>
// 学生の情報を表す構造体
typedef struct {
    char name[50]; // 名前
    int age;       // 年齢
    float gpa;     // GPA
} Student;
int main() {
    // 構造体配列のメンバー指定による初期化
    Student students[3] = {
        {.name = "田中太郎", .age = 20, .gpa = 3.5},
        {.name = "鈴木花子", .age = 22, .gpa = 3.8},
        {.name = "佐藤次郎", .age = 19, .gpa = 3.2}
    };
    // 初期化された構造体配列の内容を表示
    for (int i = 0; i < 3; i++) {
        printf("名前: %s, 年齢: %d, GPA: %.1f\n", students[i].name, students[i].age, students[i].gpa);
    }
    return 0;
}
名前: 田中太郎, 年齢: 20, GPA: 3.5
名前: 鈴木花子, 年齢: 22, GPA: 3.8
名前: 佐藤次郎, 年齢: 19, GPA: 3.2

この例では、構造体のメンバーを指定して初期化しています。

メンバーを指定することで、コードの可読性が向上し、誤りを防ぐことができます。

構造体配列の活用例

構造体配列は、データを整理して管理するための強力なツールです。

ここでは、構造体配列を活用した具体的な例をいくつか紹介します。

学生の成績管理

学生の成績を管理するために、構造体配列を使用することができます。

以下の例では、学生の名前、学籍番号、成績を管理しています。

#include <stdio.h>
// 学生の情報を表す構造体
typedef struct {
    char name[50];   // 名前
    int student_id;  // 学籍番号
    float grade;     // 成績
} Student;
int main() {
    // 学生の成績を管理する構造体配列
    Student students[3] = {
        {"田中太郎", 1001, 85.5},
        {"鈴木花子", 1002, 92.0},
        {"佐藤次郎", 1003, 78.5}
    };
    // 学生の成績を表示
    for (int i = 0; i < 3; i++) {
        printf("名前: %s, 学籍番号: %d, 成績: %.1f\n", students[i].name, students[i].student_id, students[i].grade);
    }
    return 0;
}
名前: 田中太郎, 学籍番号: 1001, 成績: 85.5
名前: 鈴木花子, 学籍番号: 1002, 成績: 92.0
名前: 佐藤次郎, 学籍番号: 1003, 成績: 78.5

この例では、3人の学生の成績を構造体配列で管理しています。

各学生の情報は、構造体のメンバーとして格納されています。

社員情報の管理

社員の情報を管理するために、構造体配列を使用することができます。

以下の例では、社員の名前、社員番号、給与を管理しています。

#include <stdio.h>
// 社員の情報を表す構造体
typedef struct {
    char name[50];   // 名前
    int employee_id; // 社員番号
    float salary;    // 給与
} Employee;
int main() {
    // 社員情報を管理する構造体配列
    Employee employees[3] = {
        {"山田太郎", 2001, 500000},
        {"佐藤花子", 2002, 550000},
        {"鈴木次郎", 2003, 480000}
    };
    // 社員情報を表示
    for (int i = 0; i < 3; i++) {
        printf("名前: %s, 社員番号: %d, 給与: %.0f\n", employees[i].name, employees[i].employee_id, employees[i].salary);
    }
    return 0;
}
名前: 山田太郎, 社員番号: 2001, 給与: 500000
名前: 佐藤花子, 社員番号: 2002, 給与: 550000
名前: 鈴木次郎, 社員番号: 2003, 給与: 480000

この例では、3人の社員の情報を構造体配列で管理しています。

各社員の情報は、構造体のメンバーとして格納されています。

商品カタログの管理

商品カタログを管理するために、構造体配列を使用することができます。

以下の例では、商品の名前、商品コード、価格を管理しています。

#include <stdio.h>
// 商品の情報を表す構造体
typedef struct {
    char name[50];   // 商品名
    int product_code; // 商品コード
    float price;     // 価格
} Product;
int main() {
    // 商品カタログを管理する構造体配列
    Product products[3] = {
        {"ノートパソコン", 3001, 150000},
        {"スマートフォン", 3002, 80000},
        {"タブレット", 3003, 60000}
    };
    // 商品カタログを表示
    for (int i = 0; i < 3; i++) {
        printf("商品名: %s, 商品コード: %d, 価格: %.0f\n", products[i].name, products[i].product_code, products[i].price);
    }
    return 0;
}
商品名: ノートパソコン, 商品コード: 3001, 価格: 150000
商品名: スマートフォン, 商品コード: 3002, 価格: 80000
商品名: タブレット, 商品コード: 3003, 価格: 60000

この例では、3つの商品を構造体配列で管理しています。

各商品の情報は、構造体のメンバーとして格納されています。

構造体配列を使用することで、商品情報を効率的に管理することができます。

構造体配列の操作

構造体配列を使用することで、データの管理が容易になりますが、実際のアプリケーションでは要素の追加、削除、検索、更新といった操作が必要になることがあります。

ここでは、これらの操作について解説します。

要素の追加と削除

構造体配列に要素を追加したり削除したりするには、配列のサイズを変更する必要があります。

C言語では、配列のサイズを動的に変更することはできないため、動的メモリ確保を使用します。

要素の追加

要素を追加するには、realloc関数を使用して配列のサイズを拡張します。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
// 商品の情報を表す構造体
typedef struct {
    char name[50];   // 商品名
    int product_code; // 商品コード
    float price;     // 価格
} Product;
int main() {
    int num_products = 3;
    Product *products = (Product *)malloc(num_products * sizeof(Product));
    // 初期データの設定
    strcpy(products[0].name, "ノートパソコン");
    products[0].product_code = 3001;
    products[0].price = 150000;
    strcpy(products[1].name, "スマートフォン");
    products[1].product_code = 3002;
    products[1].price = 80000;
    strcpy(products[2].name, "タブレット");
    products[2].product_code = 3003;
    products[2].price = 60000;
    // 新しい商品を追加
    num_products++;
    products = (Product *)realloc(products, num_products * sizeof(Product));
    strcpy(products[3].name, "スマートウォッチ");
    products[3].product_code = 3004;
    products[3].price = 30000;
    // 商品カタログを表示
    for (int i = 0; i < num_products; i++) {
        printf("商品名: %s, 商品コード: %d, 価格: %.0f\n", products[i].name, products[i].product_code, products[i].price);
    }
    // メモリの解放
    free(products);
    return 0;
}
商品名: ノートパソコン, 商品コード: 3001, 価格: 150000
商品名: スマートフォン, 商品コード: 3002, 価格: 80000
商品名: タブレット, 商品コード: 3003, 価格: 60000
商品名: スマートウォッチ, 商品コード: 3004, 価格: 30000

この例では、reallocを使用して配列のサイズを拡張し、新しい商品を追加しています。

要素の削除

要素を削除するには、削除したい要素を配列の末尾に移動し、reallocでサイズを縮小します。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
// 商品の情報を表す構造体
typedef struct {
    char name[50];   // 商品名
    int product_code; // 商品コード
    float price;     // 価格
} Product;
int main() {
    int num_products = 3;
    Product *products = (Product *)malloc(num_products * sizeof(Product));
    // 初期データの設定
    strcpy(products[0].name, "ノートパソコン");
    products[0].product_code = 3001;
    products[0].price = 150000;
    strcpy(products[1].name, "スマートフォン");
    products[1].product_code = 3002;
    products[1].price = 80000;
    strcpy(products[2].name, "タブレット");
    products[2].product_code = 3003;
    products[2].price = 60000;
    // 商品を削除(例: スマートフォンを削除)
    int delete_index = 1;
    for (int i = delete_index; i < num_products - 1; i++) {
        products[i] = products[i + 1];
    }
    num_products--;
    products = (Product *)realloc(products, num_products * sizeof(Product));
    // 商品カタログを表示
    for (int i = 0; i < num_products; i++) {
        printf("商品名: %s, 商品コード: %d, 価格: %.0f\n", products[i].name, products[i].product_code, products[i].price);
    }
    // メモリの解放
    free(products);
    return 0;
}
商品名: ノートパソコン, 商品コード: 3001, 価格: 150000
商品名: タブレット, 商品コード: 3003, 価格: 60000

この例では、指定したインデックスの要素を削除し、配列のサイズを縮小しています。

要素の検索

構造体配列の要素を検索するには、線形探索を行います。

以下の例では、商品コードを基に商品を検索しています。

#include <stdio.h>
#include <string.h>
// 商品の情報を表す構造体
typedef struct {
    char name[50];   // 商品名
    int product_code; // 商品コード
    float price;     // 価格
} Product;
int main() {
    Product products[3] = {
        {"ノートパソコン", 3001, 150000},
        {"スマートフォン", 3002, 80000},
        {"タブレット", 3003, 60000}
    };
    // 検索する商品コード
    int search_code = 3002;
    int found = 0;
    // 商品を検索
    for (int i = 0; i < 3; i++) {
        if (products[i].product_code == search_code) {
            printf("商品名: %s, 商品コード: %d, 価格: %.0f\n", products[i].name, products[i].product_code, products[i].price);
            found = 1;
            break;
        }
    }
    if (!found) {
        printf("商品コード %d の商品は見つかりませんでした。\n", search_code);
    }
    return 0;
}
商品名: スマートフォン, 商品コード: 3002, 価格: 80000

この例では、商品コード3002を持つ商品を検索し、見つかった場合はその情報を表示しています。

要素の更新

構造体配列の要素を更新するには、検索した要素のメンバーを変更します。

以下の例では、商品コードを基に商品の価格を更新しています。

#include <stdio.h>
#include <string.h>
// 商品の情報を表す構造体
typedef struct {
    char name[50];   // 商品名
    int product_code; // 商品コード
    float price;     // 価格
} Product;
int main() {
    Product products[3] = {
        {"ノートパソコン", 3001, 150000},
        {"スマートフォン", 3002, 80000},
        {"タブレット", 3003, 60000}
    };
    // 更新する商品コードと新しい価格
    int update_code = 3002;
    float new_price = 85000;
    int found = 0;
    // 商品を検索して価格を更新
    for (int i = 0; i < 3; i++) {
        if (products[i].product_code == update_code) {
            products[i].price = new_price;
            printf("商品名: %s, 商品コード: %d, 新しい価格: %.0f\n", products[i].name, products[i].product_code, products[i].price);
            found = 1;
            break;
        }
    }
    if (!found) {
        printf("商品コード %d の商品は見つかりませんでした。\n", update_code);
    }
    return 0;
}
商品名: スマートフォン, 商品コード: 3002, 新しい価格: 85000

この例では、商品コード3002を持つ商品の価格を85000に更新しています。

検索と更新を組み合わせることで、特定の要素を効率的に変更することができます。

構造体配列の応用

構造体配列は、データを整理して管理するための基本的な手段ですが、応用することでより高度なデータ処理が可能になります。

ここでは、構造体配列を用いたいくつかの応用例を紹介します。

ソートアルゴリズムの実装

構造体配列をソートすることで、データを特定の順序で整理することができます。

以下の例では、クイックソートアルゴリズムを使用して、商品を価格の昇順にソートしています。

#include <stdio.h>
#include <stdlib.h>
// 商品の情報を表す構造体
typedef struct {
    char name[50];   // 商品名
    int product_code; // 商品コード
    float price;     // 価格
} Product;
// クイックソート用の比較関数
int compare(const void *a, const void *b) {
    Product *productA = (Product *)a;
    Product *productB = (Product *)b;
    return (productA->price > productB->price) - (productA->price < productB->price);
}
int main() {
    Product products[3] = {
        {"ノートパソコン", 3001, 150000},
        {"スマートフォン", 3002, 80000},
        {"タブレット", 3003, 60000}
    };
    // 商品を価格の昇順にソート
    qsort(products, 3, sizeof(Product), compare);
    // ソートされた商品を表示
    for (int i = 0; i < 3; i++) {
        printf("商品名: %s, 商品コード: %d, 価格: %.0f\n", products[i].name, products[i].product_code, products[i].price);
    }
    return 0;
}
商品名: タブレット, 商品コード: 3003, 価格: 60000
商品名: スマートフォン, 商品コード: 3002, 価格: 80000
商品名: ノートパソコン, 商品コード: 3001, 価格: 150000

この例では、qsort関数を使用して商品を価格の昇順にソートしています。

比較関数を定義することで、任意の基準でソートが可能です。

ファイル入出力との連携

構造体配列をファイルに保存したり、ファイルから読み込んだりすることで、データの永続化が可能になります。

以下の例では、商品情報をファイルに書き込み、再度読み込んで表示しています。

#include <stdio.h>
#include <stdlib.h>
// 商品の情報を表す構造体
typedef struct {
    char name[50];   // 商品名
    int product_code; // 商品コード
    float price;     // 価格
} Product;
int main() {
    Product products[3] = {
        {"ノートパソコン", 3001, 150000},
        {"スマートフォン", 3002, 80000},
        {"タブレット", 3003, 60000}
    };
    // ファイルに書き込み
    FILE *file = fopen("products.dat", "wb");
    if (file == NULL) {
        perror("ファイルのオープンに失敗しました");
        return 1;
    }
    fwrite(products, sizeof(Product), 3, file);
    fclose(file);
    // ファイルから読み込み
    Product loaded_products[3];
    file = fopen("products.dat", "rb");
    if (file == NULL) {
        perror("ファイルのオープンに失敗しました");
        return 1;
    }
    fread(loaded_products, sizeof(Product), 3, file);
    fclose(file);
    // 読み込んだ商品を表示
    for (int i = 0; i < 3; i++) {
        printf("商品名: %s, 商品コード: %d, 価格: %.0f\n", loaded_products[i].name, loaded_products[i].product_code, loaded_products[i].price);
    }
    return 0;
}
商品名: ノートパソコン, 商品コード: 3001, 価格: 150000
商品名: スマートフォン, 商品コード: 3002, 価格: 80000
商品名: タブレット, 商品コード: 3003, 価格: 60000

この例では、構造体配列をバイナリファイルに書き込み、再度読み込んで表示しています。

ファイル入出力を使用することで、データを永続的に保存することができます。

データベースの簡易実装

構造体配列を使用して、簡易的なデータベースを実装することができます。

以下の例では、商品情報を管理する簡易データベースを実装しています。

#include <stdio.h>
#include <string.h>
// 商品の情報を表す構造体
typedef struct {
    char name[50];   // 商品名
    int product_code; // 商品コード
    float price;     // 価格
} Product;
// 商品を検索する関数
Product *find_product(Product *products, int num_products, int product_code) {
    for (int i = 0; i < num_products; i++) {
        if (products[i].product_code == product_code) {
            return &products[i];
        }
    }
    return NULL;
}
int main() {
    Product products[3] = {
        {"ノートパソコン", 3001, 150000},
        {"スマートフォン", 3002, 80000},
        {"タブレット", 3003, 60000}
    };
    // 商品コードで商品を検索
    int search_code = 3002;
    Product *product = find_product(products, 3, search_code);
    if (product != NULL) {
        printf("商品名: %s, 商品コード: %d, 価格: %.0f\n", product->name, product->product_code, product->price);
    } else {
        printf("商品コード %d の商品は見つかりませんでした。\n", search_code);
    }
    return 0;
}
商品名: スマートフォン, 商品コード: 3002, 価格: 80000

この例では、商品コードを基に商品を検索する簡易データベースを実装しています。

構造体配列を使用することで、データの検索や管理が容易になります。

よくある質問

構造体配列のサイズを変更するには?

構造体配列のサイズを変更するには、動的メモリ確保を使用します。

静的配列のサイズはコンパイル時に決定されるため、実行時に変更することはできません。

動的配列を使用することで、mallocrealloc関数を用いてサイズを変更できます。

例えば、reallocを使って配列のサイズを拡張することが可能です。

構造体配列とポインタの違いは?

構造体配列とポインタは、データの格納とアクセス方法に違いがあります。

構造体配列は、メモリ上に連続して配置された構造体の集合です。

一方、ポインタはメモリ上の任意の位置を指すことができ、構造体のアドレスを格納することができます。

ポインタを使うことで、動的にメモリを確保したり、関数間で構造体を渡す際に効率的に扱うことができます。

構造体配列のメモリ管理はどうする?

構造体配列のメモリ管理は、動的メモリ確保を行う場合に重要です。

malloc関数を使用してメモリを確保し、reallocでサイズを変更することができます。

使用が終わったら、free関数を使って確保したメモリを解放する必要があります。

これにより、メモリリークを防ぎ、プログラムの安定性を保つことができます。

まとめ

この記事では、C言語における構造体配列の初期化方法や活用例、操作方法、応用について詳しく解説しました。

構造体配列を用いることで、データの管理や操作が効率的に行えることが理解できたのではないでしょうか。

これを機に、実際のプログラムで構造体配列を活用し、より複雑なデータ構造を扱うスキルを磨いてみてください。

  • URLをコピーしました!
目次から探す