1 列舉型別

1 。 如果一個變數只有幾種可能的值,則可以定義為“列舉型別”;所謂“列舉”就是把可能的值一一的列舉出來,變數的值只限於列舉出來的值的範圍, 如:

語法:

enum

列舉型別

{

列舉成員列表

};

//其中的列舉成員列表是以逗號“,”相分隔

如:

enum

Spectrum

{

red

balck

yellow

blue

white

};

時間:2018-10-24 修改,Spectrum列舉變數中成員

balck

寫錯了,應為

black

。多謝 [福蔥] 讀者的提示!

enum Spectrum{red,balck,yellow,blue,white};

enum

Spectrum

{

red

black

yellow

blue

white

};

其中:

enum為關鍵字

Spectrum為該列舉型別的標記名

(標記名:遵循識別符號的命名規則);

花括號“

{}

”中的

red

black

yellow

blue

white稱為

“列舉元素”或“列舉常量”;

2。可以用“列舉型別”宣告符號名稱來表示int型常量。只要是能使用int型的地方就能夠使用列舉型別。注意:C語言中的列舉的一些特性不適合C++;比如c中的列舉變數允許使用++運算子,但是c++中則不允許。

3。有關列舉型別常量的預設值

這裡仍然拿上面的列舉型別常量作為示例:

enum

Spectrum

{

red

black

yellow

blue

white

};

0

1

2

3

4

預設情況下:該列舉列表中的常量值分別為:

0

1

2

3

4

當然也可以在列舉宣告中,可以為列舉常量指定整數值:如

enum

Spectrum

{

red

=

10

black

=

20

yellow

=

30

blue

=

40

white

=

50

};

也可以只對列舉型別中的一個列舉元素賦值;這時該列舉元素後面的列舉元素會被賦予後續的值。如:

enum

Spectrum

{

red

black

=

22

yellow

blue

white

};

則:

red

=

0

black

=

22

yellow

=

23

blue

=

24

white

=

25

此外,還可在列舉型別成員列表中,宣告多個成員的數值(整型常量值)相同, 如:

enum

Spectrum

{

red

black

=

22

yellow

blue

=

22

white

};

red

=

0

black

=

22

yellow

=

23

blue

=

22

white

=

23。

2018-04-26 07:04:01 補充

4。列舉型別也可以是匿名的

匿名的列舉型別會有著意想不到的作用,比如在程式中需要使用

數值的名字

的時候,常常有

3

種方法可以實現。

(1)宏定義

#define FALSE 0

#define TRUE 1

但是

宏定義

有弱點:其定義的只是預處理階段的名字,在編譯器的預處理階段會進行簡單的名字替換,而且不會進行型別的安全檢查,其作用域是全域性的 href=“

https://

blog。csdn。net/lixiaogan

g_theanswer/article/details/80140522

”>( C++11強列舉型別 ) ,因此若程式中有變數

true、false

,則會被替換。為了避免這樣的情況,採用將全部的宏用

大寫

來命名,以區別於正常的程式碼。

(2)匿名的

enum

列舉

enum

{

FALSE

TRUE

};

//FALSE 0, TRUE 1Text only

這裡的

FALSE,TRUE

都是編譯時期的名字,編譯器會對其進行型別檢查,若程式碼中其他地方有和該名字衝突的,會報錯。因此採用匿名的列舉不會有產生干擾正常程式碼的尷尬。

(3)採用靜態變數

C++中更加推薦使用該方式,如:

static

const

int

FALSE

=

0

static

const

int

TRUE

=

1

在這裡的

TRUE,FALSE

同樣會得到編譯器在編譯階段的檢查。由於是靜態變數,因此其作用域被限制到了本檔案內。相比於

enum

列舉型別,靜態變數不僅是編譯時期的名字,同時編譯器還可能會在程式碼中為

TRUE,FALSE

產生實際的資料,這會增加一點儲存空間。

5。列舉型別的作用:提高程式的可讀性和可維護性

示例程式碼一:輸出12個月的英文單詞

#include

#include

enum

Months

{

jan

=

1

feb

mar

apr

may

jun

jul

aug

sep

oct

nov

dec

};

