您的位置:首页 > 编程语言 > C语言/C++

枚举---知识总结----------gyy加以整理以及改为C++方法

2014-03-11 13:51 459 查看
(一)

 

枚举类型的使用方法
1.
枚举的定义枚举类型定义的一般形式为: 
enum
枚举名{
枚举值表 };
在枚举值表中应罗列出所有可用值。这些值也称为枚举元素。
enum weekday{ sun,mou,tue,wed,thu,fri,sat };
 例如:该枚举名为weekday,枚举值共有7个,即一周中的七天。凡被说明为weekday类型变量的取值只能是七天中的某一天。 
2.
枚举变量的说明如同结构和联合一样,枚举变量也可用不同的方式说明,即先定义后说明,同时定义说明或直接说明。 
设有变量a,b,c被说明为上述的weekday,可采用下述任一种方式: 
enum weekday{ sun,mou,tue,wed,thu,fri,sat }; 
enum weekday a,b,c;
 或者为: enum weekday{ sun,mou,tue,wed,thu,fri,sat }a,b,c;
 或者为: enum { sun,mou,tue,wed,thu,fri,sat }a,b,c;
 3.枚举类型在使用中有以下规定:
 (1)枚举值是常量,不是变量。不能在程序中用赋值语句再对它赋值。
 例如对枚举weekday的元素再作以下赋值:
sun=5; mon=2; sun=mon; 都是错误的。
 (2)枚举元素本身由系统定义了一个表示序号的数值,从0开始顺序定义为0,1,2…。如在weekday中,sun值为0,mon值为1,…,sat值为6。
(3) 只能把枚举值赋予枚举变量,不能把元素的数值直接赋予枚举变量。
 enum weekday { sun,mon,tue,wed,thu,fri,sat } a,b,c;

a=sun;  b=mon;  c=tue;  //ok
a=0; b=1; //是错误的。如一定要把数值赋予枚举变量,则必须用强制类型转换。
 如: a=(enum weekday)2;
其意义是将顺序号为2的枚举元素赋予枚举变量a,相当于:
a=tue;
 还应该说明的是枚举元素不是字符常量也不是字符串常量,使用时不要加单、双引号。
 
 
 (二)

枚举类型的使用方法[转]

参考文献:

[1]C++程序设计语言(特别版),
裘宗燕译, 机械工业出版社
[2]C++ Primer (3rd Ed.), S.B. Lippman and J. Lajoie,
人民邮电出版社

 

1、 枚举enum的用途浅例
 写程序时,我们常常需要为某个对象关联一组可选alternative属性.例如,学生的成绩分A,B,C,D等,天气分sunny,
cloudy, rainy等等。
 更常见的,打开一个文件可能有三种状态:input, output和append.
典型做法是,对应定义3个常数,即:
 const int input = 1;

 const int output = 2;

 const int append = 3;
然后,调用以下函数:
 bool open_file(string file_name, int open_mode);
比如,
 open_file("Phenix_and_the_Crane", append);

 这种做法比较简单,但存在许多缺点,主要的一点就是无法限制传递给open_file函数的第2个参数的取值范围,只要传递int类型的值都是合法的。(当然,这样的情况下的应对措施就是在open_file函数内部判断第二个参数的取值,只有在1,2,3范围内才处理。)

 使用枚举能在一定程度上减轻这种尴尬(注1),它不但能实现类似于之前定义三个常量的功能,还能够将这三个值组合起来成为独一无二的组。例如:
 enum open_modes {input = 1, output, append};

 以上定义了open_modes为枚举类型enumeration type。每一个命名了的枚举都是唯一的类型,是一个类型标示器type specifier。例如,我们可以重新写一个open_file函数:

 bool open_file(string file_name, open_modes om);

 在open_modes枚举中,input, output, append称为枚举常量enumerator,
它们限定了open_modes定义的对象的取值范围。这个时候,调用open_file函数和之前的方法还是一模一样:
 open_file("Phenix_and_the_Crane", append);

 但是,如果传递给open_file的第二个参数不是open_modes枚举类型值的话(注1),那么编译器就会识别出错误;就算该参数取值等价于input,
output, append中的某个,

也一样会出错哦!例如:
 open_file("Phenix_and_the_Crane", 1);

 

总结:枚举类型的变量的赋值是受限的。
2、枚举的定义
 一个枚举是一个类型,可以保存一组由用户刻画的值。,枚举的使用很像一个整数类型。

