2020-12-19C/C++学习00
请注意,本文编写于 710 天前,最后修改于 704 天前,其中某些信息可能已经过时。

目录


c
定义一种类型stu可以放学生的姓名、学号、英语成绩,
其中英语成绩有的老师按照“A”、“B”、“C”、“D”、“F”五个等级给的,
有的老师按照百分制给的成绩,要求该类型可以如实反映学生的情况。

使用结构体

c
# include <string.h>
# include <stdio.h>
# include <stdlib.h>

# define TYPE_INT    0
# define TYPE_FLOAT  1
# define TYPE_CHAR   2
# define TYPE_TEXT   3

struct tagScore
{
    int nType;

    int nPoint;
    float fPoint;
    char cLevel;
    char szText[8];
};

void ShowScore(struct tagScore sc)
{
    switch(sc.nType)
    {
    case TYPE_INT:
        {
            printf("%d\r\n",sc.nPoint);
            break;
        }
    case TYPE_FLOAT:
        {
            printf("%f\r\n",sc.fPoint);
            break;
        }
    case TYPE_CHAR:
        {
            printf("%c\r\n",sc.cLevel);
            break;
        }
    case TYPE_TEXT:
        {
            printf("%s\r\n",sc.szText);
            break;
        }
    }
}

int main()
{
    struct tagScore sc1;
    struct tagScore sc2;
    struct tagScore sc3;
    struct tagScore sc4;

    sc1.nPoint = 89;
    sc1.nType = TYPE_INT;
    ShowScore(sc1);


    sc2.fPoint = 65.5f;
    sc2.nType = TYPE_FLOAT;
    ShowScore(sc2);


    sc3.cLevel = 'B';
    sc3.nType = TYPE_CHAR;
    ShowScore(sc3);


    strcpy(sc4.szText,"Good");
    sc4.nType = TYPE_TEXT;
    ShowScore(sc4);

    system("pause");
    return(0);
}

/*
以上代码可以发现结构体并不能节省空间,每次使用只是使用其中一个类型,其余类型都会被闲置,所以浪费空间
*/

优化一下

c
# include <string.h>
# include <stdio.h>
# include <stdlib.h>

# define TYPE_INT    0
# define TYPE_FLOAT  1
# define TYPE_CHAR   2
# define TYPE_TEXT   3

struct tagScore
{
    int nType;
    char szText[8];
};

void ShowScore(struct tagScore sc)
{
    switch(sc.nType)
    {
    case TYPE_INT:
        {
            printf("%d\r\n",*(int *)sc.szText);
            break;
        }
    case TYPE_FLOAT:
        {
            printf("%f\r\n",*(float *)sc.szText);
            break;
        }
    case TYPE_CHAR:
        {
            printf("%c\r\n",*(char *)sc.szText);
            break;
        }
    case TYPE_TEXT:
        {
            printf("%s\r\n",sc.szText);
            break;
        }
    }
}

int main()
{
    struct tagScore sc1;

    //同一地址放不同数据类型

    *(int *)sc1.szText = 89;
    sc1.nType = TYPE_INT;
    ShowScore(sc1);

    *(float *)sc1.szText = 65.5f;
    sc1.nType = TYPE_FLOAT;
    ShowScore(sc1);

    *(char *)sc1.szText = 'B';
    sc1.nType = TYPE_CHAR;
    ShowScore(sc1);

    strcpy(sc1.szText,"Good");
    sc1.nType = TYPE_TEXT;
    ShowScore(sc1);

    system("pause");
    return(0);
}
/*
    强转方式
*/

以上代码看起来非常繁琐,所以使用共用体解决

一、共用体

共用体(联合体)关键字union,语法定义类同struct。共用体所有成员共享使用同一段内存,成员名是解释此段内存的代号。手动实现就是强转指针类型取内容,而共用体是编译器对此实现提供了一种简易方式,同时也增加了可读性。

c
# include <string.h>
# include <stdio.h>
# include <stdlib.h>

# define TYPE_INT    0
# define TYPE_FLOAT  1
# define TYPE_CHAR   2
# define TYPE_TEXT   3

union unScore
{
    int nPoint;
    float fPoint;
    char cLevel;
    char szText[8];
};

