1. 程式人生 > 實用技巧 >[C/C++]詳解結構體

[C/C++]詳解結構體

引子

設計程式時,最重要的步驟之一就是選擇表示資料的方法。在許多情況下,簡單變數甚至是陣列還不夠。為此,C提供了結構變數(structure variable)提高表示資料的能力,它能夠創造新的形式。

建立結構體宣告

小栗子

需求:需要列印一份圖書目錄。裡面包含每本書的各種資訊:書名、作者、出版社、版權日期和價格。其中一些元素(例如書名和作者)可以儲存在字元陣列中,其他專案需要一個int或者float。如果使用5哥不同的陣列分別記錄每一項都比較繁瑣,尤其是要建立多份列表:一份按書名排序、一份按作者排序、一份按照價格排序等。如果能把圖書目錄的資訊都包含在一個數組裡更好,其中每個元素包含一本書的相關資訊。

因此,就需要一種既能包含字串也能包含數字的資料形式,而且還要保持各資訊的獨立。結構體就滿足這種情況下的需求。

struct Book { /* 結構體模板:標記為Book (我們通常使用首字母大寫的方式來標識結構體) */
    char title[128]; // 成員 or 欄位
    char author[40];
    char publisher[256];
    int date;
    float price;
}
​
int main (void) {
    struct Book book; /* 把book宣告為一個Book型別的變數 */
    printf("請輸入書名:");
    scanf("%s", book.title);
    printf("請輸入作者:");
    scanf("%s", book.author);
    printf("請輸入出版社:");
    scanf("%s", book.publisher);
    printf("請輸入出版日期:");
    scanf("%d", book.date);
    printf("請輸入價格:");
    scanf("%f", book.price);
    
    return 0;
}
​
// Output
請輸入書名:《C Primer Plus》
請輸入作者:Stephen Prata
請輸入出版社:人民郵電出版社
請輸入出版日期:201604
請輸入價格:59.4

建立結構宣告

結構宣告(structure declaration)描述了一個結構的組織布局。宣告類似下面這樣:

struct Book {
    char title[128];
    char author[40];
    float price;
}

該宣告描述了一個由兩個字元陣列和一個float型別變數組成的結構。該宣告並未建立實際的資料物件,只描述了該物件由什麼組成。

分析下,首先是關鍵字struct,它表明跟在其後的是一個結構,後面是一個標記 (例子為Book),我們可以使用該標記引用該結構。所以,我們可以在後面的程式中這樣宣告:

struct Book book1;

這把book1宣告為一個使用Book結構佈局的結構變數。

在結構宣告中,用一對花括號括起來的是結構成員列表。每個成員都用自己的宣告來描述。例如,title部分就是一個內涵128個元素的char型別的陣列。成員可以是任意一種C的資料型別,甚至可以是其他結構體。右花括號後面的分號是宣告所必需的,表示結構佈局定義結束。可以把這個宣告放在所有函式的外部,也可以放在一個函式定義的內部。如果把結構宣告置於一個函式的內部,它的標記就只限於該函式內部使用。如果置於外部,那麼該宣告之後的所有函式都能使用標記。

定義結構變數

結構有兩層含義。一層含義是“結構佈局”,結構佈局告訴編譯器如何表示資料,但是它並未讓編譯器為資料分配空間。下一步是建立一個結構變數,即是結構的另一層含義。

struct Book book1; // 建立結構變數

初始化結構體

初始化變數和陣列如下:

int count = 0;

int array[7] = {0, 1, 2, 3, 4, 5, 6};

結構變數也可以像這樣進行初始化,初始化一個結構變數與初始化陣列的語法類似:

struct Book book1 = {
    "C Primer Plus",
    "Stephen Prata",
    59.4
};

我們使用在一對花括號中括起來的初始化列表進行初始化,各初始化項用逗號分隔。因此,title成員可以被初始化為一個字串,price可以被初始化為一個數字。為了讓初始化項與結構中各成員的關聯更加明顯,我們讓每個成員的初始化項都獨佔一樣。這樣做只是為了提高程式碼的可讀性,對編譯器而言,只需要用逗號分隔各成員的初始化項即可。

訪問結構體成員

結構類似於一個“超級陣列”,這個超級陣列中,可以是一個元素為char型別,下一個元素為float型別,下一個元素為int陣列。可以通過陣列下標單獨訪問陣列中的個元素,那麼,如何訪問結構中的成員?使用結構成員運算子 點 (.) 訪問結構中的成員。例如,book1.price即訪問book1的price元素。可以像使用任何float型別變數那樣使用book1.price。與此類似,可以像使用字元陣列那樣使用 book1.title。

本質上,.title、.author和.price的作用相當於是Book結構的下標。

所以在初始化結構體變數時,也可以指定成員:

struct Book book1 = {.price = 59.4};

既然已經是指定成員賦值了,那麼就不用再考慮順序:

struct Book book1 = {
    .price = 59.4,
    .title = "C Primer Plus",
    .author = "Stephen Prata"
}