2023年5月24日 星期三

C/C++ 學習筆記 : 結構

結構 (structure) 是將數個相關的資料類型 (稱為欄位或成員) 集結起來組成一個衍生的資料類型, 讓程式設計者可以依據需要自訂資料類型. 結構裡面的欄位可以是同質的 (全部欄位之類型相同) 或異質的 (包含不同類型), 而且欄位也可以是另一個結構 (即巢狀結構). 

例如公司的產品, 可以用包含型號 (字串), 品名 (字串), 與價格 (整數) 這三個欄位組成的結構來儲存; 好友通訊錄可以用包含姓名 (字串), 電話 (字串), 與生日 (字串) 等類型組成之結構來表示. 結構可讓資料的儲存更有系統. 


1. 定義結構 : 

C/C++ 使用 struct 關鍵字來定義結構, 語法如下 :

struct 結構名稱 {   
    資料類型 欄位名稱1;   
    資料類型 欄位名稱2;   
    ....   
    };    

注意, 每個欄位宣告後要用分號結束; 結尾大括號後面也要用分號結束. 定義一個結構就是在描述此新的資料型態是如何組成的, 它的成員可由既有的基本資料型態組成, 例如數值, 字串, 陣列, 指標, 甚至是另一個結構 (即巢狀結構, 結構裡面的成員是另一個結構). 其次, 結構的定義可以寫在 main() 裡面 (其他函式不可用), 也可以寫在 main() 外面 (其他函式可用).

例如定義一個記錄學生成績的結構 :

struct score {
    char name[10];
    int chinese;
    int english;
    int math;
    int nature;
    }

C++ 可以匯入 string 函式庫後使用 string 類型 : 

struct score {
    string name;
    int chinese;
    int english;
    int math;
    int nature;
    }


2. 結構變數的宣告與賦值 : 

定義一個結構後, 即可使用下列語法宣告結構變數 :

struct 結構名稱 結構變數名稱;      

以上面定義的 score 結構為例宣告兩個結構變數 : 

sctruc score score1, score2;       //宣告了兩個結構變數 score1, scroe2

但這兩個變數目前內容是空的, 賦值的方式是透過小數點符號取得欄位, 對於數值欄位 (整數與浮點數) 而言, 直接用 = 運算子將欄位值指派給該欄位即可, 但字串欄位則必須匯入 string 函式庫後使用 strcpy() 函式來賦值, 例如 :

strcpy(score1.name, "Tony");
score1.chinese=90;
score1.english=87;
score1.math=77;
score1.nature=92;

也可以用陣列的大括弧來賦值, 裡面的值一一對應到宣告結構時之順序, 例如 : 

struct score score2={"Amy", 98, 91, 56, 65}

使用此方式用不到 strcpy() 複製字串到欄位裏, 所以就不需要匯入 string 函式庫了. 結構成員的取值方式一律使用小數點符號與欄位名稱,  例如 score1.name, score2.nature 等. 如果要修改欄位內容, 除了字串需使用 strcpy() 外, 數值可直接用指派運算子 '=' 直接修改. 

下面範例中宣告了兩個結構變數 score1 與 score2, 分別用宣告後再賦值與宣告同時賦值兩種方式來儲存資料 : 

/* 建立結構和顯示結構內容 test01.c */
#include <stdio.h>
#include <string.h>

struct score {  //定義結構
  char name[10];
  int chinese;
  int english;
  int math;
  int nature;
  };