枚举的定义具有以下形式,即以关键词enum开头,接着一个可选的枚举名,下来是由大括号{}包含着一个由逗号分隔的枚举常量列表enumerators
list:
 enum [enumeration name] {enumerator1[=value1], enumerator2[=value2], ...};

enum weather {sunny, cloudy, rainy, windy};

enum weather {sunny=1, cloudy, rainy, windy};
3
、枚举常量的类型和取值
 枚举常量的类型就是它所在的那个枚举,例如前面说到的open_modes枚举中,input,output和append等枚举常量的类型都是open_modes。这种做法,其实是为了赋予用户和编译器一些有关该变量拟议中的用途的提示。
 默认下,第一个枚举常量被赋值0,接下来的枚举常量取值是前面一个枚举常量的取值+1,例如:
 enum weather {sunny, cloudy, rainy, windy};
其中
 sunny == 0,

 cloudy == 1,

 rainy == 2,

 windy == 3;

 以上是默认情况,有时候我们希望显式地指定某个枚举常量的值,那么会出现什么情况呢?看看:
 enum some_fruit {apple = 3, orange, banana = 4, bear};

 好了,apple == 3, banana == 4;
那么orange和bear呢?记得前面说过一句,默认下”接下来的枚举常量取值是前面一个枚举常量的取值+1“。既然这两个枚举常量没有显式赋值,那么就按照默认规则办事,所以
orange == 4, bear == 5.

 从这个例子也可以看出,同一枚举中枚举常量的取值不需要唯一。这样有什么用处呢?下面是个简单的例子:
 enum some_big_cities {

 Guangzhou = 4,

 Shenzhen = 4,

 Hongkong = 4,

 Shanghai = 2,

 Beijing = 3,

 Chongqi = 3

 };
以上简单地按区域,将五个城市按照华南(4),华东(2),
华北(3)的几个城市分类了。

#include <iostream>

using namespace std;

 //华南(4),华东(2),
华北(3)

 enum some_big_cities {

 Guangzhou = 4,

 Shenzhen = 4,

 Hongkong = 4,

 Shanghai = 2,

 Beijing = 3,

 Chongqi = 3

 };

int main()

{some_big_cities s;

 s=Shenzhen;

 cout<<(s==4?"华南地区":"非华南地区")<<endl;

 return 0;

}

运行结果:华南地区
4、枚举变量的定义、初始化和赋值
 既然每个枚举都是一个类型,那么由这个类型自然可以声明变量,例如,由前面定义的some_big_cities:
 some_big_cities where_I_am;

 需要注意的是,在声明where_I_am时没有初始化,如果这时打印where_I_am的值:
 enum some_big_cities {

 Guangzhou = 4,

 Shenzhen = 4,

 Hongkong = 4,

 Shanghai = 2,

 Beijing = 3,

 Chongqi = 5};

int main(void)

{

 some_big_cities wh;

 cout<<"the value is: "<<wh<<endl;

 return 0;

}
输出将是the value is: 随机值.
然而,如果声明wh为全局变量,则另一种情况:
enum some_big_cities {Guangzhou = 1 Shenzhen = 1, Hongkong = 1,

 Shanghai = 2, Beijing = 3, Chongqi = 5};

some_big_cities wh;

int main(void)

{

 cout<<"the value is: "<<wh<<endl;

 return 0;

}
输出将是the value is: 0;

 定义一个枚举变量时,可以给它初始化,例如:
 some_big_cities wh = Guangzhou;

 注意等号右边只能取枚举常量中的某一个;特别地,以Guangzhou为例,虽然Guangzhou==4,
但以下初始化是出错的:
 some_big_cities wh = 4;

 error C2440: 'initializing' : cannot convert from 'int' to 'some_big_cities'
 可见,不能直接地把一个整型赋值给一个枚举变量,因为枚举和整型是不同类型的,除非显式转换。关于枚举与整型的关系,后面再讲。
 除了初始化,枚举变量也有赋值运算:
 some_big_cities wh;
 wh = Guangzhou;

 wh = Shanghai;
或者
 some_big_cities wh1 = Guangzhou;
 some_big_cities wh2 = Shanghai;
 wh2 = wh1;
5、枚举的取值范围
 如果某个枚举中所有枚举常量的值均非负,该枚举的表示范围就是[0:2^k-1],其中2^k是能使所有枚举常量都位于此范围内的最小的2的幂;如果存在负的枚举值,该枚举的取值范围就是[-2^k,2^k-1].例如:
 enum e1 {dark, light}; //范围0:1

 enum e3 {min = -10, max = 1000}; //范围-1024:1023