struct tagScore
{
    int nType;
    union unScore uScore;
};

void ShowScore(struct tagScore sc)
{
    switch(sc.nType)
    {
    case TYPE_INT:
        {
            printf("%d\r\n",sc.uScore.nPoint);
            break;
        }
    case TYPE_FLOAT:
        {
            printf("%f\r\n",sc.uScore.fPoint);
            break;
        }
    case TYPE_CHAR:
        {
            printf("%c\r\n",sc.uScore.cLevel);
            break;
        }
    case TYPE_TEXT:
        {
            printf("%s\r\n",sc.uScore.szText);
            break;
        }
    }
}

int main()
{
    struct tagScore sc1;

    sc1.uScore.nPoint = 89;
    sc1.nType = TYPE_INT;
    ShowScore(sc1);

    sc1.uScore.fPoint = 65.5f;
    sc1.nType = TYPE_FLOAT;
    ShowScore(sc1);

    sc1.uScore.cLevel = 'B';
    sc1.nType = TYPE_CHAR;
    ShowScore(sc1);

    strcpy(sc1.uScore.szText,"Good");
    sc1.nType = TYPE_TEXT;
    ShowScore(sc1);

    system("pause");
    return(0);
}

私有

c
struct tagScore
{
    int nType;

    union unScore
    {
        int nPoint;
        float fPoint;
        char cLevel;
        char szText[8];
    }uScore;
};

此时如果要使用
可以通过层级访问

c
union tagScore::unScore uScore;

如果要设为彻底不让别人用

c
struct tagScore
{
    int nType;

    union //去掉名字
    {
        int nPoint;
        float fPoint;
        char cLevel;
        char szText[8];
    }uScore;
};

二、枚举类型

枚举关键字enum,成员间用逗号分隔,每个成员都是一个常量值。默认的如果不指定成员值,编译将第一个成员定义为0,后面的成员累加1,如果有成员数值被显示指定,那么后面没有指定的成员在指定值的基础上累加1。

  • 枚举与宏不同的一点,枚举类型限制符号化常量的范围,其值只能取定义者之一。

枚举实际上就是收到约束的宏

  1. 约束了枚举里面的值保证唯一
  2. 不能对枚举变量乱赋值,只能赋值为枚举常量之一
  3. 层级访问作用域
c
# include <string.h>
# include <stdio.h>
# include <stdlib.h>

union unScore
{
    int nPoint;
    float fPoint;
    char cLevel;
    char szText[8];
};

struct tagScore
{
    //如果要禁止其他人使用的话可以去掉eScoreType
    enum eScoreType
    {
        TYPE_INT,
        TYPE_FLOAT,
        TYPE_CHAR,
        TYPE_TEXT
    }nType;

    union
    {
        int nPoint;
        float fPoint;
        char cLevel;
        char szText[8];
    }uScore;
};

void ShowScore(struct tagScore sc)
{
    switch(sc.nType)
    {
    case tagScore::TYPE_INT:
        {
            printf("%d\r\n",sc.uScore.nPoint);
            break;
        }
    case tagScore::TYPE_FLOAT:
        {
            printf("%f\r\n",sc.uScore.fPoint);
            break;
        }
    case tagScore::TYPE_CHAR:
        {
            printf("%c\r\n",sc.uScore.cLevel);
            break;
        }
    case tagScore::TYPE_TEXT:
        {
            printf("%s\r\n",sc.uScore.szText);
            break;
        }
    }
}

int main()
{
    struct tagScore sc1;

    sc1.uScore.nPoint = 89;
    sc1.nType = tagScore::TYPE_INT;
    ShowScore(sc1);

    sc1.uScore.fPoint = 65.5f;
    sc1.nType =  tagScore::TYPE_FLOAT;
    ShowScore(sc1);

    sc1.uScore.cLevel = 'B';
    sc1.nType =  tagScore::TYPE_CHAR;
    ShowScore(sc1);

    strcpy(sc1.uScore.szText,"Good");
    sc1.nType =  tagScore::TYPE_TEXT;
    ShowScore(sc1);

    system("pause");
    return(0);
}

本文作者:Na1r

本文链接:

版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!