int main() {
  /* 宣告結構變數score1並使用.賦值 */
  struct score score1;   
  strcpy(score1.name, "Tony");
  score1.chinese=90;
  score1.english=87;
  score1.math=77;
  score1.nature=92;
  /* 顯示結構score1資料 */
  printf("結構score1的內容:\n");
  printf("姓名: %s\n", score1.name);
  printf("國文: %d\n", score1.chinese);
  printf("英文: %d\n", score1.english);
  printf("數學: %d\n", score1.math);
  printf("自然: %d\n", score1.nature);   
  /* 宣告結構變數score2並使用{}賦值 */
  struct score score2={"Amy", 98, 91, 56, 65); 
  /* 顯示結構score2資料 */
  printf("結構score2的內容:\n");
  printf("姓名: %s\n", score2.name);
  printf("國文: %d\n", score2.chinese);
  printf("英文: %d\n", score2.english);
  printf("數學: %d\n", score2.math);
  printf("自然: %d\n", score2.nature);   
  return 0;
  }

將此程式貼到線上編譯器 onlinGDB 執行結果如下 : 

結構score1的內容:
姓名: Tony
國文: 90
英文: 87
數學: 77
自然: 92
結構score2的內容:
姓名: Amy
國文: 98
英文: 91
數學: 56
自然: 65


3. 結構陣列 : 

陣列的元素為結構變數時, 此陣列變數稱為結構陣列, 其元素為在記憶體連續空間中的結構變數資料, 這與宣告一些相同定義之結構變數不同 (可能會放在不連續空間).  

結構陣列變數宣告方式如下 : 

struct 結構名稱 結構陣列名稱[長度];     

在此之前要先用 struct 關鍵字宣告一個結構, 例如 :

struct score {  //定義結構
  char name[10];
  int chinese;
  int english;
  int math;
  int nature;
  }; 

然後宣告含有兩個元素的結構陣列變數 scores[] : 

struct score scores[2];

注意, 給每一個元素賦值時不可以用 {}  指派給元素 : 

scores[0]={"Tony", 90, 87, 77, 92};
scores[1]={"Amy", 98, 91, 56, 65}; 

這種包含字串地內容要在宣告時同時賦值 :

struct score scores[2]={{"Tony", 90, 87, 77, 92}, {"Amy", 98, 91, 56, 65}}

完整範例程式如下 : 

/* 建立結構陣列和顯示其內容 : test02.c */
#include <stdio.h>
#include <string.h>

struct score {  //定義結構
  char name[10];
  int chinese;
  int english;
  int math;
  int nature;
  };

int main() {
  /* 宣告結構陣列變數scores並賦值 */
  struct score scores[2];   //宣告結構陣列變數
  strcpy(scores[0].name, "Tony");    //字串要用 strcpy() 賦值
  scores[0].chinese=90;
  scores[0].english=87;
  scores[0].math=77;
  scores[0].nature=92;
  strcpy(scores[0].name, "Amy");    //字串要用 strcpy() 賦值
  scores[1].chinese=98;
  scores[1].english=91;
  scores[1].math=56;
  scores[1].nature=65; 
  /* 顯示結構變數scores[0]資料 */
  printf("結構score[0]的內容:\n");
  printf("姓名: %s\n", scores[0].name);
  printf("國文: %d\n", scores[0].chinese);
  printf("英文: %d\n", scores[0].english);
  printf("數學: %d\n", scores[0].math);
  printf("自然: %d\n", scores[0].nature);   
  /* 顯示結構變數scores[1]資料 */
  printf("結構score[1]的內容:\n");
  printf("姓名: %s\n", scores[1].name);
  printf("國文: %d\n", scores[1].chinese);
  printf("英文: %d\n", scores[1].english);
  printf("數學: %d\n", scores[1].math);
  printf("自然: %d\n", scores[1].nature);  
  return 0;
  }

使用線上編譯器 onlinGDB 執行結果如下 :  

結構score[0]的內容:
姓名: Amy
國文: 90
英文: 87
數學: 77
自然: 92
結構score[1]的內容:
姓名: 
國文: 98
英文: 91
數學: 56
自然: 65

既然是陣列, 可以用迴圈讓程式更簡潔 : 

/* 建立結構陣列和顯示其內容 : test03.c */
#include <stdio.h>
#include <string.h>