6、枚举与整型的关系
 整型值只能显式地转换成一个枚举值,但是,如果转换的结果位于该枚举取值范围之外,则结果是无定义的。
 enum e1 {dark = 1, light = 10};

 e1 VAR1 = e1(50); //无定义
 e1 VAR2 = e1(3); //编译通过
 在这里也说明了不允许隐式地从整型转换到枚举的原因,因为大部分整型值在特定的枚举里没有对应的表示。
 至于枚举可以当作特定的整型数来用的例子,从open_modes可以体会。
7、自定义运算符
 枚举是用户自定义类型,所以在用户可以为它定义自身的操作,例如++或者<<等。但是,在没有定义之前,不能因为枚举像整型就可以默认使用,例如:

 enum SomeCities

{

 zhanjiang,

 Maoming,

 Yangjiang,

 Jiangmen,

 Zhongshan

};

SomeCities oneCity;

for (oneCity = zhanjiang; oneCity != Zhongshan; ++oneCity)

{

 cout<<oneCity<<endl;

}

以上的++OneCity是没有定义的,在Visual C++ 6
编译下得到如下错误:
error C2675: unary '++' : 'enum main::SomeCities' does not define this operator or a conversion to a type acceptable to the predefined operator

8
、Sizeof
 一个枚举类型的sizeof就是某个能够容纳其范围的整型的sizeof,
而且不会大于sizeof(int), 除非某个枚举常量的值不能用int或者unsigned int来表示。
 在32位机器中,sizeof(int)一般等于4。前面介绍的所有枚举,例如,
enum SomeCities

{

 zhanjiang,

 Maoming,

 Yangjiang,

 Jiangmen,

 Zhongshan

};

计算其sizeof,可能是1,也可能是是4。在我的intel E2160双核、32位机器中,得到4。
-----------------------------------------------------------------------------------

[注1,
Begin]
由于通过将整型数显式转换就可能得到对应枚举类型的值,所以声明一个枚举来达到限制传递给函数的参数取值范围还是力不从心的,以下是一个例子:
enum SomeCities

{

zhanjiang=1, //1

Maoming, //2

Yangjiang, //3

Jiangmen, //4

Zhongshan = 1000 //1000

};

void printEnum(SomeCities sc)

{

cout<<sc<<endl;

}

int main(void)

{

SomeCities oneCity = SomeCities(50); //将50通过显式转换,为oneCity赋值
printEnum(oneCity); //在VC++ 6
编译器下得到50输出
return 0;

}

以上例子说明,虽然SomeCities的定义里没有赋值为50的枚举值,但是,由于50在该枚举的取值范围内,所以通过显式声明得到一个有定义的枚举值,从而成功传递给printEnum函数。
[注1,
End]

 

(三)

宏和枚举的区别

   宏和枚举之间的差别主要在作用的时期和存储的形式不同,宏是在预处理的阶段进行替换工作的,它替换代码段的文本,程序运行的过程中宏已不存在了。而枚举是在程序运行之后才起作用的,枚举常量存储在数据段的静态存储区里。宏占用代码段的空间,而枚举除了占用空间,还消耗CPU资源。

   但也不能就此说宏比枚举好,如果需要定义非常多的常量,用一条enum {.....}明显比一大堆define更清晰,枚举也可以用来定义一些特殊类型,比如Bool,

如: type enum {FALSE,TRUE} Bool;

  在程序中,可能需要为某些整数定义一个别名,我们可以利用预处理指令#define来完成这项工作,您的代码可能是:

#define MON  1

#define TUE   2

#define WED  3

#define THU   4

#define FRI    5

#define SAT   6

#define SUN   7

   在此,我们定义一种新的数据类型,希望它能完成同样的工作。这种新的数据类型叫枚举型。

1.
定义一种新的数据类型 -
枚举型

 以下代码定义了这种新的数据类型 -
枚举型

enum DAY

{

      MON=1, TUE, WED, THU, FRI, SAT, SUN

};

 

(1) 枚举型是一个集合,集合中的元素(枚举成员)是一些命名的整型常量,元素之间用逗号,隔开。

(2) DAY是一个标识符,可以看成这个集合的名字,是一个可选项,即是可有可无的项。

(3) 第一个枚举成员的默认值为整型的0,后续枚举成员的值在前一个成员上加1。

(4) 可以人为设定枚举成员的值,从而自定义某个范围内的整数。

(5) 枚举型是预处理指令#define的替代。

(6) 类型定义以分号;结束。

2.
使用枚举类型对变量进行声明

