2014年3月14日 星期五

C 語言 結構-宣告、變數及指標 / C language struct declare, struct variable , struct pointer

C 語言 結構-宣告、變數及指標

作者:許裕永 Darban

結構是一種 C 語言提供設計師自行開發新型別的機制,使用時機是設計師需要把一個以上的資料群組成一個單位時。假如程式中要儲存許多位學生的資料,而每一位學生都擁有學號、姓名、性別及5科成績的資料。此時,利用結構把每一位學生的資料群組成一個單位,便是相當適合的使用時機。

>_< 宣告結構
基本語法:
struct Identify
{
  Members;
};

struct ->是宣告及使用結構時必要的關鍵字。
Identify ->由開發者自己取的名字,就如同變數或函式名稱。
Members ->任意個合法的型別宣告的變數、陣列或指標。
; ->結構宣告必須以 ‘;’ 結束

Example:

struct Student
{
        char id[6];
        char name[21];
        int sex;
        int score[5];
};

大括號中只接受成員的宣告,不接受指派。

>_< 結構變數
用已宣告的結構為型別宣告的變數,稱之為結構變數。
1.          宣告結構變數
A.         宣告結構後宣告
Example :

struct Student
{
        char id[6];
        char name[21];
        int sex;
        int score[5];
};

int main(int argc, char *argv[]) {
        struct Student s,s2;
        struct Student s_array[5];
        return 0;
}
如同一般型別,可以宣告變數或陣列。

B.         宣告結構時宣告

Example :

struct Student
{
        char id[6];
        char name[21];
        int sex;
        int score[5];
}t,t2,t_array[5];

可以在結構宣告敍述結束的 ‘;’ 前,宣告變數名稱。

2.          指派結構變數的成員
A.         宣告結構後,宣告結構變數時指派

Example:

struct Student
{
        char id[6];
        char name[21];
        int sex;
        int score[5];
};

int main(int argc, char *argv[]) {
       
        struct Student s ={"S0001","Darban Hsu",1,{90,94,90,85,95}},s2;
        struct Student s_array[5]={
        {"S0003"," Tom Hanks ",1,{100,80,90,90,89}},
        {"S0004"," Derek Jeter ",1,{90,88,95,91,80}}
        };
        return 0;
}

宣告變數或陣列時,以一組大括號指派一個群組的資料。資料的順序必須吻合成員的宣告順序。

B.         宣告結構時,宣告結構變數時指派

Example:

struct Student
{
        char id[6];
        char name[21];
        int sex;
        int score[5];
}t={"S0001","Darban Hsu",1,{90,94,90,85,95}},t2,
t_array[5]={
        {"S0003"," Tom Hanks ",1,{100,80,90,90,89}},
        {"S0004"," Derek Jeter ",1,{90,88,95,91,80}}
};

這是合法的,是有必要把程式碼搞成這樣嗎???????

3.          存取結構變數的成員
在宣告敍述之後,可以用成員存取運算符號 ‘.’ 存取結構變數的成員。

struct Student
{
        char id[6];
        char name[21];
        int sex;
        int score[5];
};

int main(int argc, char *argv[]) {
       
        struct Student s ={"S0001","Darban Hsu",1,{90,94,90,85,95}},s2;
        struct Student s_array[5]={
        {"S0003","Tom Hanks ",1,{100,80,90,90,89}},
        {"S0004","Derek Jeter ",1,{90,88,95,91,80}}
        };

       
        strcpy(s2.id,"S0002");
        strcpy(s2.name,"Jennifer Aniston");
        s2.sex = 0;
        s2.score[0]= 99;
        s2.score[1]= 89;
        s2.score[2]= 79;
        s2.score[3]= 98;
        s2.score[4]= 96;

        printf("%s->%d\n",s.name,s.score[2]);
        printf("%s->%d\n",s2.name,s2.score[2]);
        printf("%s->%d\n",s_array[0].name,s_array[0].score[2]);

        return 0;
}

