微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

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 <stdio.h>
#include <string.h>    // for strcmp(), strchr()
#include <stdbool.h>   // 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++不允许这样做,因为它把标记名和变量名都在相同的名称空间中。  

原文地址:https://www.jb51.cc/wenti/3279922.html

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