struct score {  //定義結構
  char name[10];
  int chinese;
  int english;
  int math;
  int nature;
  };

int main() {
  /* 宣告結構陣列變數scores並賦值 */
  struct score scores[2];   //宣告結構陣列變數
  strcpy(scores[0].name, "Tony");    //字串要用 strcpy() 賦值
  scores[0].chinese=90;
  scores[0].english=87;
  scores[0].math=77;
  scores[0].nature=92;
  strcpy(scores[0].name, "Amy");    //字串要用 strcpy() 賦值
  scores[1].chinese=98;
  scores[1].english=91;
  scores[1].math=56;
  scores[1].nature=65; 
  /* 顯示結構變數資料 */
  int i;
  for (i=0; i<2; i++) {
    printf("結構score[%d]的內容:\n", i);
    printf("姓名: %s\n", scores[i].name);
    printf("國文: %d\n", scores[i].chinese);
    printf("英文: %d\n", scores[i].english);
    printf("數學: %d\n", scores[i].math);
    printf("自然: %d\n", scores[i].nature);   
    }  
  return 0;
  }


4. 結構指標 : 

指標可以指向任何類型的資料, 指向結構開始位址的指標稱為結構指標, 只要在宣告結構變數時, 在變數名稱前面加個星號, 此指標所存之位址即指向一個結構. 

結構指標語法如下 :

struct *結構指標名稱;    

首先宣告一個結構 score :

struct score {  //定義結構
  char name[10];
  int chinese;
  int english;
  int math;
  int nature;
  }; 

接著宣告一個結構變數 score1 :

struct score score1={"Tony", 90, 87, 77, 92};

然後宣告一個結構指標 ptr, 並將結構 score1 的位址指派給 *ptr :

struct score *ptr=&score1;

這樣結構指標 ptr 就指向結構 score1 了. 

存取結構指標所指向的內容有兩種做法 :
  • 使用指標所指內容搭配點運算子 : (*ptr).欄位名稱
    由於存取欄位的小數點運算子比指標運算子優先權高, 因此要先用括號將指標內容括起來, 例如要用 (*ptr).name 而非 *ptr.name (這會編譯錯誤).
  • 使用指標名稱搭配 -> 運算子 : ptr->欄位名稱
    注意, 使用 -> 時要用指標名稱, 不是所指向的內容 (*ptr).
下面範例指標內容搭配點運算子來存取結構之欄位 :

/* 建立結構陣列和顯示其內容 : test04.c */
#include <stdio.h>

struct score {  //定義結構
  char name[10];
  int chinese;
  int english;
  int math;
  int nature;
  };

int main() {
  /* 宣告結構變數score1並賦值 */
  struct score score1={"Tony", 90, 87, 77, 92}; 
  struct score *ptr=&score1;
  /* 顯示結構變數score1資料 */
  printf("結構score1的內容:\n");
  printf("姓名: %s\n", score1.name);
  printf("國文: %d\n", score1.chinese);
  printf("英文: %d\n", score1.english);
  printf("數學: %d\n", score1.math);
  printf("自然: %d\n", score1.nature); 
  /* 使用指標所指內容(*ptr)搭配點運算子來顯示結構資料 */
  printf("結構指標*ptr的內容:\n");  
  printf("姓名: %s\n", (*ptr).name);
  printf("國文: %d\n", (*ptr).chinese);
  printf("英文: %d\n", (*ptr).english);
  printf("數學: %d\n", (*ptr).math);
  printf("自然: %d\n", (*ptr).nature);      
  return 0; 
  }

此例使用指標內容 (*ptr) 搭配點運算子來存取結構欄位. 

用線上編譯器 onlinGDB 執行結果如下 :

結構score1的內容:
姓名: Tony
國文: 90
英文: 87
數學: 77
自然: 92
結構指標*ptr的內容:
姓名: Tony
國文: 90
英文: 87
數學: 77
自然: 92