int

main

void

{

enum

Months

m

//flag用來標記輸出的個數,若為4個,則輸出一個換行符

int

flag

=

0

//指標陣列,存放的是個字串的入口地址

char

*

months

[]

=

{

“January”

“February”

“March”

“April”

“May”

“June”

“July”

“August”

“September”

“October”

“November”

“December”

};

for

m

=

jan

m

<=

dec

m

++

{

printf

“%-d月份:%-10s ”

m

months

m

-

1

]);

flag

++

if

flag

%

4

==

0

{

putchar

‘\n’

);

}

}

system

“pause”

);

return

0

}

示例程式碼二:用作函式返回錯誤碼

這是在程式設計中使用得最為廣泛的用法之一,通常在開發中,我們把考慮到的所有可能出現的錯誤都列舉在一個enum中,這樣,我們就不用再函式調用出錯時候,返回一個數字。這樣的做法好處有很多:如更容易看出函式調用出錯的原因、如果enum中有漏掉的錯誤提示,則再新增一個等。

typedef

enum

{

/* Internal errors to rdkafka: */

RD_KAFKA_RESP_ERR__BEGIN

=

-

200

/* begin internal error codes */

RD_KAFKA_RESP_ERR__BAD_MSG

=

-

199

/* Received message is incorrect */

RD_KAFKA_RESP_ERR__BAD_COMPRESSION

=

-

198

/* Bad/unknown compression */

RD_KAFKA_RESP_ERR__DESTROY

=

-

197

/* Broker is going away */

RD_KAFKA_RESP_ERR__FAIL

=

-

196

/* Generic failure */

RD_KAFKA_RESP_ERR__TRANSPORT

=

-

195

/* Broker transport error */

RD_KAFKA_RESP_ERR__CRIT_SYS_RESOURCE

=

-

194

/* Critical system resource

* failure */

RD_KAFKA_RESP_ERR__RESOLVE

=

-

193

/* Failed to resolve broker */

RD_KAFKA_RESP_ERR__MSG_TIMED_OUT

=

-

192

/* Produced message timed out*/

RD_KAFKA_RESP_ERR__PARTITION_EOF

=

-

191

/* Reached the end of the

* topic+partition queue on

* the broker。

* Not really an error。 */

RD_KAFKA_RESP_ERR__UNKNOWN_PARTITION

=

-

190

/* Permanent:

* Partition does not

* exist in cluster。 */

RD_KAFKA_RESP_ERR__FS

=

-

189

/* File or filesystem error */

RD_KAFKA_RESP_ERR__UNKNOWN_TOPIC

=

-

188

/* Permanent:

* Topic does not exist

* in cluster。 */

RD_KAFKA_RESP_ERR__ALL_BROKERS_DOWN

=

-

187

/* All broker connections

* are down。 */

RD_KAFKA_RESP_ERR__INVALID_ARG

=

-

186

/* Invalid argument, or

* invalid configuration */

RD_KAFKA_RESP_ERR__TIMED_OUT

=

-

185

/* Operation timed out */

RD_KAFKA_RESP_ERR__QUEUE_FULL

=

-

184

/* Queue is full */

RD_KAFKA_RESP_ERR__ISR_INSUFF

=

-

183

/* ISR count < required。acks */

RD_KAFKA_RESP_ERR__END

=

-

100

/* end internal error codes */

/* Standard Kafka errors: */

RD_KAFKA_RESP_ERR_UNKNOWN

=

-

1

RD_KAFKA_RESP_ERR_NO_ERROR

=

0

RD_KAFKA_RESP_ERR_OFFSET_OUT_OF_RANGE

=

1

RD_KAFKA_RESP_ERR_INVALID_MSG

=

2

RD_KAFKA_RESP_ERR_UNKNOWN_TOPIC_OR_PART

=

3

RD_KAFKA_RESP_ERR_INVALID_MSG_SIZE

=

4

RD_KAFKA_RESP_ERR_LEADER_NOT_AVAILABLE

=

5

RD_KAFKA_RESP_ERR_NOT_LEADER_FOR_PARTITION

=

6

RD_KAFKA_RESP_ERR_REQUEST_TIMED_OUT

=

7

RD_KAFKA_RESP_ERR_BROKER_NOT_AVAILABLE

=

8

RD_KAFKA_RESP_ERR_REPLICA_NOT_AVAILABLE

=

9

RD_KAFKA_RESP_ERR_MSG_SIZE_TOO_LARGE

=

10

RD_KAFKA_RESP_ERR_STALE_CTRL_EPOCH

=

11

RD_KAFKA_RESP_ERR_OFFSET_METADATA_TOO_LARGE

=

12

}