新的数据类型定义完成后,它就可以使用了。我们已经见过最基本的数据类型,如:整型int,
单精度浮点型float, 双精度浮点型double,
字符型char, 短整型short等等。用这些基本数据类型声明变量通常是这样:

char    a;  //变量a的类型均为字符型char

char    letter;

int   
  x, y, z;
//变量x,y和z的类型均为整型int

int      number;

double  m, n;

double  result;
//变量result的类型为双精度浮点型double

 

既然枚举也是一种数据类型,那么它和基本数据类型一样也可以对变量进行声明。

方法一:枚举类型的定义和变量的声明分开

enum DAY

{

      MON=1, TUE, WED, THU, FRI, SAT, SUN

};

DAY  yesterday;

DAY  today;

DAY  tomorrow;  //变量tomorrow的类型为枚举型DAY

DAY  good_day, bad_day;
 //变量good_day和bad_day的类型均为枚举型DAY

方法二:类型定义与变量声明同时进行:

enum //跟第一个定义不同的是,此处的标号DAY省略,这是允许的。

{

    saturday,

    sunday = 0,

    monday,

    tuesday,

    wednesday,

    thursday,

    friday

} workday;  //变量workday的类型为枚举型
DAY

enum week { Mon=1, Tue, Wed, Thu, Fri Sat, Sun} days;
//变量days的类型为枚举型enum
week

enum BOOLEAN { false, true } end_flag, match_flag;
//定义枚举类型并声明了两个枚举型变量

方法三:用typedef关键字将枚举类型定义成别名,并利用该别名进行变量声明:

typedef enum workday

{

    saturday,

    sunday = 0,

    monday,

    tuesday,

    wednesday,

    thursday,

    friday

} workday; //此处的workday为枚举型enum
workday的别名

workday today, tomorrow;
//变量today和tomorrow的类型为枚举型workday

enum workday中的workday可以省略:

typedef enum

{   saturday,

    sunday = 0,

    monday,

    tuesday,

    wednesday,

    thursday,

    friday

} workday;  //此处的workday为枚举型enum
workday的别名

workday today, tomorrow;
 //变量today和tomorrow的类型为枚举型workday

也可以用这种方式:

typedef enum workday

{   saturday,

    sunday = 0,

    monday,

    tuesday,

    wednesday,

    thursday,

    friday

};

workday today, tomorrow;
//变量today和tomorrow的类型为枚举型workday

注意:同一个程序中不能定义同名的枚举类型,不同的枚举类型中也不能存在同名的命名常量。错误示例如下所示:

错误声明一:存在同名的枚举类型

typedef enum

{

    wednesday,

    thursday,

    friday

} workday;

typedef enum WEEK

{

    saturday,

    sunday = 0,

    monday,

} workday;

错误声明二:存在同名的枚举成员

typedef enum

{

    wednesday,

    thursday,

    Friday,

Friday

} workday_1;

3.
使用枚举类型的变量

3.1
对枚举型的变量赋值。

实例将枚举类型的赋值与基本数据类型的赋值进行了对比:

方法一:先声明变量,再对变量赋值

#include <iostream>

using namespace std;

enum DAY { MON=1, TUE, WED, THU, FRI, SAT, SUN };

int main() {       

         DAY yesterday, today, tomorrow;   


         yesterday = MON;  


         today     = TUE;  


         tomorrow  = WED; 


    cout<<yesterday<<" "<<today<<" "<<tomorrow<<endl;

         return 0;

 }

方法二:声明变量的同时赋初值

#include <iostream>

using namespace std;

enum DAY { MON=1, TUE, WED, THU, FRI, SAT, SUN };

int main() {      


        
DAY yesterday = MON, today = TUE, tomorrow = WED;

    cout<<yesterday<<" "<<today<<" "<<tomorrow<<endl;

         return 0;

 }
        

方法三:定义类型的同时声明变量,然后对变量赋值。

#include <iostream>

using namespace std;

enum DAY { MON=1, TUE, WED, THU, FRI, SAT, SUN } yesterday, today, tomorrow;

int main() {      


         yesterday = MON;  


         today     = TUE;  


         tomorrow  = WED; 


cout<<yesterday<<" "<<today<<" "<<tomorrow<<endl;

         return 0;

 }

方法四:类型定义,变量声明,赋初值同时进行。

#include <iostream>

using namespace std;

enum DAY { MON=1, TUE, WED, THU, FRI, SAT, SUN } yesterday = MON, today = TUE, tomorrow = WED;

 int main() {      


         cout<<yesterday<<" "<<today<<" "<<tomorrow<<endl;

         return 0;

 }