可見由於 ptr 指向 score1, 因此兩個內容完全一樣, 更改 (*ptr) 的任一欄位同時也會改到 score1 的欄位內容. 

下面範例指標名稱搭配 -> 運算子來存取結構之欄位 :

/* 建立結構陣列和顯示其內容 : test05.c */
#include <stdio.h>

struct score {  //定義結構
  char name[10];
  int chinese;
  int english;
  int math;
  int nature;
  };

int main() {
  /* 宣告結構變數score1並賦值 */
  struct score score1={"Tony", 90, 87, 77, 92}; 
  struct score *ptr=&score1;
  /* 顯示結構變數score1資料 */
  printf("結構score1的內容:\n");
  printf("姓名: %s\n", score1.name);
  printf("國文: %d\n", score1.chinese);
  printf("英文: %d\n", score1.english);
  printf("數學: %d\n", score1.math);
  printf("自然: %d\n", score1.nature); 
  /* 使用指標名稱搭配 -> 運算子顯示結構資料 */
  printf("結構指標*ptr的內容:\n");  
  printf("姓名: %s\n", ptr->name);
  printf("國文: %d\n", ptr->chinese);
  printf("英文: %d\n", ptr->english);
  printf("數學: %d\n", ptr->math);
  printf("自然: %d\n", ptr->nature);       
  return 0;
  }

執行結果與前面範例一樣. 


5. 巢狀結構 : 

結構的成員是另一個結構稱為巢狀結構, 語法如下 : 

struct 結構名稱1 {   
    資料類型 欄位名稱1;   
    資料類型 欄位名稱2;   
    ....   
    };   
struc 結構名稱2 {   
    資料類型 欄位名稱1;   
    struct 結構名稱1 結構變數名稱;   
    ....   
    }; 

例如 : 

struct name {  //定義結構 name
  char first_name[10];
  char last_name[10];
  };

struct score {  //定義結構 score
  struct name student_name;    // 此欄位為另一個結構 name
  int chinese;
  int english;
  int math;
  int nature;
  };

此處定義了兩個結構 name 與 score, 其中 score 的第一個成員是 name 結構, 形成巢狀結構. 接著宣告兩個 score 結構變數 score1 與 score2 :

struct score score1={{"Tony", "Huang"}, 90, 87, 77, 92};
struct score score2={{"Amy", "Chen"}, 98, 91, 56, 65); 

因為第一個成員是另一個結構 name, 因此要用 {} 賦值. 存取內層結構 name 的成員時必須使用兩層的點運算子, 例如 :

score1.student_name.first_name  
score1.student_name.last_name 
score2.student_name.first_name  
score2.student_name.last_name 

完整範例如下 :

/* 建立巢狀結構和顯示其內容 : test06.c */
#include <stdio.h>

struct name {  //定義結構 name
  char first_name[10];
  char last_name[10];
  };

struct score {  //定義結構 score
  struct name student_name;  
  int chinese;
  int english;
  int math;
  int nature;
  };

int main() {
  /* 宣告結構變數score1並賦值 */
  struct score score1={{"Tony", "Huang"}, 90, 87, 77, 92};
  struct score score2={{"Amy", "Chen"}, 98, 91, 56, 65}; 
  /* 顯示結構變數score1資料 */
  printf("結構score1的內容:\n");
  printf("姓名: %s %s\n", score1.student_name.first_name, score1.student_name.last_name);
  printf("國文: %d\n", score1.chinese);
  printf("英文: %d\n", score1.english);
  printf("數學: %d\n", score1.math);
  printf("自然: %d\n", score1.nature); 
  /* 顯示結構變數score1資料 */
  printf("結構score2的內容:\n");
  printf("姓名: %s %s\n", score2.student_name.first_name, score1.student_name.last_name);
  printf("國文: %d\n", score2.chinese);
  printf("英文: %d\n", score2.english);
  printf("數學: %d\n", score2.math);
  printf("自然: %d\n", score2.nature);   
  return 0;
  }