rd_kafka_resp_err_t

上面的程式碼是 kafka C客戶端中的原始碼,即列舉出kafka 客戶端中可能會出現的錯誤的原因。通常,還會實現2個函式,如:

//1。返回便於人們閱讀的錯誤字串

const

char

*

rd_kafka_err2str

rd_kafka_resp_err_t

err

);

//該函式的實現很簡單,即以字串形式列印error,如:

const

char

*

rd_kafka_err2str

rd_kafka_resp_err_t

err

{

char

*

tempStr

=

NULL

//對err的判斷

switch

err

{

case

RD_KAFKA_RESP_ERR__BEGIN

tempStr

=

“RD_KAFKA_RESP_ERR__BEGIN”

break

//或: case RD_KAFKA_RESP_ERR__BEGIN: return “RD_KAFKA_RESP_ERR__BEGIN”;

//此處省略。。。。。

}

}

//2。若errnox錯誤碼在我們列舉出的enum中,則返回enum中的錯誤碼列印

rd_kafka_resp_err_t

rd_kafka_errno2err

int

errnox

);

一般在函式呼叫失敗的地方的日誌列印中,加入上面2個函式:先

rd_kafka_errno2err

,再

rd_kafka_err2str

如:

#include

#include

#include

using

namespace

std

enum

{

OPERATOR_OK

=

0

//成功

OPERATOR_ERR

=

1

//失敗

MALLOC_MEMORY_ERR

=

2

//申請記憶體空間失敗

FUNCTION_PARAM_NULL

=

3

//函式引數為空

FUNCTION_PARAM_ERR

=

4

//函式引數錯誤

//省略……

};

/**@fn Div

* @brief 除法函式

* @param[in] const int a 被除數

* @param[in] const int b 除數

* @param[out] int &outData 結果值

* @return int

**/

int

Div

const

int

a

const

int

b

int

&

outData

{

if

b

<=

0

{

fprintf

stderr

“Div param is err。”

);

return

FUNCTION_PARAM_ERR

}

outData

=

a

/

b

return

OPERATOR_OK

}

/**@fn err2str

* @brief 將錯誤碼轉換為對應字串

* @param[out] const int ierrno 待轉換的錯誤碼

* @return 轉換後的錯誤碼字串

**/

const

char

*

err2str

const

int

ierrno

{

if

OPERATOR_OK

>

ierrno

||

ierrno

>

FUNCTION_PARAM_ERR

{

puts

“err2str param is err。”

);

return

NULL

}

switch

ierrno

{

case

OPERATOR_OK

return

“OPERATOR_OK”

break

case

OPERATOR_ERR

return

“OPERATOR_ERR”

break

case

MALLOC_MEMORY_ERR

return

“MALLOC_MEMORY_ERR”

break

case

FUNCTION_PARAM_NULL

return

“FUNCTION_PARAM_NULL”

break

case

FUNCTION_PARAM_ERR

return

“FUNCTION_PARAM_ERR”

break

default

return

NULL

break

}

}

int

main

()

{

int

a

=

6

b

=

2

int

iResult

=

0

if

OPERATOR_OK

!=

Div

a

b

iResult

))

{

printf

“Div failed[%d]-[%s]

\n

Div

a

b

iResult

),

err2str

Div

a

b

iResult

)));

return

-

1

}

std

::

cout

<<

“Div: ”

<<

iResult

<<

std

::

endl

return

0

}

列印結果

Div

3

更多有關“

計算機原理&編譯原理、C/C++、PostgreSQL、資料結構&演算法等

”的技術文章將第一時間更新於公眾號:[

雅俗不共賞

]。