Cプログラマへの道 #4 - 構造体 & 列挙型

Last Edited: 7/25/2024

このブログ記事では、C言語における構造体、列挙型を紹介します。

C Structs & Enums

構造体

構造体(struct)は、オブジェクト指向プログラミングにおけるメソッドを持たないクラスのようなものです。 異なる型の変数を一つの名前の下で一緒にメモリブロックに保存することができます(Haskellにおけるdataに似ています)。 構造体は次のように定義できます。

// 新しい構造体の定義
struct User {
    char name[15];
    int age;
    char password[15];
};
 
int main () {
    // 宣言
    struct User user1;
 
    // 初期化
    strcpy(user1.name, "TK");
    user1.age = 20;
    strcpy(user1.password, "random123");
    
    // 宣言 + 初期化
    struct User user2 = {"KT", 20, "Random123"};
    struct User user3 = { .name = "KT", .age = 20, .password = "Random123"};
    
    return 0;
}

構造体はプロパティを持つ新しいデータ型のように扱うことができます。そのため、以下のように構造体の配列を作成することも可能です。

int main () {
    
    // 宣言 + 初期化
    struct User user1 = {"TK", 20, "Random123"};
    struct User user2 = {"KT", 20, "Random123"};
    struct User user3 = {"TKBlog", 20, "Random123"};
 
    // 構造体の配列
    struct User users[] = {user1, user2, user3};
 
    // sizeofを使用した構造体配列の反復処理
    for (int i = 0; i < sizeof(users)/sizeof(users[0]); i++) {
        printf("%-12s", users[i].name);
        printf("%d", users[i].age);
    }
 
    return 0;
}

ただし、毎回struct Userと入力するのは面倒です。そこでtypedefを使って構文を簡素化することができます。

// 構造体 "User" を定義するためのtypedefの使用
typedef struct {
    char name[15];
    int age;
    char password[15];
} User;
 
int main () {
    // これで`struct`は必要ありません
    User user1 = {"TK", 20, "Random123"};
    User user2 = {"KT", 20, "Random123"};
    User user3 = {"TKBlog", 20, "Random123"};
 
    return 0;
}

typedefは既存のデータ型に新しい名前を付けるための便利な方法です(Haskellのtypeと同様)。構造体以外の既存の他のデータ型にも使用できます。

typedef char user[15];
 
int main () {
    user user1 = "TK";
    return 0;
}

列挙型

コードを簡略化するもう一つの概念が列挙型(enum)です。これは、関連する整数を持つ定数の集合を作成できます。たとえば、曜日に依存する条件があるとします。

int main () {
 
    // 曜日 : 番号
    // Sun : 0
    // Mon : 1
    //     :
    // Sat : 7
 
    int today = 0;
 
    if (today == 0 || today == 6) {
        printf("週末!");
    } else {
        printf("平日");
    }
 
    return 0;
}

上記のように各曜日に整数を割り当て、どの整数がどの曜日に対応するかを示すコメントを上に書くことができます。 しかし、これはあまり読みやすいとは言えません。ここでenumが登場します。

enum Day{Sun, Mon, Tue, Wed, Thu, Fri, Sat};
// ^ 各定数に0から6の値を自動的に割り当てる
 
int main () {
 
    enum Day today = Sun; // 整数として扱われる Sun = 0
 
    if (today == Sun || today == Sat) {
        printf("週末!");
    } else {
        printf("平日");
    }
 
    // 本質的には同じなので、整数と比較することもできます
    if (today == 0) {
        printf("今日は日曜日です。");
    }
 
    return 0;
}

上記のように、同じことを実現しながらコードをより読みやすくします。もし曜日を1から始めたい場合は、次のように設定できます。

enum Day{Sun=1, Mon=2, Tue=3, Wed=4, Thu=5, Fri=6, Sat=7};

クイズ

この記事では、学習した内容を確認するためのクイズを設けます。記事のメイン部分を読んだ後に、ぜひ自分で問題を解いてみることを強くお勧めします。各問題をクリックすると答えが表示されます。

リソース