使用線上編譯器 onlinGDB 執行結果如下 :  

結構score1的內容:
姓名: Tony Huang
國文: 90
英文: 87
數學: 77
自然: 92
結構score2的內容:
姓名: Amy Huang
國文: 98
英文: 91
數學: 56
自然: 65


6. 將結構傳入函式 : 

結構作為一種自訂的資料型態, 當然也可以當引數傳給函式, 但要注意, 直接將結構傳入函式中時使用的是傳值呼叫, 亦即函式接收到的參數只是一個副本, 在函式內對此副本的存取不會影響到外部的結構內容, 例如 :

/* 將結構傳入函式和顯示其內容 : test07.c */
#include <stdio.h>
#include <string.h>

struct score {  //定義結構
  char name[10];
  int chinese;
  int english;
  int math;
  int nature;
  };

void set_score(struct score s);     // 函式原型宣告必須在結構定義之後

int main() {
  /* 宣告結構變數score1並賦值 */
  struct score score1={"Tony", 90, 87, 77, 92};
  set_score(score1);   // 這是傳值呼叫
  /* 顯示函式外結構變數score1資料 */
  printf("函式外結構score1的內容:\n");
  printf("姓名: %s\n", score1.name);
  printf("國文: %d\n", score1.chinese);
  printf("英文: %d\n", score1.english);
  printf("數學: %d\n", score1.math);
  printf("自然: %d\n", score1.nature);   
  return 0;
  }

void set_score(struct score s) {
  /* 設定結構變數s資料 */
  strcpy(s.name, "Amy");
  s.chinese=98;
  s.english=91;
  s.math=56;
  s.nature=65;
  /* 顯示函式內結構變數s資料 */
  printf("函式內結構變數s的內容:\n");
  printf("姓名: %s\n", s.name);
  printf("國文: %d\n", s.chinese);
  printf("英文: %d\n", s.english);
  printf("數學: %d\n", s.math);
  printf("自然: %d\n", s.nature); 
  }

此例宣告了一個結構變數 score1, 然後將其作為引數傳入函式 set_score() 中, 由於直接將結構傳入函式為傳值呼叫, 傳入之參數為結構之副本, 故於函式內設定該結構副本之欄位對函式外部的結構毫無影響.

使用線上編譯器 onlinGDB 執行結果如下 : 

函式內結構變數s的內容:
姓名: Amy
國文: 98
英文: 91
數學: 56
自然: 65
函式外結構score1的內容:
姓名: Tony
國文: 90
英文: 87
數學: 77
自然: 92

可見函式內的結構雖然被改成 Amy 的成績, 但函式外的結構仍然是 Tony 的成績. 如果要在函式內更改函式外的結構變數內容, 必須使用結構指標, 例如 :

/* 將結構指標傳入函式和顯示其內容 : test08.c */
#include <stdio.h>
#include <string.h>

struct score {  //定義結構
  char name[10];
  int chinese;
  int english;
  int math;
  int nature;
  };

void set_score(struct score *ptr);

int main() {
  /* 宣告結構變數score1並賦值 */
  struct score score1={"Tony", 90, 87, 77, 92};
  struct score *ptr;   // 宣告結構指標變數
  ptr=&score1;         // 取得score1位址指定給指標ptr
  set_score(ptr);       // 這是傳址呼叫
  /* 顯示函式外結構變數score1資料 */
  printf("函式外結構score1的內容:\n");
  printf("姓名: %s\n", score1.name);
  printf("國文: %d\n", score1.chinese);
  printf("英文: %d\n", score1.english);
  printf("數學: %d\n", score1.math);
  printf("自然: %d\n", score1.nature);   
  return 0;
  }

