C 語言程式設計教學:結構 (Struct)

PUBLISHED ON JUL 31, 2018 — PROGRAMMING

    相對於基礎型別,結構 (struct) 是一種複合型別;在我們先前的程式中,大多都僅使用基礎型別,透過結構,我們可以創造新的型別。由於 C 沒有內建的物件導向語法,使用指向結構的指標來模擬 C++ (或 Java) 的 this 指標是相當常見的手法。

    宣告結構

    使用 struct 保留字可以宣告結構,如下例:

    struct person {
        char *name;
        unsigned age;
    };
    
    int main(void)
    {
        struct person p = { "Michael", 37 };  
        
        return 0;
    }
    

    但這種初始化結構的方式需記憶該結構的屬性的位置,若屬性有更動需一併更動相關程式碼,在軟工觀點上不佳。可以改用以下的方法來初始化結構:

    struct person {
        char *name;
        unsigned age;
    };
    
    int main(void)
    {
        struct person p = { 
            .name = "Michael", 
            .age = 37
        };  
        
        return 0;
    }
    

    可以搭配 typedef 來簡化結構的型別名稱:

    // Forward declaration.
    typedef struct person Person;
    
    struct person {
        char *name;
        unsigned age;
    };
    
    int main(void)
    {
        Person p = { 
            .name = "Michael", 
            .age = 37
        };  
        
        return 0;
    }
    

    如果想節省命名空間可改用以下方式來宣告結構:

    typedef struct {
        char *name;
        unsigned age;
    } Person;
    

    存取結構內屬性

    使用 . (點號) 可存取結構內的屬性,如下例:

    #include <assert.h>
    
    typedef struct point Point;
    
    struct point {
        double x;
        double y;
    };
    
    int main(void)
    {
        Point pt = {
            .x = 3.0,
            .y = 4.0
        };
        
        assert(pt.x == 3);
        assert(pt.y == 4);
        
        return 0;
    }
    

    內嵌在結構內的結構

    由於結構也是一種型別,我們可以在結構內嵌入另一個結構,如下例:

    #include <assert.h>
    #include <string.h>
    
    typedef struct person Person;
    
    struct person {
        char *name;
        unsigned age;
    };
    
    typedef struct employee Employee;
    
    struct employee {
        Person p;
        double salary;
    };
    
    int main(void)
    {
        Employee ee = {
            { .name = "Michael", .age = 37 },
            .salary = 100.0
        };
        
        assert(strcmp(ee.p.name, "Michael") == 0);
        assert(ee.p.age == 37);
        assert(ee.salary == 100.0);
    
        return 0;
    }
    

    但結構內不能嵌入同一個結構,需注意。

    儲存結構的陣列

    由於結構視為一個型別,我們可以用陣列來儲存多個結構,如下例:

    #include <assert.h>
    #include <stddef.h>
    #include <stdio.h>
    
    typedef struct point Point;
    
    struct point {
        double x;
        double y;
    };
    
    int main(void)
    {
        Point pts[] = {
            { .x = 0.0, .y = 0.0 },
            { .x = 1.0, .y = 2.0 },
            { .x = 3.0, .y = 4.0 }
        };
        
        for (size_t i = 0; i < 3; i++) {
            printf("(%.2f, %.2f)\n", pts[i].x, pts[i].y);
        }
    
        return 0;
    }
    
    comments powered by Disqus