• C Primer Plus(6) 中文版 第14章 结构和其他数据形式 14.11 枚举类型


    14.11 枚举类型
    可以用枚举类型(enumerated type)声明符号名称来表示整型常量。使用enum关键字,可以创建一个新“类型”并指定它可具有的值(实际上,enum常量是int类型,因此,只要能使用int类型的地方就可以使用枚举类型)。枚举类型的目的是提高程序的可读性。它的语法与结构的语法相同。例如,可以这样声明:
    enum spectrum{red, orange, yellow, green, blue, violet};
    enum spectrum color;
    第1个声明创建了spetrum作为标记名,允许把enum spectrum作为一个类型名使用。第2个声明使color作为该类型的变量。第1个声明中花括号内的标识符枚举了spectrum变量可能有的值。因此,color可能的值是red、orange、yellow等。这些符号常量被称为枚举符(enumerator)。
    然后,便可这样用:
    int c;
    color = yellow;
    if( color == yellow )
        ...;
    for( color = red; color <= violet; color++ )
        ...;
    虽然枚举符是int类型,但是枚举变量可以是任意整数类型,前提是该整数类型可以存储枚举常量。例如,spectrum的枚举符范围是0~5,所以编译器可以用unsigned char来表示color常量。
    顺带一提,C枚举的一些特性并不适用于C++。例如,C允许枚举变量使用++运算符,但是C++标准不允许。所以,如果编写的代码将来会并入C++程序,那么必须把上面例子中的color声明为int类型,才能C和C++兼容。
    14.11.1 enum常量
    blue和read到底是什么?从技术层面看,它们是int类型的常量。例如,假定有前面的枚举声明,可以这样写:
    printf( "red = %d, orange = %d\n", red, orange );
    其输出如下:
    red = 0, orange = 1
    red成为一个由名称的常量,代表整数0。类似地,其他标识符都是由名称的常量,分别代表1~5。只要是能使用整型常量的地方就可以使用枚举常量。例如,在声明数组时,可以用枚举常量表示数组的大小;在switch语句中,可以把枚举常量作为标签。
    14.11.2 默认值
    默认情况下,枚举列表的常量都被赋予0、1、2等。因此,下面的声明中nina的值是3:
    enum kids {nippy, slats, skippy, nina, liz};
    14.11.3 赋值
    在枚举声明中,可以为枚举常量指定整数值:
    enum levels {
        low = 100, medium = 500, high = 2000
    }; 
    如果只给枚举常量赋值,没有对后面的枚举常量赋值,那么后面的常量会被赋予后续的值。例如,假设有如下的声明:
    enum feline {
        cat, lynx = 10, puma, tiger
    }; 
    那么cat的值是0(默认),lynx、puma和tiger的值分别是10、11、12。
    14.11.4 enum的用法
    枚举类型的目的是提高程序的可读性和可维护性。如果要处理颜色,使用red和blue比使用0和1更直观。注意,枚举类型只能在内部使用。如果要输入color中的orange的值,只能输入1,而不是单词orange。或者,让程序先读入字符串“orange”,再将其转换成orange代表的值。
    因为枚举类型是整数类型,所以可以在表达式中以使用整型变量的方式使用enum变量。它们用在case语句中很方便。
    程序清单14.15演示了一个使用enum的小程序。该程序示例使用默认值的方案,把red的值设置为0,使之成为指向字符串"red"的指针的索引。
    程序清单14.15 enum.c程序
    /* enum.c -- uses enumerated values */
    #include
    #include    // for strcmp(), strchr()
    #include   // C99 feature
    char * s_gets(char * st, int n);

    enum spectrum {red, orange, yellow, green, blue, violet};
    const char * colors[] = {"red", "orange", "yellow",
        "green", "blue", "violet"};
    #define LEN 30

    int main(void)
    {
        char choice[LEN];
        enum spectrum color;
        bool color_is_found = false;
        
        puts("Enter a color (empty line to quit):");
        while (s_gets(choice, LEN) != NULL && choice[0] != '\0')
        {
            for (color = red; color <= violet; color++)
            {
                if (strcmp(choice, colors[color]) == 0)
                {
                    color_is_found = true;
                    break;
                }
            }
            if (color_is_found)
                switch(color)
            {
                case red    : puts("Roses are red.");
                    break;
                case orange : puts("Poppies are orange.");
                    break;
                case yellow : puts("Sunflowers are yellow.");
                    break;
                case green  : puts("Grass is green.");
                    break;
                case blue   : puts("Bluebells are blue.");
                    break;
                case violet : puts("Violets are violet.");
                    break;
            }
            else
                printf("I don't know about the color %s.\n", choice);
            color_is_found = false;
            puts("Next color, please (empty line to quit):");
        }
        puts("Goodbye!");
        
        return 0;
    }

    char * s_gets(char * st, int n)
    {
        char * ret_val;
        char * find;
        
        ret_val = fgets(st, n, stdin);
        if (ret_val)
        {
            find = strchr(st, '\n');   // look for newline
            if (find)                  // if the address is not NULL,
                *find = '\0';          // place a null character there
            else
                while (getchar() != '\n')
                    continue;          // dispose of rest of line
        }
        return ret_val;
    }
    /* 输出:

    */

    14.11.5 共享名称空间
    C语言使用名称空间(namespace)标识程序中的各部分,即通过名称来识别。作用域时名称空间概念的一部分:两个不同作用域的同名变量不冲突;两个相同作用域的同名变量冲突。名称空间是分类别的。在特定作用域中的结构标记、联合标记和枚举标记的名称可以相同,不会引起冲突,但是不能在相同作用域中声明两个同名标签或同名变量。例如,在C中,下面的代码不会产生冲突:
    struct rect{
        double x, double y;
    }; 
    int rect; //在C中不会产生冲突
    尽管如此,以两种不同的方式使用相同的标记符会造成混乱。另外,C++不允许这样做,因为它把标记名和变量名都在相同的名称空间中。  

  • 相关阅读:
    微前端:quankun
    基于JAVA医院住院部管理计算机毕业设计源码+系统+数据库+lw文档+部署
    局部异常因子(Local Outlier Factor, LOF)算法详解及实验
    【Java后端】美团提前批一面和二面面经!
    JVM学习第一天
    大型网站技术架构 | 信息加密技术及密匙安全管理
    【云原生 | 拓展02】在单台宿主机上管理Docker容器
    beamManagement(三)connected mode DL Beam training
    在 Azure ML 上用 .NET 跑机器学习
    贪心算法——赶作业(C++)
  • 原文地址:https://blog.csdn.net/weixin_40186813/article/details/126515049