void set_score(struct score *ptr) {
  /* 設定結構變數s資料 */
  strcpy((*ptr).name, "Amy");
  (*ptr).chinese=98;
  (*ptr).english=91;
  (*ptr).math=56;
  (*ptr).nature=65;
  /* 顯示函式內結構變數s資料 */
  printf("函式內結構變數s的內容:\n");
  printf("姓名: %s\n", (*ptr).name);
  printf("國文: %d\n", (*ptr).chinese);
  printf("英文: %d\n", (*ptr).english);
  printf("數學: %d\n", (*ptr).math);
  printf("自然: %d\n", (*ptr).nature); 
  }

用線上編譯器 onlinGDB 執行結果如下 : 

函式內結構變數s的內容:
姓名: Amy
國文: 98
英文: 91
數學: 56
自然: 65
函式外結構score1的內容:
姓名: Amy
國文: 98
英文: 91
數學: 56
自然: 65

可見由於傳入函式的引數是結構指標, 因此在函式內更改結構內容也就是更改函式外結構變數 score1 的內容, 所以列印的結果完全相同. 如上所述, 也可以使用結構專用的 -> 運算子來存取結構成員, 例如以 ptr->name 取代 (*ptr).name : 

/* 將結構指標傳入函式和顯示其內容 : test09.c */
#include <stdio.h>
#include <string.h>

struct score {  //定義結構
  char name[10];
  int chinese;
  int english;
  int math;
  int nature;
  };

void set_score(struct score *ptr);

int main() {
  /* 宣告結構變數score1並賦值 */
  struct score score1={"Tony", 90, 87, 77, 92};
  struct score *ptr;   // 宣告結構指標變數
  ptr=&score1;         // 取得score1位址指定給指標ptr
  set_score(ptr);      // 這是傳址呼叫
  /* 顯示函式外結構變數score1資料 */
  printf("函式外結構score1的內容:\n");
  printf("姓名: %s\n", score1.name);
  printf("國文: %d\n", score1.chinese);
  printf("英文: %d\n", score1.english);
  printf("數學: %d\n", score1.math);
  printf("自然: %d\n", score1.nature); 
  }

void set_score(struct score *ptr) {
  /* 設定結構變數s資料 */
  strcpy(ptr->name, "Amy");
  ptr->chinese=98;
  ptr->english=91;
  ptr->math=56;
  ptr->nature=65;
  /* 顯示函式內結構變數s資料 */
  printf("函式內結構變數s的內容:\n");
  printf("姓名: %s\n", ptr->name);
  printf("國文: %d\n", ptr->chinese);
  printf("英文: %d\n", ptr->english);
  printf("數學: %d\n", ptr->math);
  printf("自然: %d\n", ptr->nature); 
  }

結果與上面用 (*ptr). 作法結果相同.


7. 用 typedef 定義新資料型態 :    

型態定義關鍵字 typedef 用來為既有之資料型態取別名, 語法如下 :

typedef 原資料型態名稱 新資料型態名稱 

這經常被用在結構這種自訂資料型態上, 可使結構變數之宣告變得較簡短, 不必每次宣告一個結構變數時都要冠上 struct 關鍵字, 例如上面範例中所定義的結構 :

struct score {  //定義結構
  char name[10];
  int chinese;
  int english;
  int math;
  int nature;
  };

當宣告結構變數時必須使用 struct 關鍵字 :

struct score score1, score2;

如果用 typedef 為此結構取一個型態別名 :

typedef struct score myscore;   // 為結構 score 取一個型態別名 myscore

則宣告 score 結構變數時便可直接使用 myscore 型態 :

myscore score1, score2;  

測試範例如下 : 

/* 用typedef為結構取一個別名 : test10.c */
#include <stdio.h>

struct score {  //定義結構
  char name[10];
  int chinese;
  int english;
  int math;
  int nature;
  };