|) 在宣告敍述之外,不可以用大括號一次指派所有成員。
|) 文字不可以用 ‘=’ 指派,必須用 strcpy 請記得 include <string.h>

4.          以結構變數為參數

Example A:

struct Student
{
        char id[6];
        char name[21];
        int sex;
        int score[5];
};
void showInfo(struct Student);

void showInfo(struct Student s)
{
        double total=0;
        int index;
        for(index = 0 ;index < 5; index++)
        {
                total += s.score[index];
        }
       
        printf("%s / %s : %.2f \n", s.id, s.name, total/5);
}

int main(int argc, char *argv[]) {
       
        struct Student s ={"S0001","Darban Hsu",1,{90,94,90,85,95}},s2;
        struct Student s_array[5]={
        {"S0003","Tom Hanks ",1,{100,80,90,90,89}},
        {"S0004","Derek Jeter ",1,{90,88,95,91,80}}
        };

       
        strcpy(s2.id,"S0002");
        strcpy(s2.name,"Jennifer Aniston");
        s2.sex = 0;
        s2.score[0]= 99;
        s2.score[1]= 89;
        s2.score[2]= 79;
        s2.score[3]= 98;
        s2.score[4]= 96;

        showInfo(s);
        showInfo(s2);

        return 0;
}

Example B :


struct Student
{
        char id[6];
        char name[21];
        int sex;
        int score[5];
};
void showInfo(struct Student);
void changeScore(struct Student);

void showInfo(struct Student s)
{
        double total=0;
        int index;
        for(index = 0 ;index < 5; index++)
        {
                total += s.score[index];
        }
       
        printf("%s / %s : %.2f \n", s.id, s.name, total/5);
}
void changeScore(struct Student s)
{
        int index;
        for(index = 0 ;index < 5; index++)
        {
                s.score[index] = 0;
        }     
}


int main(int argc, char *argv[]) {
       
        struct Student s ={"S0001","Darban Hsu",1,{90,94,90,85,95}},s2;
        struct Student s_array[5]={
        {"S0003","Tom Hanks ",1,{100,80,90,90,89}},
        {"S0004","Derek Jeter ",1,{90,88,95,91,80}}
        };

       
        strcpy(s2.id,"S0002");
        strcpy(s2.name,"Jennifer Aniston");
        s2.sex = 0;
        s2.score[0]= 99;
        s2.score[1]= 89;
        s2.score[2]= 79;
        s2.score[3]= 98;
        s2.score[4]= 96;

        changeScore(s);
        changeScore(s2);

        showInfo(s);
        showInfo(s2);

        return 0;
}

Example B 中的 changeScore 試圖要修改參數的 score 陣列的值為 0 ,結果是失敗的。因為以結構變數為參數,是傳值呼叫;也就是說執行器是複製一份 main 中的結構變數 s 的資料群組指派給 changeScore 的參數 s。所以在 changeScore 中的 s 的運算跟 main 中的 s 是無關的

>_< 結構指標
以結構為型別宣告的指構,稱之為結構指標。
1.          宣告結構指標
A.         宣告結構後宣告
Example :

struct Student
{
        char id[6];
        char name[21];
        int sex;
        int score[5];
};

int main(int argc, char *argv[]) {
        struct Student* s;
        return 0;
}
如同一般型別,在型別後加 ‘*’

B.         宣告結構時宣告

Example :

struct Student
{
        char id[6];
        char name[21];
        int sex;
        int score[5];
}*t;

可以在結構宣告敍述結束的 ‘;’ 前宣告指標名稱, ‘*’ 加在指標名稱前。

2.          動態配置記憶體空間
結構變數在宣告時,執行環境便依結構的宣告內容配置適當的記憶體空間。但指標必須透過 malloc() 動態配置,雖然多一個步驟,但可以透過 free() 釋放不需要的記憶體空間

Example :

struct Student
{
        char id[6];
        char name[21];
        int sex;
        int score[5];
} ;

int main(int argc, char *argv[]) {
       
        struct Student* pointer_s = (struct Student*)malloc(sizeof(struct Student));
    struct Student* pointer_t;;
pointer_t = (struct Student*)malloc(sizeof(struct Student));
        return 0;
}

3.          存取結構變數的成員
在動態配置記憶體之後,可以用指標成員存取運算符號 ‘->’ 存取結構指標的成員。

Example :

struct Student
{
        char id[6];
        char name[21];
        int sex;
        int score[5];
} ;
int main(int argc, char *argv[]) {
       
        struct Student* pointer_s = (struct Student*)malloc(sizeof(struct Student));
        strcpy(pointer_s->id, "S0001");
        strcpy(pointer_s->name, "Darban Hsu");
        pointer_s->sex = 1;
        pointer_s->score[0] = 98;
        pointer_s->score[1] = 96;
        pointer_s->score[2] = 89;
        pointer_s->score[3] = 86;
        pointer_s->score[4] = 94;
       
        printf("%s : %s", pointer_s->id, pointer_s->name);
       
        return 0;
}

結構指標的成員的值,不可以用大括號做一次性的指派。

4.          以結構指標為參數

Example A:

struct Student
{
        char id[6];
        char name[21];
        int sex;
        int score[5];
} ;

void showInfo(struct Student*);

void showInfo(struct Student* pointer_s)
{
        double total=0;
        int index;
        for(index = 0 ;index < 5; index++)
        {
                total += pointer_s->score[index];
        }
       
        printf("%s / %s : %.2f \n", pointer_s->id, pointer_s->name, total/5);
}
int main(int argc, char *argv[]) {
       
        struct Student* pointer_s = (struct Student*)malloc(sizeof(struct Student));
        strcpy(pointer_s->id, "S0001");
        strcpy(pointer_s->name, "Darban Hsu");
        pointer_s->sex = 1;
        pointer_s->score[0] = 98;
        pointer_s->score[1] = 96;
        pointer_s->score[2] = 89;
        pointer_s->score[3] = 86;
        pointer_s->score[4] = 94;
       
        showInfo(pointer_s);
       
        return 0;
}

Example B :

struct Student
{
        char id[6];
        char name[21];
        int sex;
        int score[5];
} ;

void showInfo(struct Student*);
void changeScore(struct Student*);


void showInfo(struct Student* pointer_s)
{
        double total=0;
        int index;
        for(index = 0 ;index < 5; index++)
        {
                total += pointer_s->score[index];
        }
       
        printf("%s / %s : %.2f \n", pointer_s->id, pointer_s->name, total/5);
}
void changeScore(struct Student* pointer_s)
{
        int index;
        for(index = 0 ;index < 5; index++)
        {
                pointer_s->score[index] = 0;
        }     
}
int main(int argc, char *argv[]) {
       
        struct Student* pointer_s = (struct Student*)malloc(sizeof(struct Student));
        strcpy(pointer_s->id, "S0001");
        strcpy(pointer_s->name, "Darban Hsu");
        pointer_s->sex = 1;
        pointer_s->score[0] = 98;
        pointer_s->score[1] = 96;
        pointer_s->score[2] = 89;
        pointer_s->score[3] = 86;
        pointer_s->score[4] = 94;
       
        changeScore(pointer_s);
        showInfo(pointer_s);
       
        return 0;
}

Example B 中的 changeScore 成功的修改了參數的 score 陣列的值為 0。因為以結構指標為參數,是傳址呼叫;也就是說執行器是複製一份 main 中的結構指標 pointer_s 儲存的記憶體位址,指派給 changeScore 的參數 pointer_s 。所以在 changeScore 中的pointer_s main 中的pointer_s 是存取的是同一群資料群組 ( 記憶體叢集 )


在開發大型專案時,妥善的利用結構指標,可以避免大量資料的複製,有效的活用記憶體。

沒有留言:

張貼留言