使用者自定資料型態 - struct

 

  實 習 內 容



1. 練習使用 typedef, struct, 以及 sizeof

2. 存取 struct 型態變數裡的一個欄位

3. 函數輸入 struct 型態參數或是輸出 struct 型態參數

1

練習使用 typedef, struct, 以及 sizeof:

請定義一個新的型態 long_lat_t 來存放經緯度的資料, 這種型態的資料需要有下列欄位: degrees (int 型態), minutes (int 型態), and direction (char 型態的下列字元 'N', 'S', 'E', 或 'W')

同時使用 typedef 以及 struct 敘述:

typedef struct
{
    int degrees;
    int minutes;
    char direction;
} long_lat_t;

請定義 long_lat_t 型態的變數 startpos:

long_lat_t startpos;

請定義有 200 個 long_lat_t 型態元素的陣列變數 positions:

long_lat_t positions[200];

重複上述定義並且 初始化 前三個元素:

long_lat_t positions[200] = {{23, 12, 'N'},
                             {24, 32, 'N'},
                             {120, 15, 'E'}};

請運用 printf 以及 sizeof 印出變數 startpos positions 使用多少個位元組的記憶體:

printf("size of startpos is %d\n", sizeof(startpos));
   或
printf("size of startpos is %d\n", sizeof(long_lat_t));
   或
printf("size of positions is %d\n", sizeof(positions));
   或
printf("size of positions is %d\n", sizeof(long_log_t [200]));

輸出的位元組 (byte) 數和你預期的相同嗎?

注意:

在 C++ 編譯器中,

struct long_lat_t
{
    int degrees;
    int minutes;
    char direction;
};

就已經定義了新的型態 long_lat_t, 不需要再使用 typedef 了

2

存取 struct 型態變數中的欄位:

請使用 scanf 函數由鍵盤讀取 (23, 18, 'N') 資料到 long_lat_t 型態的變數 startpos 中:

scanf("%d%d %c", &startpos.degrees, 
                 &startpos.minutes, 
                 &startpos.direction);
請注意: 運算子 . 的優先順序比運算子 & 高, 所以上面寫法不需要額外的小括號

3

練習使用 結構 (struct) 型態的變數做為函數的輸入參數, 並且回傳一個 結構 (struct) 數值:

請撰寫一個函數, 其輸入參數是一個 long_lat_t 型態的數值, 回傳值也是一個 long_lat_t 型態的數值, 內容是輸入方向的相反方向, 例如輸入 (23, 18, 'N'), 輸出為 (23, 18, 'S') 或是 輸入 (120, 30, 'E'), 輸出為 (120, 30, 'W')

long_lat_t opposite(long_lat_t point)
{
    switch (point.direction)
    {
    case 'N':
        point.direction = 'S';
        break;
    case 'S':
        point.direction = 'N';
        break;
    case 'E':
        point.direction = 'W';
        break;
    case 'W':
        point.direction = 'E';
        break;
    }
    return point;
}

請注意結構型態參數在函數之間傳遞時和基本型態的變數傳遞時是一樣的, 是傳遞數值 (call-by value), 所以在函數裡面接收的參數基本上是原來數值的副本, 在函數裡如果你修改這個副本, 並不會影響到呼叫這個函數用的變數。另外也請注意在回傳一個結構數值時, 整個結構的內容也會完整地由函數裡拷貝到函數的呼叫端, 就算你的結構裡有一個很大的陣列, 使得你的結構佔據很多個位元組, 參數傳遞時還是完整地拷貝整個結構的內容。

4

修改步驟 2 的函數, 使得參數同時具有輸入及輸出的功能:

如果希望在函數中直接修改呼叫程式中結構型態的變數, 可以直接傳遞結構變數的記憶體位址給函數, 如此的參數就會是具有輸出功能的參數

void opposite(long_lat_t *point)
{
    switch (point->direction)
    {
    case 'N':
        point->direction = 'S';
        break;
    case 'S':
        point->direction = 'N';
        break;
    case 'E':
        point->direction = 'W';
        break;
    case 'W':
        point->direction = 'E';
        break;
    }
    return;
}

這個程式片段中 break 敘述可以換成 return 敘述。同時 point->direction 的用法和 (*point).direction 是完全等效的, 可以互相替換, 但是請注意後面這個敘述的小括號是必要的。

5

另外一個使用 結構 (struct) 為輸出參數的函數範例:

請撰寫一個 readPoint 函數, 由鍵盤讀取地球表面一個點的經度和緯度 (各有三個資料欄位: degrees, minutes, 和 direction), 檢查輸入的資料是否在 (24, 59, 'N'), (24, 59, 'S') 及 (110, 0, 'E'), (114, 59, 'E') 之間, 如果是就回傳 1, 否則回傳 0, 並且將輸入的點透過函數的輸出參數回傳給呼叫端

int readPoint(long_lat_t *longitude, long_lat_t *latitude)
{
    printf("Enter degrees, minutes, and direction of the longitude: ");
    scanf("%d%d %c", &longitude->degrees, &longitude->minutes,
                     &longitude->direction);
    if (longitude->direction != 'E') return 0;
    if (longitude->degrees >= 115) return 0;
    if (longitude->degrees < 110) return 0;

    printf("Enter degrees, minutes, and direction of the latitude: ");
    scanf("%d%d %c", &latitude->degrees, &latitude->minutes,
                     &latitude->direction);
    if (latitude->direction == 'N')
        if (latitude->degrees >= 25) return 0;
    elseif (latitude->direction == 'S')
        if (latitude->degrees >= 25) return 0;

    return 1;
}

上面這個程式中你也可以再定義一個新的結構資料型態 point_t: 其中包含兩個long_lat_t 型態的結構欄位, longitude 以及 latitude。

注意: 兩個相同結構型態的變數可以用 = 直接拷貝整個結構的內容, 例如

typedef struct
{
    char name[25];
    int age;
} Data;
Data x = {"Monica", 25};
Data y;
y = x;

6

練習以 結構 (struct) 陣列變數取代平行陣列 (parallel arrays):

平行陣列:

我們可以使用如下的多個陣列來儲存一個班級的成績記錄, 其中每一筆記錄包含學生的 id 號碼以及 gpa 資訊 (grade point average), 不同陣列的第 i 個元素代表同一個學生的多個資料:

int id[50];       /* id numbers */
double gpa[50];   /* grade point average */
使用者自定結構:
typedef struct
{
    int id;
    double gpa;
} student_t;

結構陣列變數:

student_t students[50];

 

計算機程式設計實習 首頁

製作日期: 2012/11/26 by 丁培毅 (Pei-yih Ting)
E-mail: pyting@ntu.edu.tw