3.2
对枚举型的变量赋整数值时,需要进行类型转换。

#include <iostream>

using namespace std;

enum DAY { MON=1, TUE, WED, THU, FRI, SAT, SUN };

 int main() { 


    enum DAY yesterday, today, tomorrow;

    yesterday = TUE;

    today = (enum DAY) (yesterday + 1);
//类型转换

    tomorrow = (enum DAY) 30;
//类型转换

 
  //tomorrow = 3; //错误

    cout<<yesterday<<" "<<today<<" "<<tomorrow<<endl;

        return 0;

 }

3.3
使用枚举型变量

#include <iostream>

using namespace std;

enum

{

    BELL = '\a',

    BACKSPACE = '\b',

    HTAB = '\t',

    RETURN = '\r',

    NEWLINE = '\n',

    VTAB = '\v',

    SPACE = ' '

};

enum BOOLEAN { FALSE = 0, TRUE } match_flag;

int main()

{

    int index = 0;

    int count_of_letter = 0;

    int count_of_space = 0;

    char str[] = "I'm Ely efod";

    match_flag = FALSE;

   for(; str[index] != '\0'; index++)

        if( SPACE != str[index] )

            count_of_letter++;

        else

        {

            match_flag = (enum BOOLEAN) 1;

            count_of_space++;

        }

   cout<<(match_flag ? "match" : "not match")<<" "<<count_of_space

<<" times"<<(char)NEWLINE;              

cout<<"count of letters:"<< count_of_letter<<(char)NEWLINE;

return 0;

}

输出:

match 2 times

count of letters: 10

4.
枚举类型与sizeof运算符

#include <iostream>

using namespace std;

enum escapes

{

    BELL      = '\a',

    BACKSPACE = '\b',

    HTAB      = '\t',

    RETURN    = '\r',

    NEWLINE   = '\n',

    VTAB      = '\v',

    SPACE     = ' '

};

enum BOOLEAN { FALSE = 0, TRUE } match_flag;

int main()

{

      cout<<sizeof(enum escapes)<<"bytes \n";//4 bytes 

      cout<<sizeof(escapes)<<"bytes \n";//4 bytes         

           cout<<sizeof(enum BOOLEAN)<<"bytes \n";//4 bytes           

      cout<<sizeof(BOOLEAN)<<"bytes \n";//4 bytes 

           cout<<sizeof(match_flag)<<"bytes \n";//4 bytes         

           cout<<sizeof(SPACE)<<"bytes \n";//4 bytes 

           cout<<sizeof(NEWLINE)<<"bytes \n";//4 bytes 

           cout<<sizeof(FALSE)<<"bytes \n";//4 bytes 

      cout<<sizeof(0)<<"bytes \n";//4 bytes

      return 0;



typedef   struct   weekday_st

{

        enum   week  {sun=123456789,mon,tue,wed,thu,fri,sat };

        enum   day   {monring,   moon,   aftermoon} ;

}weekday_st;

int   main(int   argc,   char   *argv[])

{

       cout<< "sizeof(weekday_st)= "<<sizeof(weekday_st)<<endl;

       cout<< "sizeof(weekday)="<<sizeof(weekday_st::week)<<edl;

       cout<< "sizeof(day)= "<<sizeof(weekday_st::day)<<endl;

        return   0;

}

sizeof(weekday_st)=1

sizeof(weekday)=4

sizeof(day)=4

cout<< "sizeof(weekday_st)= "<<sizeof(weekday_st)<<endl;

这里因为结构体里面并没有定义任何的变量

所以这个结构是空的,但是用sizeof进行运算的话也不能返回0

因为毕竟存在着这么一个东西

所以这时sizeof返回一个在机器里面所能表达的最小的存储单位的值

一般的PC里面最小的存储单位的值是char

所以sizeof返回1

 cout<< "sizeof(weekday)="<<sizeof(weekday_st::week)<<edl;

 cout<< "sizeof(day)= "<<sizeof(weekday_st::day)<<endl;

因为枚举量是当作整型常量来处理的

所以上面这两个sizeof都是返回4

 

这里的enum   week和enum   day只是内嵌“类型”,而不是成员变量,如果改成:

typedef   struct   weekday_st

{      

     enum   week  {sun=123456789,mon,tue,wed,thu,fri,sat }   ew;

     enum    day   {monring,   moon,   aftermoon}   ed;

}weekday_st;

sizeof(weekday_st)=8

sizeof(weekday)=4

sizeof(day)=4

 
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: