結構體和共用體

結構體和共用體

1.結構體

1.1 看一個養貓問題

張老太養了兩隻貓貓:一隻叫小白,今年3歲,白色,還有一隻叫小花,今年100歲,花色,請編寫一個程序,當用戶輸入小貓的名字,就顯示該貓的名字,年齡,顏色。若是用戶輸入的小貓名錯誤,則顯示張老太沒有這隻貓貓編程

1.2 使用傳統技術解決

  • 單獨的定義變量解決
  • 學習完數組,它是一組具備相同類型的數據的集合,在編程中,咱們每每還須要一組類型不一樣的數據,例如貓的名字使用字符串,年齡是int,由於數據類型不一樣,不能用一個數組來存放

1.3 現有技術解決的缺點分析

- 不利於數據的管理和維護,由於自己貓的三個屬性(名字,年齡,顏色)是一個總體,傳統解決方法是將其分解-->結構體



```c
void main(){
    char cat1Name[10]="小白";
    int cat1Age=3;
    char cat1Color[10]="白色";
    
    char *catsName[2]={
        "小白"
        "小花"
    };
    int catsAge[2]{3,100}
}

1.4 結構體與結構體變量的關係示意圖

把全部貓的特徵提取出來---->cat結構體-數據類型(成員 name age color)數組

說明:除了能夠有cat結構體,還能夠有person結構體,有fish結構體等函數

1.5 快速入門--面向對象的方式解決養貓問題

#include<stdio.h>
void main(){
    //分析:
    //1.貓貓有三個成員變量組成
    //2.使用結構體解決
    
    //建立結構體cat
    struct Cat{//結構體名Cat,Cat就是咱們本身構造的一個數據類型
        char *name;//名字,使用指針,指向一個字符串
        int age;
        char *color;
    };
    //使用Cat結構體建立變量
    struct Cat cat1;//cat1就是struct Cat的一個變量
    struct Cat  cat2;//cat2就是struct Cat的一個變量
    //給cat1的各個成員賦值
    cat1.name="小白";
    cat1.age=3;
    cat1.color="白色";
    
    //給cat2的各個成員賦值
    cat2.name="小花";
    cat2.age=100;
    cat2.color="花色";
    
    //輸出兩隻貓的信息
    printf("第一隻貓name=%s age=%d color=%s",cat1.name,cat1.age,cat1.color);
    printf("第二隻貓name=%s age=%d color=%s",cat2.name,cat2.age,cat2.color);
    
    getchar();
}

1.6 結構體和結構體變量的區別和聯繫

  • 結構體是自定義數據類型,表示的是一種數據類型
  • 結構體變量表明一個具體變量
int num1;//int 是數據類型,而num1是一個具體的int變量
struct Cat cat1;//Cat是結構體數據類型,而cat1是一個Cat變量
  • Cat就像一個」模板「,定義出來的結構體變量都含有相同的成員,也能夠將結構體比做圖紙,將結構體變量比做零件,根據同一張圖紙生產出來的零件的特徵都是同樣的

1.8 如何聲明結構體

struct 結構體名稱{//結構體名稱首字母大寫,好比Cat,Person佈局

​ 成員列表;學習

};測試

struct Student{
    char *name;
    int num;
    int age;
    char group;
    float score;
    //成員也能夠是結構體
};

1.9 成員

  • 基本介紹3d

    • 從叫法上看,有些書上稱爲成員,有些書說結構體包含的變量
    • 成員是結構體的一個組成部分,通常是基本數據類型,也能夠是數組,指針,結構體等;好比定義的Cat結構體的int age就是一個成員;
  • 注意事項即細節說明指針

    • 成員聲明語法同變量,實例,數據類型,成員名
    • 字段的類型能夠爲:基本類型,數組或指針,結構體等
  • 在建立結構體變量後,須要給成員賦值,若是沒有賦值就使用可能致使程序異常終止code

#include <stdio.h>
 void main(){
     struct Cat(){//結構體名字建議打字大寫
         char *name;
         int age;
         char *color;   
     };
     struct Cat cat1;//定義了一個結構體變量cat1
     printf("名字=%s 年齡=%d 顏色=%s",cat1.name,cat1.age,cat1.color);
     getchar();
 }
  • 不一樣結構體變量的成員是獨立,互不影響,一個結構體變量的成員更改,不影響另外一個

1.10 建立結構體和結構體變量

  • 方式一:先定義結構體,而後再建立結構體變量
struct Stu{
    char *name;
    int num;
    int age;
    char group;
    float score;
};
struct Stu stu1,stu2;
//定義了兩個變量stu1和stu2,他們都是Stu類型,都由5個成員組成
//注意關鍵字struct不能少
  • 方式二:在定義結構體的同時定義結構體變量
struct Stu{
    char *name;
    int num;
    int age;
    char group;
    float score;
}stu1,stu2;
//在定義結構體Stu的同時,建立了兩個結構體變量stu1和stu2
  • 方式三:若是隻須要stu1,stu2兩個變量,後面不須要再使用結構體數據類型,定義其餘變量,在定義時也能夠不給出結構體名
struct {
    char *name;
    int num;
    int age;
    char group;
    float score;
}stu1,stu2;
stu1.name="tom";
stu1.num=100;
//該結構體數據類型,沒有名,匿名結構體
//stu1和stu2就是該結構體的兩個變量

1.11 成員的獲取和賦值

結構體和數組相似,也是一組數據的集合,總體使用沒有太大的意義,數組使用下標[]獲取單個元素,結構體使用點號。獲取結構體成員的通常格式爲對象

結構體變量名.成員名;

struct {
    char *name;
    int num;
    int age;
    char group;
    float score;
}stu1;
stu1.name="jack";
printf("%s",stu.name);
#include<stdio.h>
void main(){
    struct Student{
        char *name;
        int num;
        int age;
        char group;
        float score;
    }stu1={"賈寶玉",11,18,'B',90.50},stu2={"林黛玉",12,16,'A',100};
    struct Student stu3={
        "林黛玉2",12,16,'A',100
    };//在定義結構體變量時,總體賦值,須要對應
    
    struct Student stu4;
    //stu4={"林黛玉2",12,16,'A',100};//這樣賦值不能夠
    //stu4.name="smith";
    printf("stu1.name=%s",stu1.name);
    printf("stu3.name=%s",stu3.name);
    getcahr();
}

2.結構體應用實例

2.1 步驟

  • 聲明結構體,肯定結構體名
  • 編寫結構體的成員
  • 編寫處理結構體的函數

2.2 案例

//編寫一個Dog結構體,包含name(char[10]),age(int),weight(double)屬性
//編寫一個say函數,返回字符串,信息中包含全部成員值

//在main方法中,建立Dog結構體變量,調用say函數,將調用結果打印輸出

#include<stdio.h>
struct Dog{
    char *name;
    int age;
    double weight;
};
//say 函數,返回字符串,信息中包含全部成員值
char *say(struct Dog dog){
    //將這個信息放入到一個字符串(字符數組)
    static char info[50];
    sprintf(info,"name=%s age=%d weight=%.2f",dog.name,dog.age,dog.weight);
    dog.name="小花";
    return info;
}
void main(){
    //測試
    //定義結構體變量
    struct Dog dog;
    char *info=NULL;
    dog.name="小黃";
    dog.age=1;
    dog.weight=3.4;
    info=say(dog);//結構體變量默認是值傳遞
    printf("小狗信息=%s",info);
    printf("main 小狗信息=%s",dog.name);
    getchar();
}

2.4 景區門票案例

  • 一個景區根據遊人的年齡收取不一樣價格的門票
  • 請根據遊人結構體(Visitor),根據年齡段決定可以購買的門票價格並輸出
  • 規則:年齡>18,門票爲20元,其餘狀況免費
  • 能夠循環從控制檯輸入名字和年齡,打印門票收費狀況,若是名字輸入n,則退出程序
#include<stdio.h>
#include<string.h>

//定義結構體
struct Visitor{
    char name[10];
    int age;
    double pay;//應付票價
};
//編寫函數處理業務
//說明:由於結構體默認是值傳遞,會拷貝一份完整數據,效率較低
//所以,爲了提升效率,咱們直接接收地址
void ticket(struct Visitor* visitor){
    //判斷
    if((*vistor).age>18){
        (*visitor).pay=20;
    }else{
        (*visitor).pay=0;
    }
}
void main(){
    //測試
    //建立結構體變量(建立一個遊客)
    struct Vistor vistor;
    //循環輸入名字和年齡
    while(1){
        printf("請輸入名字:");
        scanf("%s",visitor.name);
        //判斷若是名字輸入n,則退出程序
        if(!strcmp("n",visitor.name)){
            break;
        }
        printf("請輸入遊客年齡");
        scanf("%d",&visitor.age);
        //調用函數ticket,獲取應付的票價
        ticket(&visitor);
        printf("遊客應付票價爲%.2f",visitor.pay);
    }
    printf("退出程序");
    getchar();
    getchar();
}

3.共用體


|

3.2 傳統方式解決

定義結構體,根據人員的職業,使用對應的成員變量

struct Person{
    char name[20];
    int num;
    char sex;
    char profession;
    float score;//學生使用score
    char cousre[20];//老師使用course
};

傳統方式的問題分析:會形成空間的浪費,好比學生只使用score,可是也佔用了course成員的20個字節。

  • 解決方案
    • 作struct Stu和struct Teacher[但若是職業過多,就會對應多個結構體類型,不利於管理]
    • 使用共用體

3.3 基本介紹

  • 共用體(Union)屬於構造類型,它能夠包含多個類型不一樣的成員,和結構體很是相似,可是也有不一樣的地方,共用體有時也被稱爲聯合或者聯合體,定義格式爲

    union 共用體名{

    ​ 成員列表;

    };

  • 結構體和共用體的區別在於:結構體的各個成員會佔用不一樣的內存,互相之間沒有影響;而共用體的全部成員佔用同一段內存,修改一個成員會影響其他全部成員

3.4 快速入門

  • 定義共用體類型和共用體變量的三種方式(和結構體同樣)
union data{
    int n;
    char ch;
    double f;
};
union data a,b,c;
union data{
    int n;
    char ch;
    double f;
}a,b,c;
union{
    int n;
    char ch;
    double f;
}a,b,c;

union data{
    int n;
    char ch;
    short m;
};
void main(){
    union data a;
    pritf("%d,%d",sizeof(a),sizeof(union data));
    a.n=0x40;
    printf("%d,%c,%d",a.n,a.ch,a.m);
    a.ch='9';
    printf("%d,%c,%d",a.n,a.ch,a.m);
    a.n=0x3E25AD54;
    printf("%d,%c,%d",a.n,a.ch.a.m);
}
  • 案例演示
#include<stdio.h>
union data{
    //data就是一個共用體(內存佈局),包含三個成員,共享數據空間,該空間的大小以佔用最大的成員爲準
    int n;
    char ch;
    short m;
};
void main(){
    union data a;
    //定義一個共用體變量a
    printf("%d,%d",sizeof(a),sizeof(union data));
    a.n=0x40;
    printf("%d,%c,%d",a.n,a.ch,a.m);
    a.ch='9';
    printf("%d,%c,%d",a.n,a.ch,a.m);
    a.m=0x2059;
    printf("%d,%c,%d",a.n,a.ch,a.m);
    a.n=0x3E25AD54;
    printf("%d,%c,%d",a.n,a.ch,a.m);
    getchar();
}

3.5 內存佈局

3.6 內存佈局分析

要深刻理解爲何前面的案例輸出的結果,就須要剖析共用體在內存中是如和佈局的

  • 成員n,ch,m,在內存中"對齊"到一頭,對ch賦值修改的是前一個字節,對m賦值修改的是前兩個字節,對n賦值修改的是所有字節。也就是說,ch,m會影響到n的一部分數據,而n會影響到ch,m的所有數據
  • 上圖是在絕大多數PC機上的內存分佈狀況,若是是51單片機,狀況就會有所不一樣

3.7 最佳實踐

#include<stdio.h>
#define TOTAL 2//人員總數

//定義了一個結構體Person
union MYUNION{
    float score;
    char score;
    char course[30];
};
struct Person{
    char name[20];
    int num;
    char sex;
    char profession;
    union{
        float score;
        char course[20];
    }sc;//sc是一個共用體變量
};
void main(){
    int i;
    struct Person person[TOTAL];//定義了一個結構體數組
    //輸入人員信息
    for(i=0;i<TOTAL;i++){
        printf("input info:");
        scanf("%s %d %c %c",person[i].name,&(person[i].name),&(person[i].num),&(person[i].sex),&(person[i].profession));
        if(person[i].profession=='s'){
            printf("請輸入該學生成績:");
            scanf("%f",&person[i].sc.score);
        }else{
            printf("請輸入該老師課程:");
            scanf("%s",person[i].sc.course);
        }
        fflush(stdin);
    }
    //輸入人員信息
    printf("Name\t\tNum\tSex\tProfession\tScore\tCourse\n");
    for(i=0;i<TOTAL;i++){
        if(person[i].profession=='s'){
            printf("%s\t\t%d\t%c\t%c\t%c\t\t%f",persons[i].name,persons[i].num,persons[i].sex,persons[i],profession,persons[i].sc.score);
        }else{
            printf("%s\t\t%d\t%c\t\t%s",persons[i].name,persons[i].num,persons[i].sex,persons[i].profession,persons[i].sc.course);
        }
    }
    getchar();
    getchar();
}
相關文章
相關標籤/搜索