int main() {
  typedef struct score myscore;  //用typedef為結構score取別名myscore
  /* 宣告結構變數score1並賦值 */
  myscore score1={"Tony", 90, 87, 77, 92}; //用myscore宣告結構變數
  struct score score2={"Amy", 98, 91, 56, 65};  //用struct score宣告結構變數
  /* 顯示函式外結構變數score1資料 */
  printf("結構score1的內容:\n");
  printf("姓名: %s\n", score1.name);
  printf("國文: %d\n", score1.chinese);
  printf("英文: %d\n", score1.english);
  printf("數學: %d\n", score1.math);
  printf("自然: %d\n", score1.nature); 
  /* 顯示函式外結構變數score2資料 */
  printf("結構score2的內容:\n");
  printf("姓名: %s\n", score2.name);
  printf("國文: %d\n", score2.chinese);
  printf("英文: %d\n", score2.english);
  printf("數學: %d\n", score2.math);
  printf("自然: %d\n", score2.nature);  
  }

此例用 typedef 為結構 socre 取了一個型態別名 myscore, 然後分別用 myscore 與原始的 struct score 方式宣告了兩個結構變數 score1 與 score2, 顯然用新型態 myscore 較簡短, 以線上編譯器 onlinGDB 執行結果如下 : 

結構score1的內容:
姓名: Tony
國文: 90
英文: 87
數學: 77
自然: 92
結構score2的內容:
姓名: Amy
國文: 98
英文: 91
數學: 56
自然: 65

也可以在定義結構時就用 typedef 為結構取一個型態別名, 語法如下 : 

typedef struct 結構名稱 {   
    資料類型 欄位名稱1;   
    資料類型 欄位名稱2;   
    ....   
    } 新型態名稱;    

例如 : 

typedef struct score {  //定義結構並取一個新型態名稱 myscore
  char name[10];
  int chinese;
  int english;
  int math;
  int nature;
  } myscore;

這樣既可以用原始的 struct score 來宣告結構變數, 也可以用 myscore 來宣告 :

struct score score1;
myscore score2; 

可將上面範例修改為 :

/* 用typedef為結構取一個別名 : test11.c */
#include <stdio.h>

typedef struct score {  //定義結構並取一個新型態名稱
  char name[10];
  int chinese;
  int english;
  int math;
  int nature;
  } myscore;

int main() {
  /* 宣告結構變數score1並賦值 */
  myscore score1={"Tony", 90, 87, 77, 92}; //用myscore宣告結構變數
  struct score score2={"Amy", 98, 91, 56, 65};  //用struct score宣告結構變數
  /* 顯示函式外結構變數score1資料 */
  printf("結構score1的內容:\n");
  printf("姓名: %s\n", score1.name);
  printf("國文: %d\n", score1.chinese);
  printf("英文: %d\n", score1.english);
  printf("數學: %d\n", score1.math);
  printf("自然: %d\n", score1.nature); 
  /* 顯示函式外結構變數score2資料 */
  printf("結構score2的內容:\n");
  printf("姓名: %s\n", score2.name);
  printf("國文: %d\n", score2.chinese);
  printf("英文: %d\n", score2.english);
  printf("數學: %d\n", score2.math);
  printf("自然: %d\n", score2.nature);  
  }
 
執行節果與上一個範例相同.

事實上 typedef 可以用來為任何資料型態取別名, 例如為 int 型態取 integer 別名 : 

typedef int integer;
integer year=2023;

或為 char* 指標取 string 別名 :

typedef char* string; 
string="Hello World!" 

注意, 字串指標要用 char* 而非 *char. 

完整範例如下 : 

/* 用typedef為int與*char取一個別名 : test13.c */
#include <stdio.h>

int main() {
  typedef int integer;       // 為int型別取別名integer
  integer year=2023;         // 用integer宣告整數變數
  printf("%d\n", year);      
  typedef char* string;      // 為*char型別取別名string
  string str="Hello World!"; // 用string宣告字串變數
  printf("%s\n", str);
  return 0;
  }

執行結果如下 : 

2023
Hello World!

沒有留言 :